blob: 99d464f8846e6d39c4d76e03e00843e41435615e [file] [log] [blame]
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattner57540c52011-04-15 05:22:18 +000010// This provides Objective-C code generation targeting the Apple runtime.
Daniel Dunbar303e2c22008-08-11 02:45:11 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000015
Daniel Dunbar034299e2010-03-31 01:09:11 +000016#include "CGRecordLayout.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000017#include "CodeGenModule.h"
Daniel Dunbara94ecd22008-08-16 03:19:19 +000018#include "CodeGenFunction.h"
John McCallad7c5c12011-02-08 08:22:06 +000019#include "CGBlocks.h"
John McCalled1ae862011-01-28 11:13:47 +000020#include "CGCleanup.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000021#include "clang/AST/ASTContext.h"
Daniel Dunbar221fa942008-08-11 04:54:23 +000022#include "clang/AST/Decl.h"
Daniel Dunbarb036db82008-08-13 03:21:16 +000023#include "clang/AST/DeclObjC.h"
Anders Carlsson15b73de2009-07-18 19:43:29 +000024#include "clang/AST/RecordLayout.h"
Chris Lattnerf0b64d72009-04-26 01:32:48 +000025#include "clang/AST/StmtObjC.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000026#include "clang/Basic/LangOptions.h"
Chandler Carruth85098242010-06-15 23:19:56 +000027#include "clang/Frontend/CodeGenOptions.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000028
John McCall42227ed2010-07-31 23:20:56 +000029#include "llvm/InlineAsm.h"
30#include "llvm/IntrinsicInst.h"
Owen Andersonae86c192009-07-13 04:10:07 +000031#include "llvm/LLVMContext.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000032#include "llvm/Module.h"
Daniel Dunbarc475d422008-10-29 22:36:39 +000033#include "llvm/ADT/DenseSet.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000034#include "llvm/ADT/SetVector.h"
35#include "llvm/ADT/SmallString.h"
Fariborz Jahanian751c1e72009-12-12 21:26:21 +000036#include "llvm/ADT/SmallPtrSet.h"
John McCall5c08ab92010-07-13 22:12:14 +000037#include "llvm/Support/CallSite.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000038#include "llvm/Support/raw_ostream.h"
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +000039#include "llvm/Target/TargetData.h"
Torok Edwindb714922009-08-24 13:25:12 +000040#include <cstdio>
Daniel Dunbar303e2c22008-08-11 02:45:11 +000041
42using namespace clang;
Daniel Dunbar41cf9de2008-09-09 01:06:48 +000043using namespace CodeGen;
Daniel Dunbar303e2c22008-08-11 02:45:11 +000044
Daniel Dunbar9fd114d2009-04-22 07:32:20 +000045
Daniel Dunbar303e2c22008-08-11 02:45:11 +000046namespace {
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000047
Daniel Dunbar59e476b2009-08-03 17:06:42 +000048typedef std::vector<llvm::Constant*> ConstantVector;
Daniel Dunbareb1f9a22008-08-27 02:31:56 +000049
Daniel Dunbar59e476b2009-08-03 17:06:42 +000050// FIXME: We should find a nicer way to make the labels for metadata, string
51// concatenation is lame.
Daniel Dunbarb036db82008-08-13 03:21:16 +000052
Fariborz Jahanian279eda62009-01-21 22:04:16 +000053class ObjCCommonTypesHelper {
Owen Anderson170229f2009-07-14 23:10:40 +000054protected:
55 llvm::LLVMContext &VMContext;
Daniel Dunbar59e476b2009-08-03 17:06:42 +000056
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000057private:
John McCall9dc0db22011-05-15 01:53:33 +000058 // The types of these functions don't really matter because we
59 // should always bitcast before calling them.
60
61 /// id objc_msgSend (id, SEL, ...)
62 ///
63 /// The default messenger, used for sends whose ABI is unchanged from
64 /// the all-integer/pointer case.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000065 llvm::Constant *getMessageSendFn() const {
John McCall9dc0db22011-05-15 01:53:33 +000066 const llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
67 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
68 params, true),
69 "objc_msgSend");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000070 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000071
John McCall9dc0db22011-05-15 01:53:33 +000072 /// void objc_msgSend_stret (id, SEL, ...)
73 ///
74 /// The messenger used when the return value is an aggregate returned
75 /// by indirect reference in the first argument, and therefore the
76 /// self and selector parameters are shifted over by one.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000077 llvm::Constant *getMessageSendStretFn() const {
John McCall9dc0db22011-05-15 01:53:33 +000078 const llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
79 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
80 params, true),
81 "objc_msgSend_stret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000082
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000083 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000084
John McCall9dc0db22011-05-15 01:53:33 +000085 /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
86 ///
87 /// The messenger used when the return value is returned on the x87
88 /// floating-point stack; without a special entrypoint, the nil case
89 /// would be unbalanced.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000090 llvm::Constant *getMessageSendFpretFn() const {
John McCall9dc0db22011-05-15 01:53:33 +000091 const llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
92 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(
Owen Anderson41a75022009-08-13 21:57:51 +000093 llvm::Type::getDoubleTy(VMContext),
John McCall9dc0db22011-05-15 01:53:33 +000094 params, true),
95 "objc_msgSend_fpret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000096
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000097 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000098
John McCall9dc0db22011-05-15 01:53:33 +000099 /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
100 ///
101 /// The messenger used for super calls, which have different dispatch
102 /// semantics. The class passed is the superclass of the current
103 /// class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000104 llvm::Constant *getMessageSendSuperFn() const {
John McCall9dc0db22011-05-15 01:53:33 +0000105 const llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000106 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000107 params, true),
108 "objc_msgSendSuper");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000109 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000110
John McCall9dc0db22011-05-15 01:53:33 +0000111 /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
112 ///
113 /// A slightly different messenger used for super calls. The class
114 /// passed is the current class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000115 llvm::Constant *getMessageSendSuperFn2() const {
John McCall9dc0db22011-05-15 01:53:33 +0000116 const llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000117 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000118 params, true),
119 "objc_msgSendSuper2");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000120 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000121
John McCall9dc0db22011-05-15 01:53:33 +0000122 /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
123 /// SEL op, ...)
124 ///
125 /// The messenger used for super calls which return an aggregate indirectly.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000126 llvm::Constant *getMessageSendSuperStretFn() const {
John McCall9dc0db22011-05-15 01:53:33 +0000127 const llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000128 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000129 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000130 "objc_msgSendSuper_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000131 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000132
John McCall9dc0db22011-05-15 01:53:33 +0000133 /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
134 /// SEL op, ...)
135 ///
136 /// objc_msgSendSuper_stret with the super2 semantics.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000137 llvm::Constant *getMessageSendSuperStretFn2() const {
John McCall9dc0db22011-05-15 01:53:33 +0000138 const llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000139 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000140 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000141 "objc_msgSendSuper2_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000142 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000143
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000144 llvm::Constant *getMessageSendSuperFpretFn() const {
145 // There is no objc_msgSendSuper_fpret? How can that work?
146 return getMessageSendSuperFn();
147 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000148
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000149 llvm::Constant *getMessageSendSuperFpretFn2() const {
150 // There is no objc_msgSendSuper_fpret? How can that work?
151 return getMessageSendSuperFn2();
152 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000153
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000154protected:
155 CodeGen::CodeGenModule &CGM;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000156
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000157public:
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +0000158 const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000159 const llvm::Type *Int8PtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000160
Daniel Dunbar5d715592008-08-12 05:28:47 +0000161 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
162 const llvm::Type *ObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000163
Fariborz Jahanian406b1172008-11-18 20:18:11 +0000164 /// PtrObjectPtrTy - LLVM type for id *
165 const llvm::Type *PtrObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000166
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000167 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Daniel Dunbar5d715592008-08-12 05:28:47 +0000168 const llvm::Type *SelectorPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000169 /// ProtocolPtrTy - LLVM type for external protocol handles
170 /// (typeof(Protocol))
171 const llvm::Type *ExternalProtocolPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000172
Daniel Dunbarc722b852008-08-30 03:02:31 +0000173 // SuperCTy - clang type for struct objc_super.
174 QualType SuperCTy;
175 // SuperPtrCTy - clang type for struct objc_super *.
176 QualType SuperPtrCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000177
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000178 /// SuperTy - LLVM type for struct objc_super.
179 const llvm::StructType *SuperTy;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +0000180 /// SuperPtrTy - LLVM type for struct objc_super *.
181 const llvm::Type *SuperPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000182
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000183 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
184 /// in GCC parlance).
185 const llvm::StructType *PropertyTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000186
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000187 /// PropertyListTy - LLVM type for struct objc_property_list
188 /// (_prop_list_t in GCC parlance).
189 const llvm::StructType *PropertyListTy;
190 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
191 const llvm::Type *PropertyListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000192
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000193 // MethodTy - LLVM type for struct objc_method.
194 const llvm::StructType *MethodTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000195
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000196 /// CacheTy - LLVM type for struct objc_cache.
197 const llvm::Type *CacheTy;
198 /// CachePtrTy - LLVM type for struct objc_cache *.
199 const llvm::Type *CachePtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000200
Chris Lattnerce8754e2009-04-22 02:44:54 +0000201 llvm::Constant *getGetPropertyFn() {
202 CodeGen::CodeGenTypes &Types = CGM.getTypes();
203 ASTContext &Ctx = CGM.getContext();
204 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
John McCall2da83a32010-02-26 00:48:12 +0000205 llvm::SmallVector<CanQualType,4> Params;
206 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
207 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000208 Params.push_back(IdType);
209 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000210 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000211 Params.push_back(Ctx.BoolTy);
212 const llvm::FunctionType *FTy =
John McCallab26cfa2010-02-05 21:31:56 +0000213 Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000214 FunctionType::ExtInfo()),
215 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000216 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
217 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000218
Chris Lattnerce8754e2009-04-22 02:44:54 +0000219 llvm::Constant *getSetPropertyFn() {
220 CodeGen::CodeGenTypes &Types = CGM.getTypes();
221 ASTContext &Ctx = CGM.getContext();
222 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
John McCall2da83a32010-02-26 00:48:12 +0000223 llvm::SmallVector<CanQualType,6> Params;
224 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
225 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000226 Params.push_back(IdType);
227 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000228 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000229 Params.push_back(IdType);
230 Params.push_back(Ctx.BoolTy);
231 Params.push_back(Ctx.BoolTy);
232 const llvm::FunctionType *FTy =
John McCallab26cfa2010-02-05 21:31:56 +0000233 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000234 FunctionType::ExtInfo()),
235 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000236 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
237 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000238
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000239
240 llvm::Constant *getCopyStructFn() {
241 CodeGen::CodeGenTypes &Types = CGM.getTypes();
242 ASTContext &Ctx = CGM.getContext();
243 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
244 llvm::SmallVector<CanQualType,5> Params;
245 Params.push_back(Ctx.VoidPtrTy);
246 Params.push_back(Ctx.VoidPtrTy);
247 Params.push_back(Ctx.LongTy);
248 Params.push_back(Ctx.BoolTy);
249 Params.push_back(Ctx.BoolTy);
250 const llvm::FunctionType *FTy =
251 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
252 FunctionType::ExtInfo()),
253 false);
254 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
255 }
256
Chris Lattnerce8754e2009-04-22 02:44:54 +0000257 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000258 CodeGen::CodeGenTypes &Types = CGM.getTypes();
259 ASTContext &Ctx = CGM.getContext();
Chris Lattnerce8754e2009-04-22 02:44:54 +0000260 // void objc_enumerationMutation (id)
John McCall2da83a32010-02-26 00:48:12 +0000261 llvm::SmallVector<CanQualType,1> Params;
262 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000263 const llvm::FunctionType *FTy =
John McCallab26cfa2010-02-05 21:31:56 +0000264 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000265 FunctionType::ExtInfo()),
266 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000267 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
268 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000269
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000270 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattnerce8754e2009-04-22 02:44:54 +0000271 llvm::Constant *getGcReadWeakFn() {
272 // id objc_read_weak (id *)
John McCall9dc0db22011-05-15 01:53:33 +0000273 const llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000274 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000275 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000276 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000277 }
278
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000279 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000280 llvm::Constant *getGcAssignWeakFn() {
281 // id objc_assign_weak (id, id *)
John McCall9dc0db22011-05-15 01:53:33 +0000282 const llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000283 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000284 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000285 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
286 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000287
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000288 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000289 llvm::Constant *getGcAssignGlobalFn() {
290 // id objc_assign_global(id, id *)
John McCall9dc0db22011-05-15 01:53:33 +0000291 const llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000292 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000293 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000294 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
295 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000296
Fariborz Jahanian217af242010-07-20 20:30:03 +0000297 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
298 llvm::Constant *getGcAssignThreadLocalFn() {
299 // id objc_assign_threadlocal(id src, id * dest)
John McCall9dc0db22011-05-15 01:53:33 +0000300 const llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian217af242010-07-20 20:30:03 +0000301 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000302 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian217af242010-07-20 20:30:03 +0000303 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
304 }
305
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000306 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000307 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000308 // id objc_assign_ivar(id, id *, ptrdiff_t)
John McCall9dc0db22011-05-15 01:53:33 +0000309 const llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
310 CGM.PtrDiffTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000311 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000312 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000313 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
314 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000315
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000316 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
317 llvm::Constant *GcMemmoveCollectableFn() {
318 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
John McCall9dc0db22011-05-15 01:53:33 +0000319 const llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
320 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000321 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
322 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000323
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000324 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000325 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000326 // id objc_assign_strongCast(id, id *)
John McCall9dc0db22011-05-15 01:53:33 +0000327 const llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000328 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000329 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000330 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
331 }
Anders Carlsson9ab53d12009-02-16 22:59:18 +0000332
333 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000334 llvm::Constant *getExceptionThrowFn() {
335 // void objc_exception_throw(id)
John McCall9dc0db22011-05-15 01:53:33 +0000336 const llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000337 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000338 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000339 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
340 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000341
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000342 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
343 llvm::Constant *getExceptionRethrowFn() {
344 // void objc_exception_rethrow(void)
John McCall9dc0db22011-05-15 01:53:33 +0000345 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000346 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
347 }
348
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000349 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerdcceee72009-04-06 16:53:45 +0000350 llvm::Constant *getSyncEnterFn() {
351 // void objc_sync_enter (id)
John McCall9dc0db22011-05-15 01:53:33 +0000352 const llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerdcceee72009-04-06 16:53:45 +0000353 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000354 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000355 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
356 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000357
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000358 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000359 llvm::Constant *getSyncExitFn() {
360 // void objc_sync_exit (id)
John McCall9dc0db22011-05-15 01:53:33 +0000361 const llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000362 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000363 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000364 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
365 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000366
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000367 llvm::Constant *getSendFn(bool IsSuper) const {
368 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
369 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000370
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000371 llvm::Constant *getSendFn2(bool IsSuper) const {
372 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
373 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000374
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000375 llvm::Constant *getSendStretFn(bool IsSuper) const {
376 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
377 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000378
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000379 llvm::Constant *getSendStretFn2(bool IsSuper) const {
380 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
381 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000382
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000383 llvm::Constant *getSendFpretFn(bool IsSuper) const {
384 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
385 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000386
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000387 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
388 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
389 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000390
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000391 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
392 ~ObjCCommonTypesHelper(){}
393};
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000394
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000395/// ObjCTypesHelper - Helper class that encapsulates lazy
396/// construction of varies types used during ObjC generation.
397class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000398public:
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000399 /// SymtabTy - LLVM type for struct objc_symtab.
400 const llvm::StructType *SymtabTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000401 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
402 const llvm::Type *SymtabPtrTy;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000403 /// ModuleTy - LLVM type for struct objc_module.
404 const llvm::StructType *ModuleTy;
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000405
Daniel Dunbarb036db82008-08-13 03:21:16 +0000406 /// ProtocolTy - LLVM type for struct objc_protocol.
407 const llvm::StructType *ProtocolTy;
408 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
409 const llvm::Type *ProtocolPtrTy;
410 /// ProtocolExtensionTy - LLVM type for struct
411 /// objc_protocol_extension.
412 const llvm::StructType *ProtocolExtensionTy;
413 /// ProtocolExtensionTy - LLVM type for struct
414 /// objc_protocol_extension *.
415 const llvm::Type *ProtocolExtensionPtrTy;
416 /// MethodDescriptionTy - LLVM type for struct
417 /// objc_method_description.
418 const llvm::StructType *MethodDescriptionTy;
419 /// MethodDescriptionListTy - LLVM type for struct
420 /// objc_method_description_list.
421 const llvm::StructType *MethodDescriptionListTy;
422 /// MethodDescriptionListPtrTy - LLVM type for struct
423 /// objc_method_description_list *.
424 const llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000425 /// ProtocolListTy - LLVM type for struct objc_property_list.
426 const llvm::Type *ProtocolListTy;
427 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
428 const llvm::Type *ProtocolListPtrTy;
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000429 /// CategoryTy - LLVM type for struct objc_category.
430 const llvm::StructType *CategoryTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000431 /// ClassTy - LLVM type for struct objc_class.
432 const llvm::StructType *ClassTy;
433 /// ClassPtrTy - LLVM type for struct objc_class *.
434 const llvm::Type *ClassPtrTy;
435 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
436 const llvm::StructType *ClassExtensionTy;
437 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
438 const llvm::Type *ClassExtensionPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000439 // IvarTy - LLVM type for struct objc_ivar.
440 const llvm::StructType *IvarTy;
441 /// IvarListTy - LLVM type for struct objc_ivar_list.
442 const llvm::Type *IvarListTy;
443 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
444 const llvm::Type *IvarListPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000445 /// MethodListTy - LLVM type for struct objc_method_list.
446 const llvm::Type *MethodListTy;
447 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
448 const llvm::Type *MethodListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000449
Anders Carlsson9ff22482008-09-09 10:10:21 +0000450 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
451 const llvm::Type *ExceptionDataTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000452
Anders Carlsson9ff22482008-09-09 10:10:21 +0000453 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000454 llvm::Constant *getExceptionTryEnterFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000455 const llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000456 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000457 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000458 "objc_exception_try_enter");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000459 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000460
461 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000462 llvm::Constant *getExceptionTryExitFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000463 const llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000464 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000465 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000466 "objc_exception_try_exit");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000467 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000468
469 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000470 llvm::Constant *getExceptionExtractFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000471 const llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000472 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000473 params, false),
Chris Lattnerc6406db2009-04-22 02:26:14 +0000474 "objc_exception_extract");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000475 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000476
Anders Carlsson9ff22482008-09-09 10:10:21 +0000477 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000478 llvm::Constant *getExceptionMatchFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000479 const llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000480 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000481 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000482 "objc_exception_match");
483
Chris Lattnerc6406db2009-04-22 02:26:14 +0000484 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000485
Anders Carlsson9ff22482008-09-09 10:10:21 +0000486 /// SetJmpFn - LLVM _setjmp function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000487 llvm::Constant *getSetJmpFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000488 // This is specifically the prototype for x86.
489 const llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
490 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty,
491 params, false),
492 "_setjmp");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000493 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000494
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000495public:
496 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000497 ~ObjCTypesHelper() {}
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000498};
499
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000500/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000501/// modern abi
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000502class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000503public:
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000504
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000505 // MethodListnfABITy - LLVM for struct _method_list_t
506 const llvm::StructType *MethodListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000507
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000508 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
509 const llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000510
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000511 // ProtocolnfABITy = LLVM for struct _protocol_t
512 const llvm::StructType *ProtocolnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000513
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000514 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
515 const llvm::Type *ProtocolnfABIPtrTy;
516
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000517 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
518 const llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000519
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000520 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
521 const llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000522
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000523 // ClassnfABITy - LLVM for struct _class_t
524 const llvm::StructType *ClassnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000525
Fariborz Jahanian71394042009-01-23 23:53:38 +0000526 // ClassnfABIPtrTy - LLVM for struct _class_t*
527 const llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000528
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000529 // IvarnfABITy - LLVM for struct _ivar_t
530 const llvm::StructType *IvarnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000531
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000532 // IvarListnfABITy - LLVM for struct _ivar_list_t
533 const llvm::StructType *IvarListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000534
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000535 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
536 const llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000537
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000538 // ClassRonfABITy - LLVM for struct _class_ro_t
539 const llvm::StructType *ClassRonfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000540
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000541 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
542 const llvm::Type *ImpnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000543
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000544 // CategorynfABITy - LLVM for struct _category_t
545 const llvm::StructType *CategorynfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000546
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000547 // New types for nonfragile abi messaging.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000548
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000549 // MessageRefTy - LLVM for:
550 // struct _message_ref_t {
551 // IMP messenger;
552 // SEL name;
553 // };
554 const llvm::StructType *MessageRefTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000555 // MessageRefCTy - clang type for struct _message_ref_t
556 QualType MessageRefCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000557
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000558 // MessageRefPtrTy - LLVM for struct _message_ref_t*
559 const llvm::Type *MessageRefPtrTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000560 // MessageRefCPtrTy - clang type for struct _message_ref_t*
561 QualType MessageRefCPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000562
Fariborz Jahanian4e87c832009-02-05 01:13:09 +0000563 // MessengerTy - Type of the messenger (shown as IMP above)
564 const llvm::FunctionType *MessengerTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000565
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000566 // SuperMessageRefTy - LLVM for:
567 // struct _super_message_ref_t {
568 // SUPER_IMP messenger;
569 // SEL name;
570 // };
571 const llvm::StructType *SuperMessageRefTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000572
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000573 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
574 const llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000575
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000576 llvm::Constant *getMessageSendFixupFn() {
577 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
John McCall9dc0db22011-05-15 01:53:33 +0000578 const llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000579 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000580 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000581 "objc_msgSend_fixup");
582 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000583
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000584 llvm::Constant *getMessageSendFpretFixupFn() {
585 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
John McCall9dc0db22011-05-15 01:53:33 +0000586 const llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000587 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000588 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000589 "objc_msgSend_fpret_fixup");
590 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000591
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000592 llvm::Constant *getMessageSendStretFixupFn() {
593 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
John McCall9dc0db22011-05-15 01:53:33 +0000594 const llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000595 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000596 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000597 "objc_msgSend_stret_fixup");
598 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000599
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000600 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000601 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000602 // struct _super_message_ref_t*, ...)
John McCall9dc0db22011-05-15 01:53:33 +0000603 const llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000604 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000605 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000606 "objc_msgSendSuper2_fixup");
607 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000608
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000609 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000610 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000611 // struct _super_message_ref_t*, ...)
John McCall9dc0db22011-05-15 01:53:33 +0000612 const llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000613 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000614 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000615 "objc_msgSendSuper2_stret_fixup");
616 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000617
Chris Lattnera7c00b42009-04-22 02:15:23 +0000618 llvm::Constant *getObjCEndCatchFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000619 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000620 "objc_end_catch");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000621
Chris Lattnera7c00b42009-04-22 02:15:23 +0000622 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000623
Chris Lattnera7c00b42009-04-22 02:15:23 +0000624 llvm::Constant *getObjCBeginCatchFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000625 const llvm::Type *params[] = { Int8PtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000626 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000627 params, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000628 "objc_begin_catch");
629 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +0000630
631 const llvm::StructType *EHTypeTy;
632 const llvm::Type *EHTypePtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000633
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000634 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
635 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000636};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000637
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000638class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000639public:
640 // FIXME - accessibility
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000641 class GC_IVAR {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +0000642 public:
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000643 unsigned ivar_bytepos;
644 unsigned ivar_size;
645 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000646 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar22b0ada2009-04-23 01:29:05 +0000647
648 // Allow sorting based on byte pos.
649 bool operator<(const GC_IVAR &b) const {
650 return ivar_bytepos < b.ivar_bytepos;
651 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000652 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000653
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000654 class SKIP_SCAN {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000655 public:
656 unsigned skip;
657 unsigned scan;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000658 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000659 : skip(_skip), scan(_scan) {}
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000660 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000661
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000662protected:
663 CodeGen::CodeGenModule &CGM;
Owen Andersonae86c192009-07-13 04:10:07 +0000664 llvm::LLVMContext &VMContext;
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000665 // FIXME! May not be needing this after all.
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000666 unsigned ObjCABI;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000667
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000668 // gc ivar layout bitmap calculation helper caches.
669 llvm::SmallVector<GC_IVAR, 16> SkipIvars;
670 llvm::SmallVector<GC_IVAR, 16> IvarsInfo;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000671
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000672 /// LazySymbols - Symbols to generate a lazy reference for. See
673 /// DefinedSymbols and FinishModule().
Daniel Dunbard027a922009-09-07 00:20:42 +0000674 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000675
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000676 /// DefinedSymbols - External symbols which are defined by this
677 /// module. The symbols in this list and LazySymbols are used to add
678 /// special linker symbols which ensure that Objective-C modules are
679 /// linked properly.
Daniel Dunbard027a922009-09-07 00:20:42 +0000680 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000681
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000682 /// ClassNames - uniqued class names.
Daniel Dunbarb036db82008-08-13 03:21:16 +0000683 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000684
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000685 /// MethodVarNames - uniqued method variable names.
686 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000687
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000688 /// DefinedCategoryNames - list of category names in form Class_Category.
689 llvm::SetVector<std::string> DefinedCategoryNames;
690
Daniel Dunbarb036db82008-08-13 03:21:16 +0000691 /// MethodVarTypes - uniqued method type signatures. We have to use
692 /// a StringMap here because have no other unique reference.
693 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000694
Daniel Dunbar3c76cb52008-08-26 21:51:14 +0000695 /// MethodDefinitions - map of methods which have been defined in
696 /// this translation unit.
697 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000698
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000699 /// PropertyNames - uniqued method variable names.
700 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000701
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000702 /// ClassReferences - uniqued class references.
703 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000704
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000705 /// SelectorReferences - uniqued selector references.
706 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000707
Daniel Dunbarb036db82008-08-13 03:21:16 +0000708 /// Protocols - Protocols for which an objc_protocol structure has
709 /// been emitted. Forward declarations are handled by creating an
710 /// empty structure whose initializer is filled in when/if defined.
711 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000712
Daniel Dunbarc475d422008-10-29 22:36:39 +0000713 /// DefinedProtocols - Protocols which have actually been
714 /// defined. We should not need this, see FIXME in GenerateProtocol.
715 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000716
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000717 /// DefinedClasses - List of defined classes.
718 std::vector<llvm::GlobalValue*> DefinedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000719
720 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
721 std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000722
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000723 /// DefinedCategories - List of defined categories.
724 std::vector<llvm::GlobalValue*> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000725
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000726 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
727 std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000728
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000729 /// GetNameForMethod - Return a name for the given method.
730 /// \param[out] NameOut - The return value.
731 void GetNameForMethod(const ObjCMethodDecl *OMD,
732 const ObjCContainerDecl *CD,
Daniel Dunbard2386812009-10-19 01:21:19 +0000733 llvm::SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000734
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000735 /// GetMethodVarName - Return a unique constant for the given
736 /// selector's name. The return value has type char *.
737 llvm::Constant *GetMethodVarName(Selector Sel);
738 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000739
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000740 /// GetMethodVarType - Return a unique constant for the given
741 /// selector's name. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000742
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000743 // FIXME: This is a horrible name.
744 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000745 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000746
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000747 /// GetPropertyName - Return a unique constant for the given
748 /// name. The return value has type char *.
749 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000750
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000751 // FIXME: This can be dropped once string functions are unified.
752 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
753 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000754
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000755 /// GetClassName - Return a unique constant for the given selector's
756 /// name. The return value has type char *.
757 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000758
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000759 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
760
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000761 /// BuildIvarLayout - Builds ivar layout bitmap for the class
762 /// implementation for the __strong or __weak case.
763 ///
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000764 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
765 bool ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +0000766
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +0000767 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000768
Daniel Dunbar15bd8882009-05-03 14:10:34 +0000769 void BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000770 unsigned int BytePos, bool ForStrongLayout,
771 bool &HasUnion);
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +0000772 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000773 const llvm::StructLayout *Layout,
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000774 const RecordDecl *RD,
Chris Lattner5b36ddb2009-03-31 08:48:01 +0000775 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000776 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahaniana123b642009-04-24 16:17:09 +0000777 bool &HasUnion);
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000778
Fariborz Jahanian01dff422009-03-05 19:17:31 +0000779 /// GetIvarLayoutName - Returns a unique constant for the given
780 /// ivar layout bitmap.
781 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
782 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000783
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000784 /// EmitPropertyList - Emit the given property list. The return
785 /// value has type PropertyListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +0000786 llvm::Constant *EmitPropertyList(llvm::Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000787 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000788 const ObjCContainerDecl *OCD,
789 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000790
Fariborz Jahanian751c1e72009-12-12 21:26:21 +0000791 /// PushProtocolProperties - Push protocol's property on the input stack.
792 void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
793 std::vector<llvm::Constant*> &Properties,
794 const Decl *Container,
795 const ObjCProtocolDecl *PROTO,
796 const ObjCCommonTypesHelper &ObjCTypes);
797
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000798 /// GetProtocolRef - Return a reference to the internal protocol
799 /// description, creating an empty one if it has not been
800 /// defined. The return value has type ProtocolPtrTy.
801 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +0000802
Daniel Dunbar30c65362009-03-09 20:09:19 +0000803 /// CreateMetadataVar - Create a global variable with internal
804 /// linkage for use by the Objective-C runtime.
805 ///
806 /// This is a convenience wrapper which not only creates the
807 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +0000808 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +0000809 ///
810 /// \param Name - The variable name.
811 /// \param Init - The variable initializer; this is also used to
812 /// define the type of the variable.
813 /// \param Section - The section the variable should go into, or 0.
814 /// \param Align - The alignment for the variable, or 0.
815 /// \param AddToUsed - Whether the variable should be added to
Daniel Dunbar4527d302009-04-14 17:42:51 +0000816 /// "llvm.used".
Daniel Dunbar349e6fb2009-10-18 20:48:59 +0000817 llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +0000818 llvm::Constant *Init,
819 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +0000820 unsigned Align,
821 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +0000822
John McCall9e8bb002011-05-14 03:10:52 +0000823 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
824 ReturnValueSlot Return,
825 QualType ResultType,
826 llvm::Value *Sel,
827 llvm::Value *Arg0,
828 QualType Arg0Ty,
829 bool IsSuper,
830 const CallArgList &CallArgs,
831 const ObjCMethodDecl *OMD,
832 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000833
Daniel Dunbar5e639272010-04-25 20:39:01 +0000834 /// EmitImageInfo - Emit the image info marker used to encode some module
835 /// level information.
836 void EmitImageInfo();
837
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000838public:
Owen Andersonae86c192009-07-13 04:10:07 +0000839 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
Mike Stump11289f42009-09-09 15:08:12 +0000840 CGM(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000841
David Chisnall481e3a82010-01-23 02:40:42 +0000842 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000843
Fariborz Jahanian99113fd2009-01-26 21:38:32 +0000844 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
845 const ObjCContainerDecl *CD=0);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000846
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000847 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000848
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000849 /// GetOrEmitProtocol - Get the protocol object for the given
850 /// declaration, emitting it if necessary. The return value has type
851 /// ProtocolPtrTy.
852 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000853
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000854 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
855 /// object for the given declaration, emitting it if needed. These
856 /// forward references will be filled in with empty bodies if no
857 /// definition is seen. The return value has type ProtocolPtrTy.
858 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCall351762c2011-02-07 10:33:21 +0000859 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
860 const CGBlockInfo &blockInfo);
Fariborz Jahanianc05349e2010-08-04 16:57:49 +0000861
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000862};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000863
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000864class CGObjCMac : public CGObjCCommonMac {
865private:
866 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +0000867
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000868 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000869 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000870 void EmitModuleInfo();
871
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000872 /// EmitModuleSymols - Emit module symbols, the list of defined
873 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000874 llvm::Constant *EmitModuleSymbols();
875
Daniel Dunbar3ad53482008-08-11 21:35:06 +0000876 /// FinishModule - Write out global data structures at the end of
877 /// processing a translation unit.
878 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +0000879
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000880 /// EmitClassExtension - Generate the class extension structure used
881 /// to store the weak ivar layout and properties. The return value
882 /// has type ClassExtensionPtrTy.
883 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
884
885 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
886 /// for the given class.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000887 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000888 const ObjCInterfaceDecl *ID);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +0000889
890 /// EmitSuperClassRef - Emits reference to class's main metadata class.
891 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000892
893 /// EmitIvarList - Emit the ivar list for the given
894 /// implementation. If ForClass is true the list of class ivars
895 /// (i.e. metaclass ivars) is emitted, otherwise the list of
896 /// interface ivars will be emitted. The return value has type
897 /// IvarListPtrTy.
898 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +0000899 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000900
Daniel Dunbarca8531a2008-08-25 08:19:24 +0000901 /// EmitMetaClass - Emit a forward reference to the class structure
902 /// for the metaclass of the given interface. The return value has
903 /// type ClassPtrTy.
904 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
905
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000906 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +0000907 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000908 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
909 llvm::Constant *Protocols,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000910 const ConstantVector &Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000911
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000912 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000913
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000914 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000915
916 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +0000917 /// implementation. The return value has type MethodListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +0000918 llvm::Constant *EmitMethodList(llvm::Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000919 const char *Section,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000920 const ConstantVector &Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000921
922 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000923 /// method declarations.
Daniel Dunbarb036db82008-08-13 03:21:16 +0000924 /// - TypeName: The name for the type containing the methods.
925 /// - IsProtocol: True iff these methods are for a protocol.
926 /// - ClassMethds: True iff these are class methods.
927 /// - Required: When true, only "required" methods are
928 /// listed. Similarly, when false only "optional" methods are
929 /// listed. For classes this should always be true.
930 /// - begin, end: The method list to output.
931 ///
932 /// The return value has type MethodDescriptionListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +0000933 llvm::Constant *EmitMethodDescList(llvm::Twine Name,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000934 const char *Section,
935 const ConstantVector &Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +0000936
Daniel Dunbarc475d422008-10-29 22:36:39 +0000937 /// GetOrEmitProtocol - Get the protocol object for the given
938 /// declaration, emitting it if necessary. The return value has type
939 /// ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000940 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +0000941
942 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
943 /// object for the given declaration, emitting it if needed. These
944 /// forward references will be filled in with empty bodies if no
945 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000946 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +0000947
Daniel Dunbarb036db82008-08-13 03:21:16 +0000948 /// EmitProtocolExtension - Generate the protocol extension
949 /// structure used to store optional instance and class methods, and
950 /// protocol properties. The return value has type
951 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000952 llvm::Constant *
953 EmitProtocolExtension(const ObjCProtocolDecl *PD,
954 const ConstantVector &OptInstanceMethods,
955 const ConstantVector &OptClassMethods);
Daniel Dunbarb036db82008-08-13 03:21:16 +0000956
957 /// EmitProtocolList - Generate the list of referenced
958 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +0000959 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +0000960 ObjCProtocolDecl::protocol_iterator begin,
961 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +0000962
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000963 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
964 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +0000965 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
966 bool lval=false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000967
968public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +0000969 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +0000970
Fariborz Jahanian71394042009-01-23 23:53:38 +0000971 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000972
Daniel Dunbar97db84c2008-08-23 03:46:30 +0000973 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +0000974 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +0000975 QualType ResultType,
976 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +0000977 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +0000978 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +0000979 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +0000980 const ObjCMethodDecl *Method);
Daniel Dunbar303e2c22008-08-11 02:45:11 +0000981
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000982 virtual CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +0000983 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +0000984 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +0000985 QualType ResultType,
986 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +0000987 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +0000988 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +0000989 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +0000990 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +0000991 const CallArgList &CallArgs,
992 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000993
Daniel Dunbarcb463852008-11-01 01:53:16 +0000994 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000995 const ObjCInterfaceDecl *ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +0000996
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +0000997 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
998 bool lval = false);
Fariborz Jahanianf3648b82009-05-05 21:36:57 +0000999
1000 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1001 /// untyped one.
1002 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1003 const ObjCMethodDecl *Method);
1004
John McCall2ca705e2010-07-24 00:37:23 +00001005 virtual llvm::Constant *GetEHType(QualType T);
1006
Daniel Dunbar92992502008-08-15 22:20:32 +00001007 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001008
Daniel Dunbar92992502008-08-15 22:20:32 +00001009 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001010
Daniel Dunbarcb463852008-11-01 01:53:16 +00001011 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00001012 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001013
Chris Lattnerd4808922009-03-22 21:03:39 +00001014 virtual llvm::Constant *GetPropertyGetFunction();
1015 virtual llvm::Constant *GetPropertySetFunction();
David Chisnall168b80f2010-12-26 22:13:16 +00001016 virtual llvm::Constant *GetGetStructFunction();
1017 virtual llvm::Constant *GetSetStructFunction();
Chris Lattnerd4808922009-03-22 21:03:39 +00001018 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001019
John McCallbd309292010-07-06 01:34:17 +00001020 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1021 const ObjCAtTryStmt &S);
1022 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1023 const ObjCAtSynchronizedStmt &S);
1024 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00001025 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1026 const ObjCAtThrowStmt &S);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001027 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001028 llvm::Value *AddrWeakObj);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001029 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001030 llvm::Value *src, llvm::Value *dst);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001031 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001032 llvm::Value *src, llvm::Value *dest,
1033 bool threadlocal = false);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00001034 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001035 llvm::Value *src, llvm::Value *dest,
1036 llvm::Value *ivarOffset);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001037 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1038 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001039 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1040 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001041 llvm::Value *size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001042
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001043 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1044 QualType ObjectTy,
1045 llvm::Value *BaseValue,
1046 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001047 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001048 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001049 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001050 const ObjCIvarDecl *Ivar);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001051
1052 /// GetClassGlobal - Return the global variable for the Objective-C
1053 /// class of the given name.
1054 virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) {
1055 assert(false && "CGObjCMac::GetClassGlobal");
1056 return 0;
1057 }
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001058};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001059
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001060class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001061private:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001062 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001063 llvm::GlobalVariable* ObjCEmptyCacheVar;
1064 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001065
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001066 /// SuperClassReferences - uniqued super class references.
1067 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001068
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001069 /// MetaClassReferences - uniqued meta class references.
1070 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001071
1072 /// EHTypeReferences - uniqued class ehtype references.
1073 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001074
John McCall9e8bb002011-05-14 03:10:52 +00001075 /// VTableDispatchMethods - List of methods for which we generate
1076 /// vtable-based message dispatch.
1077 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001078
Fariborz Jahanian67260552009-11-17 21:37:35 +00001079 /// DefinedMetaClasses - List of defined meta-classes.
1080 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1081
John McCall9e8bb002011-05-14 03:10:52 +00001082 /// isVTableDispatchedSelector - Returns true if SEL is a
1083 /// vtable-based selector.
1084 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001085
Fariborz Jahanian71394042009-01-23 23:53:38 +00001086 /// FinishNonFragileABIModule - Write out global data structures at the end of
1087 /// processing a translation unit.
1088 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001089
Daniel Dunbar19573e72009-05-15 21:48:48 +00001090 /// AddModuleClassList - Add the given list of class pointers to the
1091 /// module with the provided symbol and section names.
1092 void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container,
1093 const char *SymbolName,
1094 const char *SectionName);
1095
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001096 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1097 unsigned InstanceStart,
1098 unsigned InstanceSize,
1099 const ObjCImplementationDecl *ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001100 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001101 llvm::Constant *IsAGV,
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001102 llvm::Constant *SuperClassGV,
Fariborz Jahanian82208252009-01-31 00:59:10 +00001103 llvm::Constant *ClassRoGV,
1104 bool HiddenVisibility);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001105
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001106 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001107
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00001108 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001109
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001110 /// EmitMethodList - Emit the method list for the given
1111 /// implementation. The return value has type MethodListnfABITy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001112 llvm::Constant *EmitMethodList(llvm::Twine Name,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001113 const char *Section,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001114 const ConstantVector &Methods);
1115 /// EmitIvarList - Emit the ivar list for the given
1116 /// implementation. If ForClass is true the list of class ivars
1117 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1118 /// interface ivars will be emitted. The return value has type
1119 /// IvarListnfABIPtrTy.
1120 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001121
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001122 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001123 const ObjCIvarDecl *Ivar,
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00001124 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001125
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001126 /// GetOrEmitProtocol - Get the protocol object for the given
1127 /// declaration, emitting it if necessary. The return value has type
1128 /// ProtocolPtrTy.
1129 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001130
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001131 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1132 /// object for the given declaration, emitting it if needed. These
1133 /// forward references will be filled in with empty bodies if no
1134 /// definition is seen. The return value has type ProtocolPtrTy.
1135 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001136
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001137 /// EmitProtocolList - Generate the list of referenced
1138 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001139 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001140 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001141 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001142
John McCall9e8bb002011-05-14 03:10:52 +00001143 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1144 ReturnValueSlot Return,
1145 QualType ResultType,
1146 Selector Sel,
1147 llvm::Value *Receiver,
1148 QualType Arg0Ty,
1149 bool IsSuper,
1150 const CallArgList &CallArgs,
1151 const ObjCMethodDecl *Method);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001152
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001153 /// GetClassGlobal - Return the global variable for the Objective-C
1154 /// class of the given name.
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00001155 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001156
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001157 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001158 /// for the given class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001159 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001160 const ObjCInterfaceDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001161
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001162 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1163 /// for the given super class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001164 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1165 const ObjCInterfaceDecl *ID);
1166
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001167 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1168 /// meta-data
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001169 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001170 const ObjCInterfaceDecl *ID);
1171
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001172 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1173 /// the given ivar.
1174 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001175 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001176 const ObjCInterfaceDecl *ID,
1177 const ObjCIvarDecl *Ivar);
1178
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001179 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1180 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001181 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1182 bool lval=false);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001183
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001184 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001185 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001186 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001187 bool ForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001188
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001189 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar15894b72009-04-07 05:48:37 +00001190 return "OBJC_METACLASS_$_";
1191 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001192
Daniel Dunbar15894b72009-04-07 05:48:37 +00001193 const char *getClassSymbolPrefix() const {
1194 return "OBJC_CLASS_$_";
1195 }
1196
Daniel Dunbar961202372009-05-03 12:57:56 +00001197 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001198 uint32_t &InstanceStart,
1199 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001200
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001201 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001202 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001203 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1204 return CGM.getContext().Selectors.getSelector(0, &II);
1205 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001206
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001207 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001208 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1209 return CGM.getContext().Selectors.getSelector(1, &II);
1210 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001211
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001212 /// ImplementationIsNonLazy - Check whether the given category or
1213 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001214 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001215
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001216public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001217 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001218 // FIXME. All stubs for now!
1219 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001220
Fariborz Jahanian71394042009-01-23 23:53:38 +00001221 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001222 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001223 QualType ResultType,
1224 Selector Sel,
1225 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001226 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001227 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001228 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001229
1230 virtual CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001231 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001232 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001233 QualType ResultType,
1234 Selector Sel,
1235 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001236 bool isCategoryImpl,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001237 llvm::Value *Receiver,
1238 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001239 const CallArgList &CallArgs,
1240 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001241
Fariborz Jahanian71394042009-01-23 23:53:38 +00001242 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001243 const ObjCInterfaceDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001244
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001245 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1246 bool lvalue = false)
1247 { return EmitSelector(Builder, Sel, lvalue); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001248
1249 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1250 /// untyped one.
1251 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1252 const ObjCMethodDecl *Method)
1253 { return EmitSelector(Builder, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001254
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00001255 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001256
Fariborz Jahanian71394042009-01-23 23:53:38 +00001257 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001258 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian097feda2009-01-30 18:58:59 +00001259 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001260
John McCall2ca705e2010-07-24 00:37:23 +00001261 virtual llvm::Constant *GetEHType(QualType T);
1262
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001263 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001264 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001265 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001266 virtual llvm::Constant *GetPropertySetFunction() {
1267 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001268 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001269
David Chisnall168b80f2010-12-26 22:13:16 +00001270 virtual llvm::Constant *GetSetStructFunction() {
1271 return ObjCTypes.getCopyStructFn();
1272 }
1273 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001274 return ObjCTypes.getCopyStructFn();
1275 }
1276
Chris Lattnerd4808922009-03-22 21:03:39 +00001277 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001278 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001279 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001280
John McCallbd309292010-07-06 01:34:17 +00001281 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1282 const ObjCAtTryStmt &S);
1283 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1284 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001285 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlsson9ab53d12009-02-16 22:59:18 +00001286 const ObjCAtThrowStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001287 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001288 llvm::Value *AddrWeakObj);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001289 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001290 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001291 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001292 llvm::Value *src, llvm::Value *dest,
1293 bool threadlocal = false);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001294 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001295 llvm::Value *src, llvm::Value *dest,
1296 llvm::Value *ivarOffset);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001297 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001298 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001299 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1300 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001301 llvm::Value *size);
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001302 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1303 QualType ObjectTy,
1304 llvm::Value *BaseValue,
1305 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001306 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001307 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001308 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001309 const ObjCIvarDecl *Ivar);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001310};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001311
John McCall5880fb82011-05-14 21:12:11 +00001312/// A helper class for performing the null-initialization of a return
1313/// value.
1314struct NullReturnState {
1315 llvm::BasicBlock *NullBB;
1316
1317 NullReturnState() : NullBB(0) {}
1318
1319 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
1320 // Make blocks for the null-init and call edges.
1321 NullBB = CGF.createBasicBlock("msgSend.nullinit");
1322 llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
1323
1324 // Check for a null receiver and, if there is one, jump to the
1325 // null-init test.
1326 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1327 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1328
1329 // Otherwise, start performing the call.
1330 CGF.EmitBlock(callBB);
1331 }
1332
1333 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType) {
1334 if (!NullBB) return result;
1335
1336 // Finish the call path.
1337 llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont");
1338 if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB);
1339
1340 // Emit the null-init block and perform the null-initialization there.
1341 CGF.EmitBlock(NullBB);
1342 assert(result.isAggregate() && "null init of non-aggregate result?");
1343 CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
1344
1345 // Jump to the continuation block.
1346 CGF.EmitBlock(contBB);
1347
1348 return result;
1349 }
1350};
1351
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001352} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001353
1354/* *** Helper Functions *** */
1355
1356/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001357static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001358 llvm::Constant *C,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001359 unsigned idx0,
1360 unsigned idx1) {
1361 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001362 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1363 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001364 };
Owen Andersonade90fd2009-07-29 18:54:39 +00001365 return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001366}
1367
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001368/// hasObjCExceptionAttribute - Return true if this class or any super
1369/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001370static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001371 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001372 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001373 return true;
1374 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001375 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001376 return false;
1377}
1378
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001379/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001380
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001381CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001382 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001383 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001384 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001385}
1386
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001387/// GetClass - Return a reference to the class for the given interface
1388/// decl.
Daniel Dunbarcb463852008-11-01 01:53:16 +00001389llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001390 const ObjCInterfaceDecl *ID) {
1391 return EmitClassRef(Builder, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001392}
1393
1394/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001395llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1396 bool lval) {
1397 return EmitSelector(Builder, Sel, lval);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001398}
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001399llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001400 *Method) {
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001401 return EmitSelector(Builder, Method->getSelector());
1402}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001403
John McCall2ca705e2010-07-24 00:37:23 +00001404llvm::Constant *CGObjCMac::GetEHType(QualType T) {
1405 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
1406 return 0;
1407}
1408
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001409/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001410/*
1411 struct __builtin_CFString {
1412 const int *isa; // point to __CFConstantStringClassReference
1413 int flags;
1414 const char *str;
1415 long length;
1416 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001417*/
1418
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001419/// or Generate a constant NSString object.
1420/*
1421 struct __builtin_NSString {
1422 const int *isa; // point to __NSConstantStringClassReference
1423 const char *str;
1424 unsigned int length;
1425 };
1426*/
1427
Fariborz Jahanian71394042009-01-23 23:53:38 +00001428llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall481e3a82010-01-23 02:40:42 +00001429 const StringLiteral *SL) {
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001430 return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
1431 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian50c925f2010-10-19 17:19:29 +00001432 CGM.GetAddrOfConstantString(SL));
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001433}
1434
1435/// Generates a message send where the super is the receiver. This is
1436/// a message send to self with special delivery semantics indicating
1437/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001438CodeGen::RValue
1439CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001440 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001441 QualType ResultType,
1442 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001443 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001444 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001445 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001446 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001447 const CodeGen::CallArgList &CallArgs,
1448 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001449 // Create and init a super structure; this is a (receiver, class)
1450 // pair we will pass to objc_msgSendSuper.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001451 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00001452 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001453 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001454 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001455 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001456 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001457
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001458 // If this is a class message the metaclass is passed as the target.
1459 llvm::Value *Target;
1460 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001461 if (isCategoryImpl) {
1462 // Message sent to 'super' in a class method defined in a category
1463 // implementation requires an odd treatment.
1464 // If we are in a class method, we must retrieve the
1465 // _metaclass_ for the current class, pointed at by
1466 // the class's "isa" pointer. The following assumes that
1467 // isa" is the first ivar in a class (which it must be).
1468 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1469 Target = CGF.Builder.CreateStructGEP(Target, 0);
1470 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00001471 } else {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001472 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1473 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1474 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1475 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001476 }
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00001477 }
1478 else if (isCategoryImpl)
1479 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1480 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001481 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1482 ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1483 Target = CGF.Builder.CreateLoad(ClassPtr);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001484 }
Mike Stump18bb9282009-05-16 07:57:57 +00001485 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1486 // ObjCTypes types.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001487 const llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00001488 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00001489 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001490 CGF.Builder.CreateStore(Target,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001491 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall9e8bb002011-05-14 03:10:52 +00001492 return EmitMessageSend(CGF, Return, ResultType,
1493 EmitSelector(CGF.Builder, Sel),
1494 ObjCSuper, ObjCTypes.SuperPtrCTy,
1495 true, CallArgs, Method, ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001496}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001497
1498/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001499CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001500 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001501 QualType ResultType,
1502 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001503 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001504 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001505 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001506 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00001507 return EmitMessageSend(CGF, Return, ResultType,
1508 EmitSelector(CGF.Builder, Sel),
1509 Receiver, CGF.getContext().getObjCIdType(),
1510 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00001511}
1512
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001513CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00001514CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1515 ReturnValueSlot Return,
1516 QualType ResultType,
1517 llvm::Value *Sel,
1518 llvm::Value *Arg0,
1519 QualType Arg0Ty,
1520 bool IsSuper,
1521 const CallArgList &CallArgs,
1522 const ObjCMethodDecl *Method,
1523 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc722b852008-08-30 03:02:31 +00001524 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00001525 if (!IsSuper)
1526 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
Eli Friedman43dca6a2011-05-02 17:57:46 +00001527 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1528 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
Daniel Dunbarc722b852008-08-30 03:02:31 +00001529 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001530
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00001531 CodeGenTypes &Types = CGM.getTypes();
John McCallab26cfa2010-02-05 21:31:56 +00001532 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindolac50c27c2010-03-30 20:24:48 +00001533 FunctionType::ExtInfo());
Daniel Dunbardf0e62d2009-09-17 04:01:40 +00001534 const llvm::FunctionType *FTy =
1535 Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001536
Anders Carlsson280e61f12010-06-21 20:59:55 +00001537 if (Method)
1538 assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
1539 CGM.getContext().getCanonicalType(ResultType) &&
1540 "Result type mismatch!");
1541
John McCall5880fb82011-05-14 21:12:11 +00001542 NullReturnState nullReturn;
1543
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001544 llvm::Constant *Fn = NULL;
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001545 if (CGM.ReturnTypeUsesSRet(FnInfo)) {
John McCall5880fb82011-05-14 21:12:11 +00001546 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001547 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001548 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001549 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1550 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1551 : ObjCTypes.getSendFpretFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001552 } else {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001553 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001554 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001555 }
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001556 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
John McCall5880fb82011-05-14 21:12:11 +00001557 RValue rvalue = CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
1558 return nullReturn.complete(CGF, rvalue, ResultType);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001559}
1560
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001561static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1562 if (FQT.isObjCGCStrong())
1563 return Qualifiers::Strong;
1564
1565 if (FQT.isObjCGCWeak())
1566 return Qualifiers::Weak;
1567
1568 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1569 return Qualifiers::Strong;
1570
1571 if (const PointerType *PT = FQT->getAs<PointerType>())
1572 return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1573
1574 return Qualifiers::GCNone;
1575}
1576
John McCall351762c2011-02-07 10:33:21 +00001577llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1578 const CGBlockInfo &blockInfo) {
1579 llvm::Constant *nullPtr =
Fariborz Jahanianafa3c0a2010-08-04 18:44:59 +00001580 llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
John McCall351762c2011-02-07 10:33:21 +00001581
Fariborz Jahanian0aa35b92010-09-13 16:09:44 +00001582 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
John McCall351762c2011-02-07 10:33:21 +00001583 return nullPtr;
1584
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001585 bool hasUnion = false;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001586 SkipIvars.clear();
1587 IvarsInfo.clear();
1588 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
1589 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
1590
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00001591 // __isa is the first field in block descriptor and must assume by runtime's
1592 // convention that it is GC'able.
1593 IvarsInfo.push_back(GC_IVAR(0, 1));
John McCall351762c2011-02-07 10:33:21 +00001594
1595 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1596
1597 // Calculate the basic layout of the block structure.
1598 const llvm::StructLayout *layout =
1599 CGM.getTargetData().getStructLayout(blockInfo.StructureType);
1600
1601 // Ignore the optional 'this' capture: C++ objects are not assumed
1602 // to be GC'ed.
1603
1604 // Walk the captured variables.
1605 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1606 ce = blockDecl->capture_end(); ci != ce; ++ci) {
1607 const VarDecl *variable = ci->getVariable();
1608 QualType type = variable->getType();
1609
1610 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1611
1612 // Ignore constant captures.
1613 if (capture.isConstant()) continue;
1614
1615 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
1616
1617 // __block variables are passed by their descriptor address.
1618 if (ci->isByRef()) {
1619 IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00001620 continue;
John McCall351762c2011-02-07 10:33:21 +00001621 }
1622
1623 assert(!type->isArrayType() && "array variable should not be caught");
1624 if (const RecordType *record = type->getAs<RecordType>()) {
1625 BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00001626 continue;
1627 }
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001628
John McCall351762c2011-02-07 10:33:21 +00001629 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
1630 unsigned fieldSize = CGM.getContext().getTypeSize(type);
1631
1632 if (GCAttr == Qualifiers::Strong)
1633 IvarsInfo.push_back(GC_IVAR(fieldOffset,
1634 fieldSize / WordSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001635 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
John McCall351762c2011-02-07 10:33:21 +00001636 SkipIvars.push_back(GC_IVAR(fieldOffset,
1637 fieldSize / ByteSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001638 }
1639
1640 if (IvarsInfo.empty())
John McCall351762c2011-02-07 10:33:21 +00001641 return nullPtr;
1642
1643 // Sort on byte position; captures might not be allocated in order,
1644 // and unions can do funny things.
1645 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
1646 llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001647
1648 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00001649 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001650 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
1651 printf("\n block variable layout for block: ");
1652 const unsigned char *s = (unsigned char*)BitMap.c_str();
1653 for (unsigned i = 0; i < BitMap.size(); i++)
1654 if (!(s[i] & 0xf0))
1655 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
1656 else
1657 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
1658 printf("\n");
1659 }
1660
1661 return C;
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00001662}
1663
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001664llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00001665 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00001666 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00001667 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00001668 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1669
Owen Andersonade90fd2009-07-29 18:54:39 +00001670 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Daniel Dunbarb036db82008-08-13 03:21:16 +00001671 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001672}
1673
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001674void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00001675 // FIXME: We shouldn't need this, the protocol decl should contain enough
1676 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00001677 DefinedProtocols.insert(PD->getIdentifier());
1678
1679 // If we have generated a forward reference to this protocol, emit
1680 // it now. Otherwise do nothing, the protocol objects are lazily
1681 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001682 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00001683 GetOrEmitProtocol(PD);
1684}
1685
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001686llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001687 if (DefinedProtocols.count(PD->getIdentifier()))
1688 return GetOrEmitProtocol(PD);
1689 return GetOrEmitProtocolRef(PD);
1690}
1691
Daniel Dunbarb036db82008-08-13 03:21:16 +00001692/*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001693// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1694struct _objc_protocol {
1695struct _objc_protocol_extension *isa;
1696char *protocol_name;
1697struct _objc_protocol_list *protocol_list;
1698struct _objc__method_prototype_list *instance_methods;
1699struct _objc__method_prototype_list *class_methods
1700};
Daniel Dunbarb036db82008-08-13 03:21:16 +00001701
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001702See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00001703*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00001704llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1705 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1706
1707 // Early exit if a defining object has already been generated.
1708 if (Entry && Entry->hasInitializer())
1709 return Entry;
1710
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00001711 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00001712 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00001713 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1714
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001715 // Construct method lists.
1716 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1717 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001718 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00001719 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001720 ObjCMethodDecl *MD = *i;
1721 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1722 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1723 OptInstanceMethods.push_back(C);
1724 } else {
1725 InstanceMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001726 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001727 }
1728
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001729 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00001730 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001731 ObjCMethodDecl *MD = *i;
1732 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1733 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1734 OptClassMethods.push_back(C);
1735 } else {
1736 ClassMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001737 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001738 }
1739
Daniel Dunbarb036db82008-08-13 03:21:16 +00001740 std::vector<llvm::Constant*> Values(5);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001741 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001742 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001743 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001744 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardec75f82008-08-21 21:57:41 +00001745 PD->protocol_begin(),
1746 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001747 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001748 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001749 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1750 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001751 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001752 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001753 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1754 ClassMethods);
Owen Anderson0e0189d2009-07-27 22:29:56 +00001755 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001756 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001757
Daniel Dunbarb036db82008-08-13 03:21:16 +00001758 if (Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001759 // Already created, fix the linkage and update the initializer.
1760 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001761 Entry->setInitializer(Init);
1762 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001763 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00001764 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001765 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001766 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001767 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00001768 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00001769 // FIXME: Is this necessary? Why only for protocol?
1770 Entry->setAlignment(4);
1771 }
Chris Lattnerf56501c2009-07-17 23:57:13 +00001772 CGM.AddUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001773
1774 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00001775}
1776
Daniel Dunbarc475d422008-10-29 22:36:39 +00001777llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00001778 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1779
1780 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001781 // We use the initializer as a marker of whether this is a forward
1782 // reference or not. At module finalization we add the empty
1783 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001784 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00001785 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarc475d422008-10-29 22:36:39 +00001786 llvm::GlobalValue::ExternalLinkage,
1787 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001788 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00001789 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00001790 // FIXME: Is this necessary? Why only for protocol?
1791 Entry->setAlignment(4);
1792 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001793
Daniel Dunbarb036db82008-08-13 03:21:16 +00001794 return Entry;
1795}
1796
1797/*
1798 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001799 uint32_t size;
1800 struct objc_method_description_list *optional_instance_methods;
1801 struct objc_method_description_list *optional_class_methods;
1802 struct objc_property_list *instance_properties;
Daniel Dunbarb036db82008-08-13 03:21:16 +00001803 };
1804*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001805llvm::Constant *
1806CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1807 const ConstantVector &OptInstanceMethods,
1808 const ConstantVector &OptClassMethods) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001809 uint64_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00001810 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001811 std::vector<llvm::Constant*> Values(4);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001812 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001813 Values[1] =
1814 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001815 + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001816 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1817 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001818 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001819 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001820 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1821 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001822 Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00001823 0, PD, ObjCTypes);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001824
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001825 // Return null if no extension bits are used.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001826 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Daniel Dunbarb036db82008-08-13 03:21:16 +00001827 Values[3]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00001828 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001829
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001830 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00001831 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001832
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001833 // No special section, but goes in llvm.used
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001834 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001835 Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001836 0, 0, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001837}
1838
1839/*
1840 struct objc_protocol_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001841 struct objc_protocol_list *next;
1842 long count;
1843 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00001844 };
1845*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00001846llvm::Constant *
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001847CGObjCMac::EmitProtocolList(llvm::Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001848 ObjCProtocolDecl::protocol_iterator begin,
1849 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00001850 std::vector<llvm::Constant*> ProtocolRefs;
1851
Daniel Dunbardec75f82008-08-21 21:57:41 +00001852 for (; begin != end; ++begin)
1853 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarb036db82008-08-13 03:21:16 +00001854
1855 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001856 if (ProtocolRefs.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00001857 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001858
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001859 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00001860 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbarb036db82008-08-13 03:21:16 +00001861
1862 std::vector<llvm::Constant*> Values(3);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001863 // This field is only used by the runtime.
Owen Anderson0b75f232009-07-31 20:28:54 +00001864 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001865 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001866 ProtocolRefs.size() - 1);
1867 Values[2] =
1868 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1869 ProtocolRefs.size()),
Daniel Dunbarb036db82008-08-13 03:21:16 +00001870 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001871
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00001872 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001873 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001874 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00001875 4, false);
Owen Andersonade90fd2009-07-29 18:54:39 +00001876 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001877}
1878
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00001879void CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
1880 std::vector<llvm::Constant*> &Properties,
1881 const Decl *Container,
1882 const ObjCProtocolDecl *PROTO,
1883 const ObjCCommonTypesHelper &ObjCTypes) {
1884 std::vector<llvm::Constant*> Prop(2);
1885 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
1886 E = PROTO->protocol_end(); P != E; ++P)
1887 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
1888 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
1889 E = PROTO->prop_end(); I != E; ++I) {
1890 const ObjCPropertyDecl *PD = *I;
1891 if (!PropertySet.insert(PD->getIdentifier()))
1892 continue;
1893 Prop[0] = GetPropertyName(PD->getIdentifier());
1894 Prop[1] = GetPropertyTypeString(PD, Container);
1895 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
1896 }
1897}
1898
Daniel Dunbarb036db82008-08-13 03:21:16 +00001899/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001900 struct _objc_property {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001901 const char * const name;
1902 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001903 };
1904
1905 struct _objc_property_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001906 uint32_t entsize; // sizeof (struct _objc_property)
1907 uint32_t prop_count;
1908 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001909 };
1910*/
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001911llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001912 const Decl *Container,
1913 const ObjCContainerDecl *OCD,
1914 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001915 std::vector<llvm::Constant*> Properties, Prop(2);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00001916 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001917 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
1918 E = OCD->prop_end(); I != E; ++I) {
Steve Naroffba3dc382009-01-11 12:47:58 +00001919 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00001920 PropertySet.insert(PD->getIdentifier());
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001921 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbar4932b362008-08-28 04:38:10 +00001922 Prop[1] = GetPropertyTypeString(PD, Container);
Owen Anderson0e0189d2009-07-27 22:29:56 +00001923 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001924 Prop));
1925 }
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00001926 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek0ef508d2010-09-01 01:21:15 +00001927 for (ObjCInterfaceDecl::all_protocol_iterator
1928 P = OID->all_referenced_protocol_begin(),
1929 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00001930 PushProtocolProperties(PropertySet, Properties, Container, (*P),
1931 ObjCTypes);
1932 }
1933 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
1934 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
1935 E = CD->protocol_end(); P != E; ++P)
1936 PushProtocolProperties(PropertySet, Properties, Container, (*P),
1937 ObjCTypes);
1938 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001939
1940 // Return null for empty list.
1941 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00001942 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001943
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001944 unsigned PropertySize =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00001945 CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001946 std::vector<llvm::Constant*> Values(3);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001947 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
1948 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001949 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001950 Properties.size());
Owen Anderson47034e12009-07-28 18:33:04 +00001951 Values[2] = llvm::ConstantArray::get(AT, Properties);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00001952 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001953
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001954 llvm::GlobalVariable *GV =
1955 CreateMetadataVar(Name, Init,
1956 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbarb25452a2009-04-15 02:56:18 +00001957 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001958 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbarb25452a2009-04-15 02:56:18 +00001959 true);
Owen Andersonade90fd2009-07-29 18:54:39 +00001960 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001961}
1962
1963/*
Daniel Dunbarb036db82008-08-13 03:21:16 +00001964 struct objc_method_description_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001965 int count;
1966 struct objc_method_description list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00001967 };
1968*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001969llvm::Constant *
1970CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
1971 std::vector<llvm::Constant*> Desc(2);
Owen Anderson170229f2009-07-14 23:10:40 +00001972 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001973 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1974 ObjCTypes.SelectorPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001975 Desc[1] = GetMethodVarType(MD);
Owen Anderson0e0189d2009-07-27 22:29:56 +00001976 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001977 Desc);
1978}
Daniel Dunbarb036db82008-08-13 03:21:16 +00001979
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001980llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001981 const char *Section,
1982 const ConstantVector &Methods) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00001983 // Return null for empty list.
1984 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00001985 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001986
1987 std::vector<llvm::Constant*> Values(2);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001988 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001989 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001990 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00001991 Values[1] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00001992 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001993
Daniel Dunbarb25452a2009-04-15 02:56:18 +00001994 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001995 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001996 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001997}
1998
Daniel Dunbar938a77f2008-08-22 20:34:54 +00001999/*
2000 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002001 char *category_name;
2002 char *class_name;
2003 struct _objc_method_list *instance_methods;
2004 struct _objc_method_list *class_methods;
2005 struct _objc_protocol_list *protocols;
2006 uint32_t size; // <rdar://4585769>
2007 struct _objc_property_list *instance_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002008 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002009*/
Daniel Dunbar92992502008-08-15 22:20:32 +00002010void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002011 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002012
Mike Stump18bb9282009-05-16 07:57:57 +00002013 // FIXME: This is poor design, the OCD should have a pointer to the category
2014 // decl. Additionally, note that Category can be null for the @implementation
2015 // w/o an @interface case. Sema should just create one for us as it does for
2016 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002017 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002018 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002019 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002020
2021 llvm::SmallString<256> ExtName;
2022 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2023 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002024
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002025 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002026 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002027 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002028 // Instance methods should always be defined.
2029 InstanceMethods.push_back(GetMethodConstant(*i));
2030 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002031 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002032 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002033 // Class methods should always be defined.
2034 ClassMethods.push_back(GetMethodConstant(*i));
2035 }
2036
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002037 std::vector<llvm::Constant*> Values(7);
2038 Values[0] = GetClassName(OCD->getIdentifier());
2039 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00002040 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002041 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002042 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002043 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002044 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002045 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002046 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002047 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002048 ClassMethods);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002049 if (Category) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002050 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002051 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002052 Category->protocol_begin(),
2053 Category->protocol_end());
2054 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002055 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002056 }
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002057 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002058
2059 // If there is no category @interface then there can be no properties.
2060 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002061 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002062 OCD, Category, ObjCTypes);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002063 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002064 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002065 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002066
Owen Anderson0e0189d2009-07-27 22:29:56 +00002067 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002068 Values);
2069
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002070 llvm::GlobalVariable *GV =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002071 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002072 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002073 4, true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002074 DefinedCategories.push_back(GV);
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00002075 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002076 // method definition entries must be clear for next implementation.
2077 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002078}
2079
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002080// FIXME: Get from somewhere?
2081enum ClassFlags {
2082 eClassFlags_Factory = 0x00001,
2083 eClassFlags_Meta = 0x00002,
2084 // <rdr://5142207>
2085 eClassFlags_HasCXXStructors = 0x02000,
2086 eClassFlags_Hidden = 0x20000,
2087 eClassFlags_ABI2_Hidden = 0x00010,
2088 eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
2089};
2090
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002091/*
2092 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002093 Class isa;
2094 Class super_class;
2095 const char *name;
2096 long version;
2097 long info;
2098 long instance_size;
2099 struct _objc_ivar_list *ivars;
2100 struct _objc_method_list *methods;
2101 struct _objc_cache *cache;
2102 struct _objc_protocol_list *protocols;
2103 // Objective-C 1.0 extensions (<rdr://4585769>)
2104 const char *ivar_layout;
2105 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002106 };
2107
2108 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002109*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002110void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002111 DefinedSymbols.insert(ID->getIdentifier());
2112
Chris Lattner86d7d912008-11-24 03:54:41 +00002113 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002114 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002115 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002116 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002117 llvm::Constant *Protocols =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002118 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00002119 Interface->all_referenced_protocol_begin(),
2120 Interface->all_referenced_protocol_end());
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002121 unsigned Flags = eClassFlags_Factory;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00002122 if (ID->getNumIvarInitializers())
2123 Flags |= eClassFlags_HasCXXStructors;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002124 unsigned Size =
Ken Dyckc8ae5502011-02-09 01:59:34 +00002125 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002126
2127 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00002128 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002129 Flags |= eClassFlags_Hidden;
2130
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002131 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002132 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002133 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002134 // Instance methods should always be defined.
2135 InstanceMethods.push_back(GetMethodConstant(*i));
2136 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002137 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002138 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002139 // Class methods should always be defined.
2140 ClassMethods.push_back(GetMethodConstant(*i));
2141 }
2142
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002143 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002144 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002145 ObjCPropertyImplDecl *PID = *i;
2146
2147 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2148 ObjCPropertyDecl *PD = PID->getPropertyDecl();
2149
2150 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
2151 if (llvm::Constant *C = GetMethodConstant(MD))
2152 InstanceMethods.push_back(C);
2153 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
2154 if (llvm::Constant *C = GetMethodConstant(MD))
2155 InstanceMethods.push_back(C);
2156 }
2157 }
2158
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002159 std::vector<llvm::Constant*> Values(12);
Daniel Dunbarccf61832009-05-03 08:56:52 +00002160 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002161 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002162 // Record a reference to the super class.
2163 LazySymbols.insert(Super->getIdentifier());
2164
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002165 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002166 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002167 ObjCTypes.ClassPtrTy);
2168 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002169 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002170 }
2171 Values[ 2] = GetClassName(ID->getIdentifier());
2172 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002173 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2174 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2175 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002176 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002177 Values[ 7] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002178 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002179 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002180 InstanceMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002181 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002182 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002183 Values[ 9] = Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002184 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002185 Values[11] = EmitClassExtension(ID);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002186 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002187 Values);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002188 std::string Name("\01L_OBJC_CLASS_");
2189 Name += ClassName;
2190 const char *Section = "__OBJC,__class,regular,no_dead_strip";
2191 // Check for a forward reference.
2192 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2193 if (GV) {
2194 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2195 "Forward metaclass reference has incorrect type.");
2196 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2197 GV->setInitializer(Init);
2198 GV->setSection(Section);
2199 GV->setAlignment(4);
2200 CGM.AddUsedGlobal(GV);
2201 }
2202 else
2203 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002204 DefinedClasses.push_back(GV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002205 // method definition entries must be clear for next implementation.
2206 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002207}
2208
2209llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2210 llvm::Constant *Protocols,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002211 const ConstantVector &Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002212 unsigned Flags = eClassFlags_Meta;
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002213 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002214
John McCall457a04e2010-10-22 21:05:15 +00002215 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002216 Flags |= eClassFlags_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002217
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002218 std::vector<llvm::Constant*> Values(12);
2219 // The isa for the metaclass is the root of the hierarchy.
2220 const ObjCInterfaceDecl *Root = ID->getClassInterface();
2221 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2222 Root = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002223 Values[ 0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002224 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002225 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002226 // The super class for the metaclass is emitted as the name of the
2227 // super class. The runtime fixes this up to point to the
2228 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002229 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002230 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002231 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002232 ObjCTypes.ClassPtrTy);
2233 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002234 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002235 }
2236 Values[ 2] = GetClassName(ID->getIdentifier());
2237 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002238 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2239 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2240 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002241 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002242 Values[ 7] =
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002243 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002244 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002245 Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002246 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002247 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002248 Values[ 9] = Protocols;
2249 // ivar_layout for metaclass is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002250 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002251 // The class extension is always unused for metaclasses.
Owen Anderson0b75f232009-07-31 20:28:54 +00002252 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002253 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002254 Values);
2255
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002256 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattner86d7d912008-11-24 03:54:41 +00002257 Name += ID->getNameAsCString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002258
2259 // Check for a forward reference.
2260 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2261 if (GV) {
2262 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2263 "Forward metaclass reference has incorrect type.");
2264 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2265 GV->setInitializer(Init);
2266 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00002267 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002268 llvm::GlobalValue::InternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002269 Init, Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002270 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002271 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbarae333842009-03-09 22:18:41 +00002272 GV->setAlignment(4);
Chris Lattnerf56501c2009-07-17 23:57:13 +00002273 CGM.AddUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002274
2275 return GV;
2276}
2277
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002278llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002279 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002280
Mike Stump18bb9282009-05-16 07:57:57 +00002281 // FIXME: Should we look these up somewhere other than the module. Its a bit
2282 // silly since we only generate these while processing an implementation, so
2283 // exactly one pointer would work if know when we entered/exitted an
2284 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002285
2286 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00002287 // Previously, metaclass with internal linkage may have been defined.
2288 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002289 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2290 true)) {
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002291 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2292 "Forward metaclass reference has incorrect type.");
2293 return GV;
2294 } else {
2295 // Generate as an external reference to keep a consistent
2296 // module. This will be patched up when we emit the metaclass.
Owen Andersonc10c8d32009-07-08 19:05:04 +00002297 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002298 llvm::GlobalValue::ExternalLinkage,
2299 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002300 Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002301 }
2302}
2303
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002304llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2305 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2306
2307 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2308 true)) {
2309 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2310 "Forward class metadata reference has incorrect type.");
2311 return GV;
2312 } else {
2313 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2314 llvm::GlobalValue::ExternalLinkage,
2315 0,
2316 Name);
2317 }
2318}
2319
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002320/*
2321 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002322 uint32_t size;
2323 const char *weak_ivar_layout;
2324 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002325 };
2326*/
2327llvm::Constant *
2328CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002329 uint64_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002330 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002331
2332 std::vector<llvm::Constant*> Values(3);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002333 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian6df69862009-04-22 23:00:43 +00002334 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002335 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002336 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002337
2338 // Return null if no extension bits are used.
2339 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002340 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002341
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002342 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002343 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002344 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002345 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002346 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002347}
2348
2349/*
2350 struct objc_ivar {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002351 char *ivar_name;
2352 char *ivar_type;
2353 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002354 };
2355
2356 struct objc_ivar_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002357 int ivar_count;
2358 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002359 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002360*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002361llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002362 bool ForClass) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002363 std::vector<llvm::Constant*> Ivars, Ivar(3);
2364
2365 // When emitting the root class GCC emits ivar entries for the
2366 // actual class structure. It is not clear if we need to follow this
2367 // behavior; for now lets try and get away with not doing it. If so,
2368 // the cleanest solution would be to make up an ObjCInterfaceDecl
2369 // for the class.
2370 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00002371 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002372
2373 ObjCInterfaceDecl *OID =
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002374 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002375
Daniel Dunbarf5c18462009-04-20 06:54:31 +00002376 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian7c809592009-06-04 01:19:09 +00002377 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002378
Daniel Dunbarf5c18462009-04-20 06:54:31 +00002379 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2380 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian7c809592009-06-04 01:19:09 +00002381 // Ignore unnamed bit-fields.
2382 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002383 continue;
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00002384 Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2385 Ivar[1] = GetMethodVarType(IVD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002386 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00002387 ComputeIvarBaseOffset(CGM, OID, IVD));
Owen Anderson0e0189d2009-07-27 22:29:56 +00002388 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002389 }
2390
2391 // Return null for empty list.
2392 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002393 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002394
2395 std::vector<llvm::Constant*> Values(2);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002396 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002397 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002398 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002399 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002400 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002401
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002402 llvm::GlobalVariable *GV;
2403 if (ForClass)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002404 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002405 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002406 4, true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002407 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002408 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002409 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002410 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002411 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002412}
2413
2414/*
2415 struct objc_method {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002416 SEL method_name;
2417 char *method_types;
2418 void *method;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002419 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002420
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002421 struct objc_method_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002422 struct objc_method_list *obsolete;
2423 int count;
2424 struct objc_method methods_list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002425 };
2426*/
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002427
2428/// GetMethodConstant - Return a struct objc_method constant for the
2429/// given method if it has been defined. The result is null if the
2430/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002431llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00002432 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002433 if (!Fn)
2434 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002435
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002436 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002437 Method[0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002438 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002439 ObjCTypes.SelectorPtrTy);
2440 Method[1] = GetMethodVarType(MD);
Owen Andersonade90fd2009-07-29 18:54:39 +00002441 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002442 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002443}
2444
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002445llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002446 const char *Section,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002447 const ConstantVector &Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002448 // Return null for empty list.
2449 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002450 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002451
2452 std::vector<llvm::Constant*> Values(3);
Owen Anderson0b75f232009-07-31 20:28:54 +00002453 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002454 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002455 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002456 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002457 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002458 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002459
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002460 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002461 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002462 ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002463}
2464
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00002465llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002466 const ObjCContainerDecl *CD) {
Daniel Dunbard2386812009-10-19 01:21:19 +00002467 llvm::SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00002468 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002469
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00002470 CodeGenTypes &Types = CGM.getTypes();
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00002471 const llvm::FunctionType *MethodTy =
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00002472 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002473 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00002474 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002475 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00002476 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002477 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002478 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002479
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002480 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002481}
2482
Daniel Dunbar30c65362009-03-09 20:09:19 +00002483llvm::GlobalVariable *
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002484CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00002485 llvm::Constant *Init,
2486 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00002487 unsigned Align,
2488 bool AddToUsed) {
Daniel Dunbar30c65362009-03-09 20:09:19 +00002489 const llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002490 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002491 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerf56501c2009-07-17 23:57:13 +00002492 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbar30c65362009-03-09 20:09:19 +00002493 if (Section)
2494 GV->setSection(Section);
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00002495 if (Align)
2496 GV->setAlignment(Align);
2497 if (AddToUsed)
Chris Lattnerf56501c2009-07-17 23:57:13 +00002498 CGM.AddUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00002499 return GV;
2500}
2501
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002502llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00002503 // Abuse this interface function as a place to finalize.
2504 FinishModule();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002505 return NULL;
2506}
2507
Chris Lattnerd4808922009-03-22 21:03:39 +00002508llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002509 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00002510}
2511
Chris Lattnerd4808922009-03-22 21:03:39 +00002512llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002513 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00002514}
2515
David Chisnall168b80f2010-12-26 22:13:16 +00002516llvm::Constant *CGObjCMac::GetGetStructFunction() {
2517 return ObjCTypes.getCopyStructFn();
2518}
2519llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00002520 return ObjCTypes.getCopyStructFn();
2521}
2522
Chris Lattnerd4808922009-03-22 21:03:39 +00002523llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002524 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00002525}
2526
John McCallbd309292010-07-06 01:34:17 +00002527void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
2528 return EmitTryOrSynchronizedStmt(CGF, S);
2529}
2530
2531void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
2532 const ObjCAtSynchronizedStmt &S) {
2533 return EmitTryOrSynchronizedStmt(CGF, S);
2534}
2535
John McCall65bea082010-07-21 06:59:36 +00002536namespace {
John McCallcda666c2010-07-21 07:22:38 +00002537 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00002538 const Stmt &S;
John McCall2dd7d442010-08-04 05:59:32 +00002539 llvm::Value *SyncArgSlot;
John McCall65bea082010-07-21 06:59:36 +00002540 llvm::Value *CallTryExitVar;
2541 llvm::Value *ExceptionData;
2542 ObjCTypesHelper &ObjCTypes;
2543 PerformFragileFinally(const Stmt *S,
John McCall2dd7d442010-08-04 05:59:32 +00002544 llvm::Value *SyncArgSlot,
John McCall65bea082010-07-21 06:59:36 +00002545 llvm::Value *CallTryExitVar,
2546 llvm::Value *ExceptionData,
2547 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00002548 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00002549 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
2550
2551 void Emit(CodeGenFunction &CGF, bool IsForEH) {
2552 // Check whether we need to call objc_exception_try_exit.
2553 // In optimized code, this branch will always be folded.
2554 llvm::BasicBlock *FinallyCallExit =
2555 CGF.createBasicBlock("finally.call_exit");
2556 llvm::BasicBlock *FinallyNoCallExit =
2557 CGF.createBasicBlock("finally.no_call_exit");
2558 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
2559 FinallyCallExit, FinallyNoCallExit);
2560
2561 CGF.EmitBlock(FinallyCallExit);
2562 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
2563 ->setDoesNotThrow();
2564
2565 CGF.EmitBlock(FinallyNoCallExit);
2566
2567 if (isa<ObjCAtTryStmt>(S)) {
2568 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00002569 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
2570 // Save the current cleanup destination in case there's
2571 // control flow inside the finally statement.
2572 llvm::Value *CurCleanupDest =
2573 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
2574
John McCall65bea082010-07-21 06:59:36 +00002575 CGF.EmitStmt(FinallyStmt->getFinallyBody());
2576
John McCallcebe0ca2010-08-11 00:16:14 +00002577 if (CGF.HaveInsertPoint()) {
2578 CGF.Builder.CreateStore(CurCleanupDest,
2579 CGF.getNormalCleanupDestSlot());
2580 } else {
2581 // Currently, the end of the cleanup must always exist.
2582 CGF.EnsureInsertPoint();
2583 }
2584 }
John McCall65bea082010-07-21 06:59:36 +00002585 } else {
2586 // Emit objc_sync_exit(expr); as finally's sole statement for
2587 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00002588 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall65bea082010-07-21 06:59:36 +00002589 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
2590 ->setDoesNotThrow();
2591 }
2592 }
2593 };
John McCall42227ed2010-07-31 23:20:56 +00002594
2595 class FragileHazards {
2596 CodeGenFunction &CGF;
2597 llvm::SmallVector<llvm::Value*, 20> Locals;
2598 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
2599
2600 llvm::InlineAsm *ReadHazard;
2601 llvm::InlineAsm *WriteHazard;
2602
2603 llvm::FunctionType *GetAsmFnType();
2604
2605 void collectLocals();
2606 void emitReadHazard(CGBuilderTy &Builder);
2607
2608 public:
2609 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00002610
John McCall42227ed2010-07-31 23:20:56 +00002611 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00002612 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00002613 };
2614}
2615
2616/// Create the fragile-ABI read and write hazards based on the current
2617/// state of the function, which is presumed to be immediately prior
2618/// to a @try block. These hazards are used to maintain correct
2619/// semantics in the face of optimization and the fragile ABI's
2620/// cavalier use of setjmp/longjmp.
2621FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
2622 collectLocals();
2623
2624 if (Locals.empty()) return;
2625
2626 // Collect all the blocks in the function.
2627 for (llvm::Function::iterator
2628 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
2629 BlocksBeforeTry.insert(&*I);
2630
2631 llvm::FunctionType *AsmFnTy = GetAsmFnType();
2632
2633 // Create a read hazard for the allocas. This inhibits dead-store
2634 // optimizations and forces the values to memory. This hazard is
2635 // inserted before any 'throwing' calls in the protected scope to
2636 // reflect the possibility that the variables might be read from the
2637 // catch block if the call throws.
2638 {
2639 std::string Constraint;
2640 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2641 if (I) Constraint += ',';
2642 Constraint += "*m";
2643 }
2644
2645 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2646 }
2647
2648 // Create a write hazard for the allocas. This inhibits folding
2649 // loads across the hazard. This hazard is inserted at the
2650 // beginning of the catch path to reflect the possibility that the
2651 // variables might have been written within the protected scope.
2652 {
2653 std::string Constraint;
2654 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2655 if (I) Constraint += ',';
2656 Constraint += "=*m";
2657 }
2658
2659 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2660 }
2661}
2662
2663/// Emit a write hazard at the current location.
2664void FragileHazards::emitWriteHazard() {
2665 if (Locals.empty()) return;
2666
2667 CGF.Builder.CreateCall(WriteHazard, Locals.begin(), Locals.end())
2668 ->setDoesNotThrow();
2669}
2670
John McCall42227ed2010-07-31 23:20:56 +00002671void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
2672 assert(!Locals.empty());
2673 Builder.CreateCall(ReadHazard, Locals.begin(), Locals.end())
2674 ->setDoesNotThrow();
2675}
2676
2677/// Emit read hazards in all the protected blocks, i.e. all the blocks
2678/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00002679void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00002680 if (Locals.empty()) return;
2681
2682 CGBuilderTy Builder(CGF.getLLVMContext());
2683
2684 // Iterate through all blocks, skipping those prior to the try.
2685 for (llvm::Function::iterator
2686 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
2687 llvm::BasicBlock &BB = *FI;
2688 if (BlocksBeforeTry.count(&BB)) continue;
2689
2690 // Walk through all the calls in the block.
2691 for (llvm::BasicBlock::iterator
2692 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
2693 llvm::Instruction &I = *BI;
2694
2695 // Ignore instructions that aren't non-intrinsic calls.
2696 // These are the only calls that can possibly call longjmp.
2697 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
2698 if (isa<llvm::IntrinsicInst>(I))
2699 continue;
2700
2701 // Ignore call sites marked nounwind. This may be questionable,
2702 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
2703 llvm::CallSite CS(&I);
2704 if (CS.doesNotThrow()) continue;
2705
John McCall2dd7d442010-08-04 05:59:32 +00002706 // Insert a read hazard before the call. This will ensure that
2707 // any writes to the locals are performed before making the
2708 // call. If the call throws, then this is sufficient to
2709 // guarantee correctness as long as it doesn't also write to any
2710 // locals.
John McCall42227ed2010-07-31 23:20:56 +00002711 Builder.SetInsertPoint(&BB, BI);
2712 emitReadHazard(Builder);
2713 }
2714 }
2715}
2716
2717static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
2718 if (V) S.insert(V);
2719}
2720
2721void FragileHazards::collectLocals() {
2722 // Compute a set of allocas to ignore.
2723 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
2724 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
2725 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
2726 addIfPresent(AllocasToIgnore, CGF.EHCleanupDest);
2727
2728 // Collect all the allocas currently in the function. This is
2729 // probably way too aggressive.
2730 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
2731 for (llvm::BasicBlock::iterator
2732 I = Entry.begin(), E = Entry.end(); I != E; ++I)
2733 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
2734 Locals.push_back(&*I);
2735}
2736
2737llvm::FunctionType *FragileHazards::GetAsmFnType() {
John McCall9dc0db22011-05-15 01:53:33 +00002738 llvm::SmallVector<const llvm::Type *, 16> tys(Locals.size());
2739 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
2740 tys[i] = Locals[i]->getType();
2741 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00002742}
2743
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002744/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002745
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002746 Objective-C setjmp-longjmp (sjlj) Exception Handling
2747 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002748
John McCallbd309292010-07-06 01:34:17 +00002749 A catch buffer is a setjmp buffer plus:
2750 - a pointer to the exception that was caught
2751 - a pointer to the previous exception data buffer
2752 - two pointers of reserved storage
2753 Therefore catch buffers form a stack, with a pointer to the top
2754 of the stack kept in thread-local storage.
2755
2756 objc_exception_try_enter pushes a catch buffer onto the EH stack.
2757 objc_exception_try_exit pops the given catch buffer, which is
2758 required to be the top of the EH stack.
2759 objc_exception_throw pops the top of the EH stack, writes the
2760 thrown exception into the appropriate field, and longjmps
2761 to the setjmp buffer. It crashes the process (with a printf
2762 and an abort()) if there are no catch buffers on the stack.
2763 objc_exception_extract just reads the exception pointer out of the
2764 catch buffer.
2765
2766 There's no reason an implementation couldn't use a light-weight
2767 setjmp here --- something like __builtin_setjmp, but API-compatible
2768 with the heavyweight setjmp. This will be more important if we ever
2769 want to implement correct ObjC/C++ exception interactions for the
2770 fragile ABI.
2771
2772 Note that for this use of setjmp/longjmp to be correct, we may need
2773 to mark some local variables volatile: if a non-volatile local
2774 variable is modified between the setjmp and the longjmp, it has
2775 indeterminate value. For the purposes of LLVM IR, it may be
2776 sufficient to make loads and stores within the @try (to variables
2777 declared outside the @try) volatile. This is necessary for
2778 optimized correctness, but is not currently being done; this is
2779 being tracked as rdar://problem/8160285
2780
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002781 The basic framework for a @try-catch-finally is as follows:
2782 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002783 objc_exception_data d;
2784 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00002785 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002786
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002787 objc_exception_try_enter(&d);
2788 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002789 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002790 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002791 // exception path
2792 id _caught = objc_exception_extract(&d);
2793
2794 // enter new try scope for handlers
2795 if (!setjmp(d.jmp_buf)) {
2796 ... match exception and execute catch blocks ...
2797
2798 // fell off end, rethrow.
2799 _rethrow = _caught;
2800 ... jump-through-finally to finally_rethrow ...
2801 } else {
2802 // exception in catch block
2803 _rethrow = objc_exception_extract(&d);
2804 _call_try_exit = false;
2805 ... jump-through-finally to finally_rethrow ...
2806 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002807 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002808 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002809
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002810 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00002811 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002812 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00002813
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002814 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002815 ... dispatch to finally destination ...
2816
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002817 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002818 objc_exception_throw(_rethrow);
2819
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002820 finally_end:
2821 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002822
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002823 This framework differs slightly from the one gcc uses, in that gcc
2824 uses _rethrow to determine if objc_exception_try_exit should be called
2825 and if the object should be rethrown. This breaks in the face of
2826 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002827
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002828 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002829
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002830 - If there are no catch blocks, then we avoid emitting the second
2831 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002832
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002833 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
2834 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002835
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002836 - FIXME: If there is no @finally block we can do a few more
2837 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002838
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002839 Rethrows and Jumps-Through-Finally
2840 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002841
John McCallbd309292010-07-06 01:34:17 +00002842 '@throw;' is supported by pushing the currently-caught exception
2843 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002844
John McCallbd309292010-07-06 01:34:17 +00002845 Branches through the @finally block are handled with an ordinary
2846 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
2847 exceptions are not compatible with C++ exceptions, and this is
2848 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002849
John McCallbd309292010-07-06 01:34:17 +00002850 @synchronized(expr) { stmt; } is emitted as if it were:
2851 id synch_value = expr;
2852 objc_sync_enter(synch_value);
2853 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002854*/
2855
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00002856void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2857 const Stmt &S) {
2858 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00002859
2860 // A destination for the fall-through edges of the catch handlers to
2861 // jump to.
2862 CodeGenFunction::JumpDest FinallyEnd =
2863 CGF.getJumpDestInCurrentScope("finally.end");
2864
2865 // A destination for the rethrow edge of the catch handlers to jump
2866 // to.
2867 CodeGenFunction::JumpDest FinallyRethrow =
2868 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002869
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002870 // For @synchronized, call objc_sync_enter(sync.expr). The
2871 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00002872 // @synchronized. We can't avoid a temp here because we need the
2873 // value to be preserved. If the backend ever does liveness
2874 // correctly after setjmp, this will be unnecessary.
2875 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002876 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00002877 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002878 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2879 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallbd309292010-07-06 01:34:17 +00002880 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
2881 ->setDoesNotThrow();
John McCall2dd7d442010-08-04 05:59:32 +00002882
2883 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
2884 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002885 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002886
John McCall2dd7d442010-08-04 05:59:32 +00002887 // Allocate memory for the setjmp buffer. This needs to be kept
2888 // live throughout the try and catch blocks.
2889 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2890 "exceptiondata.ptr");
2891
John McCall42227ed2010-07-31 23:20:56 +00002892 // Create the fragile hazards. Note that this will not capture any
2893 // of the allocas required for exception processing, but will
2894 // capture the current basic block (which extends all the way to the
2895 // setjmp call) as "before the @try".
2896 FragileHazards Hazards(CGF);
2897
John McCallbd309292010-07-06 01:34:17 +00002898 // Create a flag indicating whether the cleanup needs to call
2899 // objc_exception_try_exit. This is true except when
2900 // - no catches match and we're branching through the cleanup
2901 // just to rethrow the exception, or
2902 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00002903 // The setjmp-safety rule here is that we should always store to this
2904 // variable in a place that dominates the branch through the cleanup
2905 // without passing through any setjmps.
John McCallbd309292010-07-06 01:34:17 +00002906 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlssonda0e4562009-02-07 21:26:04 +00002907 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002908
John McCall9916e3f2010-10-04 23:42:51 +00002909 // A slot containing the exception to rethrow. Only needed when we
2910 // have both a @catch and a @finally.
2911 llvm::Value *PropagatingExnVar = 0;
2912
John McCallbd309292010-07-06 01:34:17 +00002913 // Push a normal cleanup to leave the try scope.
John McCallcda666c2010-07-21 07:22:38 +00002914 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00002915 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00002916 CallTryExitVar,
2917 ExceptionData,
2918 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00002919
2920 // Enter a try block:
2921 // - Call objc_exception_try_enter to push ExceptionData on top of
2922 // the EH stack.
2923 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
2924 ->setDoesNotThrow();
2925
2926 // - Call setjmp on the exception data buffer.
2927 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
2928 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
2929 llvm::Value *SetJmpBuffer =
2930 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, GEPIndexes+3, "setjmp_buffer");
2931 llvm::CallInst *SetJmpResult =
2932 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
2933 SetJmpResult->setDoesNotThrow();
2934
2935 // If setjmp returned 0, enter the protected block; otherwise,
2936 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00002937 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
2938 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00002939 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00002940 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
2941 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00002942
John McCallbd309292010-07-06 01:34:17 +00002943 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00002944 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00002945 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002946 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00002947 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00002948
2949 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002950
John McCallbd309292010-07-06 01:34:17 +00002951 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00002952 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00002953
John McCall42227ed2010-07-31 23:20:56 +00002954 // Don't optimize loads of the in-scope locals across this point.
2955 Hazards.emitWriteHazard();
2956
John McCallbd309292010-07-06 01:34:17 +00002957 // For a @synchronized (or a @try with no catches), just branch
2958 // through the cleanup to the rethrow block.
2959 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
2960 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00002961 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00002962 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00002963
2964 // Otherwise, we have to match against the caught exceptions.
2965 } else {
John McCall2dd7d442010-08-04 05:59:32 +00002966 // Retrieve the exception object. We may emit multiple blocks but
2967 // nothing can cross this so the value is already in SSA form.
2968 llvm::CallInst *Caught =
2969 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
2970 ExceptionData, "caught");
2971 Caught->setDoesNotThrow();
2972
John McCallbd309292010-07-06 01:34:17 +00002973 // Push the exception to rethrow onto the EH value stack for the
2974 // benefit of any @throws in the handlers.
2975 CGF.ObjCEHValueStack.push_back(Caught);
2976
Douglas Gregor96c79492010-04-23 22:50:49 +00002977 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002978
John McCall2dd7d442010-08-04 05:59:32 +00002979 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallbd309292010-07-06 01:34:17 +00002980
John McCall2dd7d442010-08-04 05:59:32 +00002981 llvm::BasicBlock *CatchBlock = 0;
2982 llvm::BasicBlock *CatchHandler = 0;
2983 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00002984 // Save the currently-propagating exception before
2985 // objc_exception_try_enter clears the exception slot.
2986 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
2987 "propagating_exception");
2988 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
2989
John McCall2dd7d442010-08-04 05:59:32 +00002990 // Enter a new exception try block (in case a @catch block
2991 // throws an exception).
2992 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
2993 ->setDoesNotThrow();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00002994
John McCall2dd7d442010-08-04 05:59:32 +00002995 llvm::CallInst *SetJmpResult =
2996 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
2997 "setjmp.result");
2998 SetJmpResult->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002999
John McCall2dd7d442010-08-04 05:59:32 +00003000 llvm::Value *Threw =
3001 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3002
3003 CatchBlock = CGF.createBasicBlock("catch");
3004 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3005 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3006
3007 CGF.EmitBlock(CatchBlock);
3008 }
3009
3010 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003011
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003012 // Handle catch list. As a special case we check if everything is
3013 // matched and avoid generating code for falling off the end if
3014 // so.
3015 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00003016 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3017 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003018
Douglas Gregor46a572b2010-04-26 16:46:50 +00003019 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff7cae42b2009-07-10 23:34:53 +00003020 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar523208f2008-09-27 07:36:24 +00003021
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003022 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003023 if (!CatchParam) {
3024 AllMatched = true;
3025 } else {
John McCall9dd450b2009-09-21 23:43:11 +00003026 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003027
John McCallbd309292010-07-06 01:34:17 +00003028 // catch(id e) always matches under this ABI, since only
3029 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00003030 // FIXME: For the time being we also match id<X>; this should
3031 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00003032 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003033 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003034 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003035
John McCallbd309292010-07-06 01:34:17 +00003036 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003037 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00003038 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3039
Anders Carlsson9396a892008-09-11 09:15:33 +00003040 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00003041 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003042 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00003043
3044 // These types work out because ConvertType(id) == i8*.
Steve Naroff371b8fb2009-03-03 19:52:17 +00003045 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson9396a892008-09-11 09:15:33 +00003046 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003047
Anders Carlsson9396a892008-09-11 09:15:33 +00003048 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003049
3050 // The scope of the catch variable ends right here.
3051 CatchVarCleanups.ForceCleanup();
3052
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003053 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003054 break;
3055 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003056
Steve Naroff7cae42b2009-07-10 23:34:53 +00003057 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00003058 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00003059
3060 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00003061 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3062 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003063
3064 // Check if the @catch block matches the exception object.
John McCall96fa4842010-05-17 21:00:27 +00003065 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003066
John McCallbd309292010-07-06 01:34:17 +00003067 llvm::CallInst *Match =
Chris Lattnerc6406db2009-04-22 02:26:14 +00003068 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3069 Class, Caught, "match");
John McCallbd309292010-07-06 01:34:17 +00003070 Match->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003071
John McCallbd309292010-07-06 01:34:17 +00003072 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3073 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003074
3075 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00003076 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003077
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003078 // Emit the @catch block.
3079 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00003080
3081 // Collect any cleanups for the catch variable. The scope lasts until
3082 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00003083 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00003084
John McCall1c9c3fd2010-10-15 04:57:14 +00003085 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003086 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003087
John McCallbd309292010-07-06 01:34:17 +00003088 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003089 llvm::Value *Tmp =
3090 CGF.Builder.CreateBitCast(Caught,
3091 CGF.ConvertType(CatchParam->getType()),
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003092 "tmp");
Steve Naroff371b8fb2009-03-03 19:52:17 +00003093 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003094
Anders Carlsson9396a892008-09-11 09:15:33 +00003095 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003096
3097 // We're done with the catch variable.
3098 CatchVarCleanups.ForceCleanup();
3099
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003100 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003101
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003102 CGF.EmitBlock(NextCatchBlock);
3103 }
3104
John McCallbd309292010-07-06 01:34:17 +00003105 CGF.ObjCEHValueStack.pop_back();
3106
John McCall2dd7d442010-08-04 05:59:32 +00003107 // If nothing wanted anything to do with the caught exception,
3108 // kill the extract call.
3109 if (Caught->use_empty())
3110 Caught->eraseFromParent();
3111
3112 if (!AllMatched)
3113 CGF.EmitBranchThroughCleanup(FinallyRethrow);
3114
3115 if (HasFinally) {
3116 // Emit the exception handler for the @catch blocks.
3117 CGF.EmitBlock(CatchHandler);
3118
3119 // In theory we might now need a write hazard, but actually it's
3120 // unnecessary because there's no local-accessing code between
3121 // the try's write hazard and here.
3122 //Hazards.emitWriteHazard();
3123
John McCall9916e3f2010-10-04 23:42:51 +00003124 // Extract the new exception and save it to the
3125 // propagating-exception slot.
3126 assert(PropagatingExnVar);
3127 llvm::CallInst *NewCaught =
3128 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3129 ExceptionData, "caught");
3130 NewCaught->setDoesNotThrow();
3131 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
3132
John McCall2dd7d442010-08-04 05:59:32 +00003133 // Don't pop the catch handler; the throw already did.
3134 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003135 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003136 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003137 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003138
John McCall42227ed2010-07-31 23:20:56 +00003139 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00003140 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003141
John McCallbd309292010-07-06 01:34:17 +00003142 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00003143 CGF.Builder.restoreIP(TryFallthroughIP);
3144 if (CGF.HaveInsertPoint())
3145 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00003146 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00003147 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003148
John McCallbd309292010-07-06 01:34:17 +00003149 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00003150 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00003151 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00003152 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00003153 // If we have a propagating-exception variable, check it.
3154 llvm::Value *PropagatingExn;
3155 if (PropagatingExnVar) {
3156 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00003157
John McCall9916e3f2010-10-04 23:42:51 +00003158 // Otherwise, just look in the buffer for the exception to throw.
3159 } else {
3160 llvm::CallInst *Caught =
3161 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3162 ExceptionData);
3163 Caught->setDoesNotThrow();
3164 PropagatingExn = Caught;
3165 }
3166
3167 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
John McCallbd309292010-07-06 01:34:17 +00003168 ->setDoesNotThrow();
3169 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00003170 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003171
John McCall42227ed2010-07-31 23:20:56 +00003172 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003173}
3174
3175void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003176 const ObjCAtThrowStmt &S) {
Anders Carlssone005aa12008-09-09 16:16:55 +00003177 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003178
Anders Carlssone005aa12008-09-09 16:16:55 +00003179 if (const Expr *ThrowExpr = S.getThrowExpr()) {
3180 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003181 ExceptionAsObject =
Anders Carlssone005aa12008-09-09 16:16:55 +00003182 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
3183 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003184 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003185 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00003186 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00003187 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003188
John McCallbd309292010-07-06 01:34:17 +00003189 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3190 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003191 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003192
3193 // Clear the insertion point to indicate we are in unreachable code.
3194 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003195}
3196
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003197/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003198/// object: objc_read_weak (id *src)
3199///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003200llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003201 llvm::Value *AddrWeakObj) {
Eli Friedmana374b682009-03-07 03:57:15 +00003202 const llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003203 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3204 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3205 ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00003206 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003207 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00003208 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003209 return read_weak;
3210}
3211
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003212/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
3213/// objc_assign_weak (id src, id *dst)
3214///
3215void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003216 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003217 const llvm::Type * SrcTy = src->getType();
3218 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003219 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003220 assert(Size <= 8 && "does not support size > 8");
3221 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003222 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003223 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3224 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003225 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3226 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00003227 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003228 src, dst, "weakassign");
3229 return;
3230}
3231
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003232/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
3233/// objc_assign_global (id src, id *dst)
3234///
3235void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00003236 llvm::Value *src, llvm::Value *dst,
3237 bool threadlocal) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003238 const llvm::Type * SrcTy = src->getType();
3239 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003240 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003241 assert(Size <= 8 && "does not support size > 8");
3242 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003243 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003244 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3245 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003246 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3247 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00003248 if (!threadlocal)
3249 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
3250 src, dst, "globalassign");
3251 else
3252 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
3253 src, dst, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003254 return;
3255}
3256
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003257/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003258/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003259///
3260void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003261 llvm::Value *src, llvm::Value *dst,
3262 llvm::Value *ivarOffset) {
3263 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003264 const llvm::Type * SrcTy = src->getType();
3265 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003266 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003267 assert(Size <= 8 && "does not support size > 8");
3268 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003269 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003270 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3271 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003272 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3273 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003274 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3275 src, dst, ivarOffset);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003276 return;
3277}
3278
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003279/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
3280/// objc_assign_strongCast (id src, id *dst)
3281///
3282void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003283 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003284 const llvm::Type * SrcTy = src->getType();
3285 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003286 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003287 assert(Size <= 8 && "does not support size > 8");
3288 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003289 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003290 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3291 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003292 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3293 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00003294 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003295 src, dst, "weakassign");
3296 return;
3297}
3298
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003299void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003300 llvm::Value *DestPtr,
3301 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003302 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003303 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3304 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003305 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003306 DestPtr, SrcPtr, size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003307 return;
3308}
3309
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003310/// EmitObjCValueForIvar - Code Gen for ivar reference.
3311///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003312LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3313 QualType ObjectTy,
3314 llvm::Value *BaseValue,
3315 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003316 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00003317 const ObjCInterfaceDecl *ID =
3318 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003319 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3320 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003321}
3322
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003323llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00003324 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003325 const ObjCIvarDecl *Ivar) {
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003326 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003327 return llvm::ConstantInt::get(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003328 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3329 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003330}
3331
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003332/* *** Private Interface *** */
3333
3334/// EmitImageInfo - Emit the image info marker used to encode some module
3335/// level information.
3336///
3337/// See: <rdr://4810609&4810587&4810587>
3338/// struct IMAGE_INFO {
3339/// unsigned version;
3340/// unsigned flags;
3341/// };
3342enum ImageInfoFlags {
Daniel Dunbar5e639272010-04-25 20:39:01 +00003343 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003344 eImageInfo_GarbageCollected = (1 << 1),
3345 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003346 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
3347
Daniel Dunbar5e639272010-04-25 20:39:01 +00003348 // A flag indicating that the module has no instances of a @synthesize of a
3349 // superclass variable. <rdar://problem/6803242>
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003350 eImageInfo_CorrectedSynthesize = (1 << 4)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003351};
3352
Daniel Dunbar5e639272010-04-25 20:39:01 +00003353void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003354 unsigned version = 0; // Version is unused?
3355 unsigned flags = 0;
3356
3357 // FIXME: Fix and continue?
3358 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
3359 flags |= eImageInfo_GarbageCollected;
3360 if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
3361 flags |= eImageInfo_GCOnly;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003362
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003363 // We never allow @synthesize of a superclass property.
3364 flags |= eImageInfo_CorrectedSynthesize;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003365
Chris Lattner5e016ae2010-06-27 07:15:29 +00003366 const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
3367
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003368 // Emitted as int[2];
3369 llvm::Constant *values[2] = {
Chris Lattner5e016ae2010-06-27 07:15:29 +00003370 llvm::ConstantInt::get(Int32Ty, version),
3371 llvm::ConstantInt::get(Int32Ty, flags)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003372 };
Chris Lattner5e016ae2010-06-27 07:15:29 +00003373 llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003374
3375 const char *Section;
3376 if (ObjCABI == 1)
3377 Section = "__OBJC, __image_info,regular";
3378 else
3379 Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003380 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003381 CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
Owen Anderson47034e12009-07-28 18:33:04 +00003382 llvm::ConstantArray::get(AT, values, 2),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003383 Section,
3384 0,
3385 true);
3386 GV->setConstant(true);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003387}
3388
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003389
3390// struct objc_module {
3391// unsigned long version;
3392// unsigned long size;
3393// const char *name;
3394// Symtab symtab;
3395// };
3396
3397// FIXME: Get from somewhere
3398static const int ModuleVersion = 7;
3399
3400void CGObjCMac::EmitModuleInfo() {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003401 uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003402
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003403 std::vector<llvm::Constant*> Values(4);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003404 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
3405 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbar92992502008-08-15 22:20:32 +00003406 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbarb036db82008-08-13 03:21:16 +00003407 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003408 Values[3] = EmitModuleSymbols();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003409 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson0e0189d2009-07-27 22:29:56 +00003410 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003411 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00003412 4, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003413}
3414
3415llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003416 unsigned NumClasses = DefinedClasses.size();
3417 unsigned NumCategories = DefinedCategories.size();
3418
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003419 // Return null if no symbols were defined.
3420 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00003421 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003422
3423 std::vector<llvm::Constant*> Values(5);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003424 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Anderson0b75f232009-07-31 20:28:54 +00003425 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003426 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3427 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003428
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003429 // The runtime expects exactly the list of defined classes followed
3430 // by the list of defined categories, in a single array.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003431 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003432 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00003433 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003434 ObjCTypes.Int8PtrTy);
3435 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003436 Symbols[NumClasses + i] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003437 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003438 ObjCTypes.Int8PtrTy);
3439
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003440 Values[4] =
Owen Anderson9793f0e2009-07-29 22:16:19 +00003441 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003442 NumClasses + NumCategories),
3443 Symbols);
3444
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00003445 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003446
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003447 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003448 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3449 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003450 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003451 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003452}
3453
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003454llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003455 const ObjCInterfaceDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003456 LazySymbols.insert(ID->getIdentifier());
3457
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003458 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003459
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003460 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003461 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00003462 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003463 ObjCTypes.ClassPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003464 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003465 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3466 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003467 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003468 }
3469
Daniel Dunbarc76493a2009-11-29 21:23:36 +00003470 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003471}
3472
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00003473llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
3474 bool lvalue) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003475 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003476
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003477 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003478 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00003479 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003480 ObjCTypes.SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003481 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003482 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3483 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003484 4, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003485 }
3486
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00003487 if (lvalue)
3488 return Entry;
Daniel Dunbarc76493a2009-11-29 21:23:36 +00003489 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003490}
3491
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00003492llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003493 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003494
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003495 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003496 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003497 llvm::ConstantArray::get(VMContext,
3498 Ident->getNameStart()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003499 ((ObjCABI == 2) ?
3500 "__TEXT,__objc_classname,cstring_literals" :
3501 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003502 1, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003503
Owen Anderson170229f2009-07-14 23:10:40 +00003504 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003505}
3506
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00003507llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
3508 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
3509 I = MethodDefinitions.find(MD);
3510 if (I != MethodDefinitions.end())
3511 return I->second;
3512
3513 if (MD->hasBody() && MD->getPCHLevel() > 0) {
3514 // MD isn't emitted yet because it comes from PCH.
3515 CGM.EmitTopLevelDecl(const_cast<ObjCMethodDecl*>(MD));
3516 assert(MethodDefinitions[MD] && "EmitTopLevelDecl didn't emit the method!");
3517 return MethodDefinitions[MD];
3518 }
3519
3520 return NULL;
3521}
3522
Fariborz Jahanian01dff422009-03-05 19:17:31 +00003523/// GetIvarLayoutName - Returns a unique constant for the given
3524/// ivar layout bitmap.
3525llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003526 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003527 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00003528}
3529
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003530void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003531 unsigned int BytePos,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003532 bool ForStrongLayout,
3533 bool &HasUnion) {
3534 const RecordDecl *RD = RT->getDecl();
3535 // FIXME - Use iterator.
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003536 llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003537 const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003538 const llvm::StructLayout *RecLayout =
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003539 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003540
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003541 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3542 ForStrongLayout, HasUnion);
3543}
3544
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +00003545void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003546 const llvm::StructLayout *Layout,
3547 const RecordDecl *RD,
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003548 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003549 unsigned int BytePos, bool ForStrongLayout,
3550 bool &HasUnion) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003551 bool IsUnion = (RD && RD->isUnion());
3552 uint64_t MaxUnionIvarSize = 0;
3553 uint64_t MaxSkippedUnionIvarSize = 0;
3554 FieldDecl *MaxField = 0;
3555 FieldDecl *MaxSkippedField = 0;
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003556 FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003557 uint64_t MaxFieldOffset = 0;
3558 uint64_t MaxSkippedFieldOffset = 0;
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003559 uint64_t LastBitfieldOrUnnamedOffset = 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003560
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003561 if (RecFields.empty())
3562 return;
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003563 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3564 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3565
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003566 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003567 FieldDecl *Field = RecFields[i];
Daniel Dunbar62b10702009-05-03 23:35:23 +00003568 uint64_t FieldOffset;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00003569 if (RD) {
Daniel Dunbard51c1a62010-04-14 17:02:21 +00003570 // Note that 'i' here is actually the field index inside RD of Field,
3571 // although this dependency is hidden.
3572 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Ken Dyckc5ca8762011-04-14 00:43:09 +00003573 FieldOffset = RL.getFieldOffset(i) / ByteSizeInBits;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00003574 } else
Daniel Dunbar62b10702009-05-03 23:35:23 +00003575 FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003576
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003577 // Skip over unnamed or bitfields
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003578 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003579 LastFieldBitfieldOrUnnamed = Field;
3580 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003581 continue;
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003582 }
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003583
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003584 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003585 QualType FQT = Field->getType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003586 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003587 if (FQT->isUnionType())
3588 HasUnion = true;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003589
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003590 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003591 BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003592 ForStrongLayout, HasUnion);
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003593 continue;
3594 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003595
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003596 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003597 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003598 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003599 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003600 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003601 FQT = CArray->getElementType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003602 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3603 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003604 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003605 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003606 FQT = CArray->getElementType();
3607 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003608
3609 assert(!FQT->isUnionType() &&
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003610 "layout for array of unions not supported");
Fariborz Jahanian9a7d57d2011-01-03 19:23:18 +00003611 if (FQT->isRecordType() && ElCount) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003612 int OldIndex = IvarsInfo.size() - 1;
3613 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003614
Ted Kremenekc23c7e62009-07-29 21:53:49 +00003615 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003616 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003617 ForStrongLayout, HasUnion);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003618
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003619 // Replicate layout information for each array element. Note that
3620 // one element is already done.
3621 uint64_t ElIx = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003622 for (int FirstIndex = IvarsInfo.size() - 1,
3623 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003624 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003625 for (int i = OldIndex+1; i <= FirstIndex; ++i)
3626 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
3627 IvarsInfo[i].ivar_size));
3628 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
3629 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
3630 SkipIvars[i].ivar_size));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003631 }
3632 continue;
3633 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003634 }
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003635 // At this point, we are done with Record/Union and array there of.
3636 // For other arrays we are down to its element type.
John McCall8ccfcb52009-09-24 19:53:00 +00003637 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003638
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003639 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall8ccfcb52009-09-24 19:53:00 +00003640 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3641 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00003642 if (IsUnion) {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003643 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00003644 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003645 MaxUnionIvarSize = UnionIvarSize;
3646 MaxField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003647 MaxFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003648 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00003649 } else {
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003650 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003651 FieldSize / WordSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003652 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003653 } else if ((ForStrongLayout &&
John McCall8ccfcb52009-09-24 19:53:00 +00003654 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3655 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00003656 if (IsUnion) {
Mike Stump18bb9282009-05-16 07:57:57 +00003657 // FIXME: Why the asymmetry? We divide by word size in bits on other
3658 // side.
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003659 uint64_t UnionIvarSize = FieldSize;
Daniel Dunbar22007d32009-05-03 13:32:01 +00003660 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003661 MaxSkippedUnionIvarSize = UnionIvarSize;
3662 MaxSkippedField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003663 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003664 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00003665 } else {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003666 // FIXME: Why the asymmetry, we divide by byte size in bits here?
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003667 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003668 FieldSize / ByteSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003669 }
3670 }
3671 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003672
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003673 if (LastFieldBitfieldOrUnnamed) {
3674 if (LastFieldBitfieldOrUnnamed->isBitField()) {
3675 // Last field was a bitfield. Must update skip info.
3676 Expr *BitWidth = LastFieldBitfieldOrUnnamed->getBitWidth();
3677 uint64_t BitFieldSize =
3678 BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
3679 GC_IVAR skivar;
3680 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
3681 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3682 + ((BitFieldSize % ByteSizeInBits) != 0);
3683 SkipIvars.push_back(skivar);
3684 } else {
3685 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
3686 // Last field was unnamed. Must update skip info.
3687 unsigned FieldSize
3688 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
3689 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
3690 FieldSize / ByteSizeInBits));
3691 }
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003692 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003693
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003694 if (MaxField)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003695 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003696 MaxUnionIvarSize));
3697 if (MaxSkippedField)
Daniel Dunbar5b743912009-05-03 23:31:46 +00003698 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003699 MaxSkippedUnionIvarSize));
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00003700}
3701
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00003702/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
3703/// the computations and returning the layout bitmap (for ivar or blocks) in
3704/// the given argument BitMap string container. Routine reads
3705/// two containers, IvarsInfo and SkipIvars which are assumed to be
3706/// filled already by the caller.
3707llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string& BitMap) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003708 unsigned int WordsToScan, WordsToSkip;
Benjamin Kramerabd5b902009-10-13 10:07:13 +00003709 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003710
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003711 // Build the string of skip/scan nibbles
Fariborz Jahaniance5676572009-04-24 17:15:27 +00003712 llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003713 unsigned int WordSize =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003714 CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003715 if (IvarsInfo[0].ivar_bytepos == 0) {
3716 WordsToSkip = 0;
3717 WordsToScan = IvarsInfo[0].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003718 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003719 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3720 WordsToScan = IvarsInfo[0].ivar_size;
3721 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003722 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003723 unsigned int TailPrevGCObjC =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003724 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003725 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003726 // consecutive 'scanned' object pointers.
3727 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003728 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003729 // Skip over 'gc'able object pointer which lay over each other.
3730 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
3731 continue;
3732 // Must skip over 1 or more words. We save current skip/scan values
3733 // and start a new pair.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003734 SKIP_SCAN SkScan;
3735 SkScan.skip = WordsToSkip;
3736 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003737 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003738
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003739 // Skip the hole.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003740 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3741 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003742 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003743 WordsToSkip = 0;
3744 WordsToScan = IvarsInfo[i].ivar_size;
3745 }
3746 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003747 if (WordsToScan > 0) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003748 SKIP_SCAN SkScan;
3749 SkScan.skip = WordsToSkip;
3750 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003751 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003752 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003753
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003754 if (!SkipIvars.empty()) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003755 unsigned int LastIndex = SkipIvars.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003756 int LastByteSkipped =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003757 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003758 LastIndex = IvarsInfo.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003759 int LastByteScanned =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003760 IvarsInfo[LastIndex].ivar_bytepos +
3761 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003762 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramerd20ef752009-12-25 15:43:36 +00003763 if (LastByteSkipped > LastByteScanned) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003764 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003765 SKIP_SCAN SkScan;
3766 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3767 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003768 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003769 }
3770 }
3771 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3772 // as 0xMN.
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003773 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003774 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003775 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3776 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3777 // 0xM0 followed by 0x0N detected.
3778 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
3779 for (int j = i+1; j < SkipScan; j++)
3780 SkipScanIvars[j] = SkipScanIvars[j+1];
3781 --SkipScan;
3782 }
3783 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003784
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003785 // Generate the string.
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003786 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003787 unsigned char byte;
3788 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
3789 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
3790 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
3791 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003792
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003793 // first skip big.
3794 for (unsigned int ix = 0; ix < skip_big; ix++)
3795 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003796
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003797 // next (skip small, scan)
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003798 if (skip_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003799 byte = skip_small << 4;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003800 if (scan_big > 0) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003801 byte |= 0xf;
3802 --scan_big;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003803 } else if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003804 byte |= scan_small;
3805 scan_small = 0;
3806 }
3807 BitMap += byte;
3808 }
3809 // next scan big
3810 for (unsigned int ix = 0; ix < scan_big; ix++)
3811 BitMap += (unsigned char)(0x0f);
3812 // last scan small
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003813 if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003814 byte = scan_small;
3815 BitMap += byte;
3816 }
3817 }
3818 // null terminate string.
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003819 unsigned char zero = 0;
3820 BitMap += zero;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003821
3822 llvm::GlobalVariable * Entry =
3823 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3824 llvm::ConstantArray::get(VMContext, BitMap.c_str()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003825 ((ObjCABI == 2) ?
3826 "__TEXT,__objc_classname,cstring_literals" :
3827 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003828 1, true);
3829 return getConstantGEP(VMContext, Entry, 0, 0);
3830}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003831
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003832/// BuildIvarLayout - Builds ivar layout bitmap for the class
3833/// implementation for the __strong or __weak case.
3834/// The layout map displays which words in ivar list must be skipped
3835/// and which must be scanned by GC (see below). String is built of bytes.
3836/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
3837/// of words to skip and right nibble is count of words to scan. So, each
3838/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
3839/// represented by a 0x00 byte which also ends the string.
3840/// 1. when ForStrongLayout is true, following ivars are scanned:
3841/// - id, Class
3842/// - object *
3843/// - __strong anything
3844///
3845/// 2. When ForStrongLayout is false, following ivars are scanned:
3846/// - __weak anything
3847///
3848llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
3849 const ObjCImplementationDecl *OMD,
3850 bool ForStrongLayout) {
3851 bool hasUnion = false;
3852
3853 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
3854 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
3855 return llvm::Constant::getNullValue(PtrTy);
3856
Fariborz Jahaniana50b3a22010-08-20 21:21:08 +00003857 llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003858 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
Fariborz Jahaniana50b3a22010-08-20 21:21:08 +00003859 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003860
Fariborz Jahaniana50b3a22010-08-20 21:21:08 +00003861 llvm::SmallVector<FieldDecl*, 32> RecFields;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003862 for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
3863 RecFields.push_back(cast<FieldDecl>(Ivars[k]));
3864
3865 if (RecFields.empty())
3866 return llvm::Constant::getNullValue(PtrTy);
3867
3868 SkipIvars.clear();
3869 IvarsInfo.clear();
3870
3871 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
3872 if (IvarsInfo.empty())
3873 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00003874 // Sort on byte position in case we encounterred a union nested in
3875 // the ivar list.
3876 if (hasUnion && !IvarsInfo.empty())
3877 std::sort(IvarsInfo.begin(), IvarsInfo.end());
3878 if (hasUnion && !SkipIvars.empty())
3879 std::sort(SkipIvars.begin(), SkipIvars.end());
3880
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003881 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00003882 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003883
3884 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003885 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00003886 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar56df9772010-08-17 22:39:59 +00003887 OMD->getClassInterface()->getName().data());
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00003888 const unsigned char *s = (unsigned char*)BitMap.c_str();
3889 for (unsigned i = 0; i < BitMap.size(); i++)
3890 if (!(s[i] & 0xf0))
3891 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
3892 else
3893 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
3894 printf("\n");
3895 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003896 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00003897}
3898
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003899llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003900 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3901
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003902 // FIXME: Avoid std::string copying.
3903 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003904 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Owen Anderson41a75022009-08-13 21:57:51 +00003905 llvm::ConstantArray::get(VMContext, Sel.getAsString()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003906 ((ObjCABI == 2) ?
3907 "__TEXT,__objc_methname,cstring_literals" :
3908 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003909 1, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003910
Owen Anderson170229f2009-07-14 23:10:40 +00003911 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003912}
3913
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003914// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003915llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003916 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
3917}
3918
Daniel Dunbarf5c18462009-04-20 06:54:31 +00003919llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00003920 std::string TypeStr;
3921 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
3922
3923 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarb036db82008-08-13 03:21:16 +00003924
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003925 if (!Entry)
3926 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson41a75022009-08-13 21:57:51 +00003927 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003928 ((ObjCABI == 2) ?
3929 "__TEXT,__objc_methtype,cstring_literals" :
3930 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003931 1, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003932
Owen Anderson170229f2009-07-14 23:10:40 +00003933 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003934}
3935
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003936llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003937 std::string TypeStr;
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003938 CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
3939 TypeStr);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00003940
3941 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3942
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003943 if (!Entry)
3944 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson41a75022009-08-13 21:57:51 +00003945 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003946 ((ObjCABI == 2) ?
3947 "__TEXT,__objc_methtype,cstring_literals" :
3948 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003949 1, true);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00003950
Owen Anderson170229f2009-07-14 23:10:40 +00003951 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003952}
3953
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003954// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003955llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003956 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003957
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003958 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003959 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003960 llvm::ConstantArray::get(VMContext,
3961 Ident->getNameStart()),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003962 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003963 1, true);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003964
Owen Anderson170229f2009-07-14 23:10:40 +00003965 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003966}
3967
3968// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00003969// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003970llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003971CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
3972 const Decl *Container) {
Daniel Dunbar4932b362008-08-28 04:38:10 +00003973 std::string TypeStr;
3974 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003975 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
3976}
3977
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003978void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003979 const ObjCContainerDecl *CD,
Daniel Dunbard2386812009-10-19 01:21:19 +00003980 llvm::SmallVectorImpl<char> &Name) {
3981 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00003982 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00003983 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
3984 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003985 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00003986 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramerb11416d2010-04-17 09:33:03 +00003987 OS << '(' << CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00003988 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003989}
3990
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003991void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003992 EmitModuleInfo();
3993
Daniel Dunbarc475d422008-10-29 22:36:39 +00003994 // Emit the dummy bodies for any protocols which were referenced but
3995 // never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003996 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerf56501c2009-07-17 23:57:13 +00003997 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
3998 if (I->second->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00003999 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004000
Daniel Dunbarc475d422008-10-29 22:36:39 +00004001 std::vector<llvm::Constant*> Values(5);
Owen Anderson0b75f232009-07-31 20:28:54 +00004002 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004003 Values[1] = GetClassName(I->first);
Owen Anderson0b75f232009-07-31 20:28:54 +00004004 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004005 Values[3] = Values[4] =
Owen Anderson0b75f232009-07-31 20:28:54 +00004006 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004007 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004008 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarc475d422008-10-29 22:36:39 +00004009 Values));
Chris Lattnerf56501c2009-07-17 23:57:13 +00004010 CGM.AddUsedGlobal(I->second);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004011 }
4012
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004013 // Add assembler directives to add lazy undefined symbol references
4014 // for classes which are referenced but not defined. This is
4015 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00004016 //
4017 // FIXME: It would be nice if we had an LLVM construct for this.
4018 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
4019 llvm::SmallString<256> Asm;
4020 Asm += CGM.getModule().getModuleInlineAsm();
4021 if (!Asm.empty() && Asm.back() != '\n')
4022 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004023
Daniel Dunbard027a922009-09-07 00:20:42 +00004024 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbard027a922009-09-07 00:20:42 +00004025 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4026 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar07d07852009-10-18 21:17:35 +00004027 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4028 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnera299f2c2010-04-17 18:26:20 +00004029 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004030 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnera299f2c2010-04-17 18:26:20 +00004031 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004032 }
4033
4034 for (size_t i = 0; i < DefinedCategoryNames.size(); ++i) {
4035 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4036 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4037 }
Chris Lattnera299f2c2010-04-17 18:26:20 +00004038
Daniel Dunbard027a922009-09-07 00:20:42 +00004039 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004040 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004041}
4042
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004043CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004044 : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00004045 ObjCTypes(cgm) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004046 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004047 ObjCABI = 2;
4048}
4049
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004050/* *** */
4051
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004052ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004053 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004054 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4055 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004056
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004057 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004058 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004059 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004060 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Benjamin Kramerabd5b902009-10-13 10:07:13 +00004061 Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004062
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004063 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004064 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004065 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004066
Mike Stump18bb9282009-05-16 07:57:57 +00004067 // FIXME: It would be nice to unify this with the opaque type, so that the IR
4068 // comes out a bit cleaner.
Daniel Dunbarb036db82008-08-13 03:21:16 +00004069 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004070 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004071
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004072 // I'm not sure I like this. The implicit coordination is a bit
4073 // gross. We should solve this in a reasonable fashion because this
4074 // is a pretty common task (match some runtime data structure with
4075 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004076
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004077 // FIXME: This is leaked.
4078 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004079
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004080 // struct _objc_super {
4081 // id self;
4082 // Class cls;
4083 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00004084 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00004085 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00004086 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004087 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004088 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004089 Ctx.getObjCIdType(), 0, 0, false));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004090 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004091 Ctx.getObjCClassType(), 0, 0, false));
Douglas Gregord5058122010-02-11 01:19:42 +00004092 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004093
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004094 SuperCTy = Ctx.getTagDeclType(RD);
4095 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004096
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004097 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004098 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4099
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004100 // struct _prop_t {
4101 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004102 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004103 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004104 PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004105 CGM.getModule().addTypeName("struct._prop_t",
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004106 PropertyTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004107
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004108 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004109 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004110 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004111 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004112 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004113 PropertyListTy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004114 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004115 llvm::ArrayType::get(PropertyTy, 0),
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004116 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004117 CGM.getModule().addTypeName("struct._prop_list_t",
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004118 PropertyListTy);
4119 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004120 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004121
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004122 // struct _objc_method {
4123 // SEL _cmd;
4124 // char *method_type;
4125 // char *_imp;
4126 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004127 MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004128 Int8PtrTy,
4129 Int8PtrTy,
4130 NULL);
4131 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004132
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004133 // struct _objc_cache *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004134 CacheTy = llvm::OpaqueType::get(VMContext);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004135 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004136 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004137}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004138
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004139ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004140 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004141 // struct _objc_method_description {
4142 // SEL name;
4143 // char *types;
4144 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004145 MethodDescriptionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004146 llvm::StructType::get(VMContext, SelectorPtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004147 Int8PtrTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00004148 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004149 CGM.getModule().addTypeName("struct._objc_method_description",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004150 MethodDescriptionTy);
4151
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004152 // struct _objc_method_description_list {
4153 // int count;
4154 // struct _objc_method_description[1];
4155 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004156 MethodDescriptionListTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004157 llvm::StructType::get(VMContext, IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004158 llvm::ArrayType::get(MethodDescriptionTy, 0),
Daniel Dunbarb036db82008-08-13 03:21:16 +00004159 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004160 CGM.getModule().addTypeName("struct._objc_method_description_list",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004161 MethodDescriptionListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004162
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004163 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004164 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004165 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004166
Daniel Dunbarb036db82008-08-13 03:21:16 +00004167 // Protocol description structures
4168
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004169 // struct _objc_protocol_extension {
4170 // uint32_t size; // sizeof(struct _objc_protocol_extension)
4171 // struct _objc_method_description_list *optional_instance_methods;
4172 // struct _objc_method_description_list *optional_class_methods;
4173 // struct _objc_property_list *instance_properties;
4174 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004175 ProtocolExtensionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004176 llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004177 MethodDescriptionListPtrTy,
4178 MethodDescriptionListPtrTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00004179 PropertyListPtrTy,
4180 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004181 CGM.getModule().addTypeName("struct._objc_protocol_extension",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004182 ProtocolExtensionTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004183
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004184 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004185 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004186
Daniel Dunbarc475d422008-10-29 22:36:39 +00004187 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00004188
Owen Andersonc36edfe2009-08-13 23:27:53 +00004189 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
4190 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004191
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004192 const llvm::Type *T =
Mike Stump11289f42009-09-09 15:08:12 +00004193 llvm::StructType::get(VMContext,
Owen Anderson758428f2009-08-05 23:18:46 +00004194 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004195 LongTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004196 llvm::ArrayType::get(ProtocolTyHolder, 0),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004197 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004198 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
4199
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004200 // struct _objc_protocol {
4201 // struct _objc_protocol_extension *isa;
4202 // char *protocol_name;
4203 // struct _objc_protocol **_objc_protocol_list;
4204 // struct _objc_method_description_list *instance_methods;
4205 // struct _objc_method_description_list *class_methods;
4206 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004207 T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004208 Int8PtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004209 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Daniel Dunbarb036db82008-08-13 03:21:16 +00004210 MethodDescriptionListPtrTy,
4211 MethodDescriptionListPtrTy,
4212 NULL);
4213 cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
4214
4215 ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004216 CGM.getModule().addTypeName("struct._objc_protocol_list",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004217 ProtocolListTy);
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004218 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004219 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004220
4221 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004222 CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004223 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004224
4225 // Class description structures
4226
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004227 // struct _objc_ivar {
4228 // char *ivar_name;
4229 // char *ivar_type;
4230 // int ivar_offset;
4231 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004232 IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004233 Int8PtrTy,
4234 IntTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004235 NULL);
4236 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
4237
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004238 // struct _objc_ivar_list *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004239 IvarListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004240 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004241 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004242
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004243 // struct _objc_method_list *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004244 MethodListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004245 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004246 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004247
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004248 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004249 ClassExtensionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004250 llvm::StructType::get(VMContext, IntTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004251 Int8PtrTy,
4252 PropertyListPtrTy,
4253 NULL);
4254 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004255 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004256
Owen Andersonc36edfe2009-08-13 23:27:53 +00004257 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004258
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004259 // struct _objc_class {
4260 // Class isa;
4261 // Class super_class;
4262 // char *name;
4263 // long version;
4264 // long info;
4265 // long instance_size;
4266 // struct _objc_ivar_list *ivars;
4267 // struct _objc_method_list *methods;
4268 // struct _objc_cache *cache;
4269 // struct _objc_protocol_list *protocols;
4270 // char *ivar_layout;
4271 // struct _objc_class_ext *ext;
4272 // };
Owen Anderson758428f2009-08-05 23:18:46 +00004273 T = llvm::StructType::get(VMContext,
4274 llvm::PointerType::getUnqual(ClassTyHolder),
Owen Anderson9793f0e2009-07-29 22:16:19 +00004275 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004276 Int8PtrTy,
4277 LongTy,
4278 LongTy,
4279 LongTy,
4280 IvarListPtrTy,
4281 MethodListPtrTy,
4282 CachePtrTy,
4283 ProtocolListPtrTy,
4284 Int8PtrTy,
4285 ClassExtensionPtrTy,
4286 NULL);
4287 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004288
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004289 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
4290 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004291 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004292
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004293 // struct _objc_category {
4294 // char *category_name;
4295 // char *class_name;
4296 // struct _objc_method_list *instance_method;
4297 // struct _objc_method_list *class_method;
4298 // uint32_t size; // sizeof(struct _objc_category)
4299 // struct _objc_property_list *instance_properties;// category's @property
4300 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004301 CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004302 Int8PtrTy,
4303 MethodListPtrTy,
4304 MethodListPtrTy,
4305 ProtocolListPtrTy,
4306 IntTy,
4307 PropertyListPtrTy,
4308 NULL);
4309 CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
4310
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004311 // Global metadata structures
4312
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004313 // struct _objc_symtab {
4314 // long sel_ref_cnt;
4315 // SEL *refs;
4316 // short cls_def_cnt;
4317 // short cat_def_cnt;
4318 // char *defs[cls_def_cnt + cat_def_cnt];
4319 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004320 SymtabTy = llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004321 SelectorPtrTy,
4322 ShortTy,
4323 ShortTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004324 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004325 NULL);
4326 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004327 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004328
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00004329 // struct _objc_module {
4330 // long version;
4331 // long size; // sizeof(struct _objc_module)
4332 // char *name;
4333 // struct _objc_symtab* symtab;
4334 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004335 ModuleTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004336 llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004337 LongTy,
4338 Int8PtrTy,
4339 SymtabPtrTy,
4340 NULL);
4341 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00004342
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004343
Mike Stump18bb9282009-05-16 07:57:57 +00004344 // FIXME: This is the size of the setjmp buffer and should be target
4345 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00004346 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004347
Anders Carlsson9ff22482008-09-09 10:10:21 +00004348 // Exceptions
Owen Anderson9793f0e2009-07-29 22:16:19 +00004349 const llvm::Type *StackPtrTy = llvm::ArrayType::get(
Benjamin Kramerabd5b902009-10-13 10:07:13 +00004350 llvm::Type::getInt8PtrTy(VMContext), 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004351
4352 ExceptionDataTy =
Chris Lattner5e016ae2010-06-27 07:15:29 +00004353 llvm::StructType::get(VMContext,
4354 llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
4355 SetJmpBufferSize),
Anders Carlsson9ff22482008-09-09 10:10:21 +00004356 StackPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004357 CGM.getModule().addTypeName("struct._objc_exception_data",
Anders Carlsson9ff22482008-09-09 10:10:21 +00004358 ExceptionDataTy);
4359
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00004360}
4361
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004362ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004363 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004364 // struct _method_list_t {
4365 // uint32_t entsize; // sizeof(struct _objc_method)
4366 // uint32_t method_count;
4367 // struct _objc_method method_list[method_count];
4368 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004369 MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004370 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004371 llvm::ArrayType::get(MethodTy, 0),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004372 NULL);
4373 CGM.getModule().addTypeName("struct.__method_list_t",
4374 MethodListnfABITy);
4375 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004376 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004377
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004378 // struct _protocol_t {
4379 // id isa; // NULL
4380 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004381 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004382 // const struct method_list_t * const instance_methods;
4383 // const struct method_list_t * const class_methods;
4384 // const struct method_list_t *optionalInstanceMethods;
4385 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004386 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004387 // const uint32_t size; // sizeof(struct _protocol_t)
4388 // const uint32_t flags; // = 0
4389 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004390
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004391 // Holder for struct _protocol_list_t *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004392 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004393
Owen Anderson758428f2009-08-05 23:18:46 +00004394 ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004395 Int8PtrTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004396 llvm::PointerType::getUnqual(
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004397 ProtocolListTyHolder),
4398 MethodListnfABIPtrTy,
4399 MethodListnfABIPtrTy,
4400 MethodListnfABIPtrTy,
4401 MethodListnfABIPtrTy,
4402 PropertyListPtrTy,
4403 IntTy,
4404 IntTy,
4405 NULL);
4406 CGM.getModule().addTypeName("struct._protocol_t",
4407 ProtocolnfABITy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004408
4409 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004410 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004411
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004412 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004413 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004414 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004415 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004416 ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004417 llvm::ArrayType::get(
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004418 ProtocolnfABIPtrTy, 0),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004419 NULL);
4420 CGM.getModule().addTypeName("struct._objc_protocol_list",
4421 ProtocolListnfABITy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004422 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004423 ProtocolListnfABITy);
4424
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004425 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004426 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004427
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004428 // struct _ivar_t {
4429 // unsigned long int *offset; // pointer to ivar offset location
4430 // char *name;
4431 // char *type;
4432 // uint32_t alignment;
4433 // uint32_t size;
4434 // }
Mike Stump11289f42009-09-09 15:08:12 +00004435 IvarnfABITy = llvm::StructType::get(VMContext,
Owen Anderson758428f2009-08-05 23:18:46 +00004436 llvm::PointerType::getUnqual(LongTy),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004437 Int8PtrTy,
4438 Int8PtrTy,
4439 IntTy,
4440 IntTy,
4441 NULL);
4442 CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004443
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004444 // struct _ivar_list_t {
4445 // uint32 entsize; // sizeof(struct _ivar_t)
4446 // uint32 count;
4447 // struct _iver_t list[count];
4448 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004449 IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004450 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004451 llvm::ArrayType::get(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004452 IvarnfABITy, 0),
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004453 NULL);
4454 CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004455
Owen Anderson9793f0e2009-07-29 22:16:19 +00004456 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004457
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004458 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004459 // uint32_t const flags;
4460 // uint32_t const instanceStart;
4461 // uint32_t const instanceSize;
4462 // uint32_t const reserved; // only when building for 64bit targets
4463 // const uint8_t * const ivarLayout;
4464 // const char *const name;
4465 // const struct _method_list_t * const baseMethods;
4466 // const struct _objc_protocol_list *const baseProtocols;
4467 // const struct _ivar_list_t *const ivars;
4468 // const uint8_t * const weakIvarLayout;
4469 // const struct _prop_list_t * const properties;
4470 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004471
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004472 // FIXME. Add 'reserved' field in 64bit abi mode!
Owen Anderson758428f2009-08-05 23:18:46 +00004473 ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004474 IntTy,
4475 IntTy,
4476 Int8PtrTy,
4477 Int8PtrTy,
4478 MethodListnfABIPtrTy,
4479 ProtocolListnfABIPtrTy,
4480 IvarListnfABIPtrTy,
4481 Int8PtrTy,
4482 PropertyListPtrTy,
4483 NULL);
4484 CGM.getModule().addTypeName("struct._class_ro_t",
4485 ClassRonfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004486
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004487 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
John McCall9dc0db22011-05-15 01:53:33 +00004488 const llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
4489 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
4490 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004491
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004492 // struct _class_t {
4493 // struct _class_t *isa;
4494 // struct _class_t * const superclass;
4495 // void *cache;
4496 // IMP *vtable;
4497 // struct class_ro_t *ro;
4498 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004499
Owen Andersonc36edfe2009-08-13 23:27:53 +00004500 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Owen Anderson170229f2009-07-14 23:10:40 +00004501 ClassnfABITy =
Owen Anderson758428f2009-08-05 23:18:46 +00004502 llvm::StructType::get(VMContext,
4503 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004504 llvm::PointerType::getUnqual(ClassTyHolder),
4505 CachePtrTy,
4506 llvm::PointerType::getUnqual(ImpnfABITy),
4507 llvm::PointerType::getUnqual(ClassRonfABITy),
4508 NULL);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004509 CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
4510
4511 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004512 ClassnfABITy);
4513
Fariborz Jahanian71394042009-01-23 23:53:38 +00004514 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004515 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004516
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004517 // struct _category_t {
4518 // const char * const name;
4519 // struct _class_t *const cls;
4520 // const struct _method_list_t * const instance_methods;
4521 // const struct _method_list_t * const class_methods;
4522 // const struct _protocol_list_t * const protocols;
4523 // const struct _prop_list_t * const properties;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00004524 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004525 CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
Fariborz Jahanian71394042009-01-23 23:53:38 +00004526 ClassnfABIPtrTy,
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00004527 MethodListnfABIPtrTy,
4528 MethodListnfABIPtrTy,
4529 ProtocolListnfABIPtrTy,
4530 PropertyListPtrTy,
4531 NULL);
4532 CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004533
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004534 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004535 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4536 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004537
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004538 // MessageRefTy - LLVM for:
4539 // struct _message_ref_t {
4540 // IMP messenger;
4541 // SEL name;
4542 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004543
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004544 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00004545 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00004546 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00004547 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004548 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004549 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004550 Ctx.VoidPtrTy, 0, 0, false));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004551 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004552 Ctx.getObjCSelType(), 0, 0, false));
Douglas Gregord5058122010-02-11 01:19:42 +00004553 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004554
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004555 MessageRefCTy = Ctx.getTagDeclType(RD);
4556 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4557 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004558
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004559 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004560 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004561
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004562 // SuperMessageRefTy - LLVM for:
4563 // struct _super_message_ref_t {
4564 // SUPER_IMP messenger;
4565 // SEL name;
4566 // };
Owen Anderson758428f2009-08-05 23:18:46 +00004567 SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004568 SelectorPtrTy,
4569 NULL);
4570 CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004571
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004572 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004573 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
4574
Daniel Dunbarb1559a42009-03-01 04:46:24 +00004575
4576 // struct objc_typeinfo {
4577 // const void** vtable; // objc_ehtype_vtable + 2
4578 // const char* name; // c++ typeinfo string
4579 // Class cls;
4580 // };
Owen Anderson758428f2009-08-05 23:18:46 +00004581 EHTypeTy = llvm::StructType::get(VMContext,
4582 llvm::PointerType::getUnqual(Int8PtrTy),
Daniel Dunbarb1559a42009-03-01 04:46:24 +00004583 Int8PtrTy,
4584 ClassnfABIPtrTy,
4585 NULL);
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00004586 CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004587 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00004588}
4589
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004590llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004591 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004592
Fariborz Jahanian71394042009-01-23 23:53:38 +00004593 return NULL;
4594}
4595
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004596void CGObjCNonFragileABIMac::AddModuleClassList(const
4597 std::vector<llvm::GlobalValue*>
4598 &Container,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004599 const char *SymbolName,
4600 const char *SectionName) {
4601 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004602
Daniel Dunbar19573e72009-05-15 21:48:48 +00004603 if (!NumClasses)
4604 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004605
Daniel Dunbar19573e72009-05-15 21:48:48 +00004606 std::vector<llvm::Constant*> Symbols(NumClasses);
4607 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00004608 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00004609 ObjCTypes.Int8PtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004610 llvm::Constant* Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004611 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004612 NumClasses),
4613 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004614
Daniel Dunbar19573e72009-05-15 21:48:48 +00004615 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00004616 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004617 llvm::GlobalValue::InternalLinkage,
4618 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00004619 SymbolName);
Daniel Dunbar710cb202010-04-25 20:39:32 +00004620 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00004621 GV->setSection(SectionName);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004622 CGM.AddUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00004623}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004624
Fariborz Jahanian71394042009-01-23 23:53:38 +00004625void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4626 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004627
Daniel Dunbar19573e72009-05-15 21:48:48 +00004628 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00004629 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004630 AddModuleClassList(DefinedClasses,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004631 "\01L_OBJC_LABEL_CLASS_$",
4632 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahanian67260552009-11-17 21:37:35 +00004633
Fariborz Jahanian67260552009-11-17 21:37:35 +00004634 for (unsigned i = 0; i < DefinedClasses.size(); i++) {
4635 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
4636 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4637 continue;
4638 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahanian67260552009-11-17 21:37:35 +00004639 }
4640
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004641 for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
4642 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
4643 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4644 continue;
4645 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4646 }
Fariborz Jahanian67260552009-11-17 21:37:35 +00004647
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004648 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004649 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4650 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004651
Fariborz Jahanian279abd32009-01-30 20:55:31 +00004652 // Build list of all implemented category addresses in array
4653 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004654 AddModuleClassList(DefinedCategories,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004655 "\01L_OBJC_LABEL_CATEGORY_$",
4656 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004657 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004658 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4659 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004660
Daniel Dunbar5e639272010-04-25 20:39:01 +00004661 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00004662}
4663
John McCall9e8bb002011-05-14 03:10:52 +00004664/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
4665/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004666/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004667/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00004668bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
4669 // At various points we've experimented with using vtable-based
4670 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004671 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
4672 default:
John McCall9e8bb002011-05-14 03:10:52 +00004673 llvm_unreachable("Invalid dispatch method!");
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004674 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00004675 return false;
John McCall9e8bb002011-05-14 03:10:52 +00004676 case CodeGenOptions::NonLegacy:
4677 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004678 case CodeGenOptions::Mixed:
4679 break;
4680 }
4681
4682 // If so, see whether this selector is in the white-list of things which must
4683 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00004684 if (VTableDispatchMethods.empty()) {
4685 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
4686 VTableDispatchMethods.insert(GetNullarySelector("class"));
4687 VTableDispatchMethods.insert(GetNullarySelector("self"));
4688 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
4689 VTableDispatchMethods.insert(GetNullarySelector("length"));
4690 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004691
John McCall9e8bb002011-05-14 03:10:52 +00004692 // These are vtable-based if GC is disabled.
4693 // Optimistically use vtable dispatch for hybrid compiles.
4694 if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) {
4695 VTableDispatchMethods.insert(GetNullarySelector("retain"));
4696 VTableDispatchMethods.insert(GetNullarySelector("release"));
4697 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
4698 }
4699
4700 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
4701 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
4702 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
4703 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
4704 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
4705 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
4706 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
4707
4708 // These are vtable-based if GC is enabled.
4709 // Optimistically use vtable dispatch for hybrid compiles.
4710 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
4711 VTableDispatchMethods.insert(GetNullarySelector("hash"));
4712 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
4713
4714 // "countByEnumeratingWithState:objects:count"
4715 IdentifierInfo *KeyIdents[] = {
4716 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
4717 &CGM.getContext().Idents.get("objects"),
4718 &CGM.getContext().Idents.get("count")
4719 };
4720 VTableDispatchMethods.insert(
4721 CGM.getContext().Selectors.getSelector(3, KeyIdents));
4722 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004723 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004724
John McCall9e8bb002011-05-14 03:10:52 +00004725 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004726}
4727
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004728// Metadata flags
4729enum MetaDataDlags {
4730 CLS = 0x0,
4731 CLS_META = 0x1,
4732 CLS_ROOT = 0x2,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004733 OBJC2_CLS_HIDDEN = 0x10,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004734 CLS_EXCEPTION = 0x20
4735};
4736/// BuildClassRoTInitializer - generate meta-data for:
4737/// struct _class_ro_t {
4738/// uint32_t const flags;
4739/// uint32_t const instanceStart;
4740/// uint32_t const instanceSize;
4741/// uint32_t const reserved; // only when building for 64bit targets
4742/// const uint8_t * const ivarLayout;
4743/// const char *const name;
4744/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004745/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004746/// const struct _ivar_list_t *const ivars;
4747/// const uint8_t * const weakIvarLayout;
4748/// const struct _prop_list_t * const properties;
4749/// }
4750///
4751llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004752 unsigned flags,
4753 unsigned InstanceStart,
4754 unsigned InstanceSize,
4755 const ObjCImplementationDecl *ID) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004756 std::string ClassName = ID->getNameAsString();
4757 std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004758 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4759 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
4760 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004761 // FIXME. For 64bit targets add 0 here.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004762 Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4763 : BuildIvarLayout(ID, true);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004764 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004765 // const struct _method_list_t * const baseMethods;
4766 std::vector<llvm::Constant*> Methods;
4767 std::string MethodListName("\01l_OBJC_$_");
4768 if (flags & CLS_META) {
4769 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004770 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004771 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004772 // Class methods should always be defined.
4773 Methods.push_back(GetMethodConstant(*i));
4774 }
4775 } else {
4776 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004777 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004778 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004779 // Instance methods should always be defined.
4780 Methods.push_back(GetMethodConstant(*i));
4781 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004782 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004783 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004784 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004785
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004786 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4787 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004788
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004789 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
4790 if (llvm::Constant *C = GetMethodConstant(MD))
4791 Methods.push_back(C);
4792 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
4793 if (llvm::Constant *C = GetMethodConstant(MD))
4794 Methods.push_back(C);
4795 }
4796 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004797 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004798 Values[ 5] = EmitMethodList(MethodListName,
4799 "__DATA, __objc_const", Methods);
4800
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004801 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4802 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004803 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00004804 + OID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00004805 OID->all_referenced_protocol_begin(),
4806 OID->all_referenced_protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004807
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00004808 if (flags & CLS_META)
Owen Anderson0b75f232009-07-31 20:28:54 +00004809 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00004810 else
4811 Values[ 7] = EmitIvarList(ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004812 Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4813 : BuildIvarLayout(ID, false);
Fariborz Jahanian066347e2009-01-28 22:18:42 +00004814 if (flags & CLS_META)
Owen Anderson0b75f232009-07-31 20:28:54 +00004815 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian066347e2009-01-28 22:18:42 +00004816 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00004817 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4818 ID, ID->getClassInterface(), ObjCTypes);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004819 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004820 Values);
4821 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004822 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
4823 llvm::GlobalValue::InternalLinkage,
4824 Init,
4825 (flags & CLS_META) ?
4826 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
4827 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00004828 CLASS_RO_GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00004829 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00004830 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004831 return CLASS_RO_GV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00004832
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004833}
4834
4835/// BuildClassMetaData - This routine defines that to-level meta-data
4836/// for the given ClassName for:
4837/// struct _class_t {
4838/// struct _class_t *isa;
4839/// struct _class_t * const superclass;
4840/// void *cache;
4841/// IMP *vtable;
4842/// struct class_ro_t *ro;
4843/// }
4844///
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004845llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004846 std::string &ClassName,
4847 llvm::Constant *IsAGV,
4848 llvm::Constant *SuperClassGV,
4849 llvm::Constant *ClassRoGV,
4850 bool HiddenVisibility) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004851 std::vector<llvm::Constant*> Values(5);
4852 Values[0] = IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004853 Values[1] = SuperClassGV;
4854 if (!Values[1])
4855 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004856 Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
4857 Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4858 Values[4] = ClassRoGV; // &CLASS_RO_GV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004859 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004860 Values);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00004861 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4862 GV->setInitializer(Init);
Fariborz Jahanian04087232009-01-31 01:07:39 +00004863 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00004864 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00004865 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian82208252009-01-31 00:59:10 +00004866 if (HiddenVisibility)
4867 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004868 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004869}
4870
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004871bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00004872CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004873 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004874}
4875
Daniel Dunbar961202372009-05-03 12:57:56 +00004876void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00004877 uint32_t &InstanceStart,
4878 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004879 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00004880 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004881
Daniel Dunbar9b042e02009-05-04 23:23:09 +00004882 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00004883 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00004884
4885 // If there are no fields, the start is the same as the end.
4886 if (!RL.getFieldCount())
4887 InstanceStart = InstanceSize;
4888 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00004889 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00004890}
4891
Fariborz Jahanian71394042009-01-23 23:53:38 +00004892void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
4893 std::string ClassName = ID->getNameAsString();
4894 if (!ObjCEmptyCacheVar) {
4895 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004896 CGM.getModule(),
4897 ObjCTypes.CacheTy,
4898 false,
4899 llvm::GlobalValue::ExternalLinkage,
4900 0,
4901 "_objc_empty_cache");
4902
Fariborz Jahanian71394042009-01-23 23:53:38 +00004903 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004904 CGM.getModule(),
4905 ObjCTypes.ImpnfABITy,
4906 false,
4907 llvm::GlobalValue::ExternalLinkage,
4908 0,
4909 "_objc_empty_vtable");
Fariborz Jahanian71394042009-01-23 23:53:38 +00004910 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004911 assert(ID->getClassInterface() &&
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004912 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00004913 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004914 uint32_t InstanceStart =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00004915 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004916 uint32_t InstanceSize = InstanceStart;
4917 uint32_t flags = CLS_META;
Daniel Dunbar15894b72009-04-07 05:48:37 +00004918 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4919 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004920
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004921 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004922
4923 bool classIsHidden =
John McCall457a04e2010-10-22 21:05:15 +00004924 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00004925 if (classIsHidden)
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004926 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00004927 if (ID->getNumIvarInitializers())
4928 flags |= eClassFlags_ABI2_HasCXXStructors;
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004929 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004930 // class is root
4931 flags |= CLS_ROOT;
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00004932 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004933 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004934 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004935 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00004936 const ObjCInterfaceDecl *Root = ID->getClassInterface();
4937 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4938 Root = Super;
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004939 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00004940 if (Root->isWeakImported())
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004941 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00004942 // work on super class metadata symbol.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004943 std::string SuperClassName =
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004944 ObjCMetaClassName +
4945 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004946 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00004947 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00004948 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004949 }
4950 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4951 InstanceStart,
4952 InstanceSize,ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004953 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004954 llvm::GlobalVariable *MetaTClass =
Fariborz Jahanian82208252009-01-31 00:59:10 +00004955 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4956 classIsHidden);
Fariborz Jahanian67260552009-11-17 21:37:35 +00004957 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00004958
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004959 // Metadata for the class
4960 flags = CLS;
Fariborz Jahanian82208252009-01-31 00:59:10 +00004961 if (classIsHidden)
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004962 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00004963 if (ID->getNumIvarInitializers())
4964 flags |= eClassFlags_ABI2_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00004965
Douglas Gregor78bd61f2009-06-18 16:11:24 +00004966 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
Daniel Dunbar8f28d012009-04-08 04:21:03 +00004967 flags |= CLS_EXCEPTION;
4968
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004969 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004970 flags |= CLS_ROOT;
4971 SuperClassGV = 0;
Chris Lattnerb433b272009-04-19 06:02:28 +00004972 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004973 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00004974 std::string RootClassName =
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004975 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00004976 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00004977 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00004978 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004979 }
Daniel Dunbar961202372009-05-03 12:57:56 +00004980 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004981 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00004982 InstanceStart,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004983 InstanceSize,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00004984 ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004985
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004986 TClassName = ObjCClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004987 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian82208252009-01-31 00:59:10 +00004988 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
4989 classIsHidden);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00004990 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00004991
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004992 // Determine if this class is also "non-lazy".
4993 if (ImplementationIsNonLazy(ID))
4994 DefinedNonLazyClasses.push_back(ClassMD);
4995
Daniel Dunbar8f28d012009-04-08 04:21:03 +00004996 // Force the definition of the EHType if necessary.
4997 if (flags & CLS_EXCEPTION)
4998 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00004999 // Make sure method definition entries are all clear for next implementation.
5000 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005001}
5002
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005003/// GenerateProtocolRef - This routine is called to generate code for
5004/// a protocol reference expression; as in:
5005/// @code
5006/// @protocol(Proto1);
5007/// @endcode
5008/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5009/// which will hold address of the protocol meta-data.
5010///
5011llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005012 const ObjCProtocolDecl *PD) {
5013
Fariborz Jahanian464423d2009-04-10 18:47:34 +00005014 // This routine is called for @protocol only. So, we must build definition
5015 // of protocol's meta-data (not a reference to it!)
5016 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005017 llvm::Constant *Init =
5018 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
5019 ObjCTypes.ExternalProtocolPtrTy);
5020
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005021 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar56df9772010-08-17 22:39:59 +00005022 ProtocolName += PD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005023
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005024 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5025 if (PTGV)
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005026 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005027 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005028 CGM.getModule(),
5029 Init->getType(), false,
5030 llvm::GlobalValue::WeakAnyLinkage,
5031 Init,
5032 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005033 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5034 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005035 CGM.AddUsedGlobal(PTGV);
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005036 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005037}
5038
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005039/// GenerateCategory - Build metadata for a category implementation.
5040/// struct _category_t {
5041/// const char * const name;
5042/// struct _class_t *const cls;
5043/// const struct _method_list_t * const instance_methods;
5044/// const struct _method_list_t * const class_methods;
5045/// const struct _protocol_list_t * const protocols;
5046/// const struct _prop_list_t * const properties;
5047/// }
5048///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005049void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005050 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005051 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005052 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5053 "_$_" + OCD->getNameAsString());
5054 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar15894b72009-04-07 05:48:37 +00005055 Interface->getNameAsString());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005056
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005057 std::vector<llvm::Constant*> Values(6);
5058 Values[0] = GetClassName(OCD->getIdentifier());
5059 // meta-class entry symbol
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005060 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005061 if (Interface->isWeakImported())
Fariborz Jahanian3ad8dcf2009-11-17 22:02:21 +00005062 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5063
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005064 Values[1] = ClassGV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005065 std::vector<llvm::Constant*> Methods;
5066 std::string MethodListName(Prefix);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005067 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005068 "_$_" + OCD->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005069
5070 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005071 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005072 // Instance methods should always be defined.
5073 Methods.push_back(GetMethodConstant(*i));
5074 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005075
5076 Values[2] = EmitMethodList(MethodListName,
5077 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005078 Methods);
5079
5080 MethodListName = Prefix;
5081 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5082 OCD->getNameAsString();
5083 Methods.clear();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005084 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005085 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005086 // Class methods should always be defined.
5087 Methods.push_back(GetMethodConstant(*i));
5088 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005089
5090 Values[3] = EmitMethodList(MethodListName,
5091 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005092 Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005093 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00005094 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005095 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005096 llvm::SmallString<256> ExtName;
5097 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5098 << OCD->getName();
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005099 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005100 + Interface->getName() + "_$_"
5101 + Category->getName(),
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005102 Category->protocol_begin(),
5103 Category->protocol_end());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005104 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5105 OCD, Category, ObjCTypes);
Mike Stump658fe022009-07-30 22:28:39 +00005106 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00005107 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5108 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005109 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005110
5111 llvm::Constant *Init =
5112 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005113 Values);
5114 llvm::GlobalVariable *GCATV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005115 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005116 false,
5117 llvm::GlobalValue::InternalLinkage,
5118 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005119 ExtCatName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005120 GCATV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005121 CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005122 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005123 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005124 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005125
5126 // Determine if this category is also "non-lazy".
5127 if (ImplementationIsNonLazy(OCD))
5128 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005129 // method definition entries must be clear for next implementation.
5130 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005131}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005132
5133/// GetMethodConstant - Return a struct objc_method constant for the
5134/// given method if it has been defined. The result is null if the
5135/// method has not been defined. The return value has type MethodPtrTy.
5136llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005137 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005138 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005139 if (!Fn)
5140 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005141
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005142 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005143 Method[0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00005144 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005145 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005146 Method[1] = GetMethodVarType(MD);
Owen Andersonade90fd2009-07-29 18:54:39 +00005147 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005148 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005149}
5150
5151/// EmitMethodList - Build meta-data for method declarations
5152/// struct _method_list_t {
5153/// uint32_t entsize; // sizeof(struct _objc_method)
5154/// uint32_t method_count;
5155/// struct _objc_method method_list[method_count];
5156/// }
5157///
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005158llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
5159 const char *Section,
5160 const ConstantVector &Methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005161 // Return null for empty list.
5162 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005163 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005164
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005165 std::vector<llvm::Constant*> Values(3);
5166 // sizeof(struct _objc_method)
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005167 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005168 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005169 // method_count
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005170 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005171 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005172 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005173 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005174 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005175
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005176 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005177 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005178 llvm::GlobalValue::InternalLinkage,
5179 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005180 Name);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005181 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005182 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005183 GV->setSection(Section);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005184 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00005185 return llvm::ConstantExpr::getBitCast(GV,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005186 ObjCTypes.MethodListnfABIPtrTy);
5187}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005188
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005189/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5190/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005191llvm::GlobalVariable *
5192CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5193 const ObjCIvarDecl *Ivar) {
5194 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar3f86b9c2009-05-05 00:36:57 +00005195 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregorbcced4e2009-04-09 21:40:53 +00005196 '.' + Ivar->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005197 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005198 CGM.getModule().getGlobalVariable(Name);
5199 if (!IvarOffsetGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005200 IvarOffsetGV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005201 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005202 false,
5203 llvm::GlobalValue::ExternalLinkage,
5204 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005205 Name);
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005206 return IvarOffsetGV;
5207}
5208
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005209llvm::Constant *
5210CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5211 const ObjCIvarDecl *Ivar,
5212 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005213 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005214 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005215 Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005216 IvarOffsetGV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005217 CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005218
Mike Stump18bb9282009-05-16 07:57:57 +00005219 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
5220 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005221 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5222 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall457a04e2010-10-22 21:05:15 +00005223 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00005224 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00005225 else
Fariborz Jahanianbc3c77b2009-04-06 18:30:00 +00005226 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendlingf7d45982011-05-04 21:37:25 +00005227 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005228 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005229}
5230
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005231/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005232/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005233/// IvarListnfABIPtrTy.
5234/// struct _ivar_t {
5235/// unsigned long int *offset; // pointer to ivar offset location
5236/// char *name;
5237/// char *type;
5238/// uint32_t alignment;
5239/// uint32_t size;
5240/// }
5241/// struct _ivar_list_t {
5242/// uint32 entsize; // sizeof(struct _ivar_t)
5243/// uint32 count;
5244/// struct _iver_t list[count];
5245/// }
5246///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005247
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005248llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005249 const ObjCImplementationDecl *ID) {
5250
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005251 std::vector<llvm::Constant*> Ivars, Ivar(5);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005252
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005253 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5254 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005255
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005256 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005257
Daniel Dunbarae032262009-04-20 00:33:43 +00005258 // Collect declared and synthesized ivars in a small vector.
Fariborz Jahanian63a224a2009-03-31 18:11:23 +00005259 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian7c809592009-06-04 01:19:09 +00005260 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005261
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005262 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
5263 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian7c809592009-06-04 01:19:09 +00005264 // Ignore unnamed bit-fields.
5265 if (!IVD->getDeclName())
5266 continue;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005267 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar961202372009-05-03 12:57:56 +00005268 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005269 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5270 Ivar[2] = GetMethodVarType(IVD);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005271 const llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005272 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005273 unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005274 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005275 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005276 Align = llvm::Log2_32(Align);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005277 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00005278 // NOTE. Size of a bitfield does not match gcc's, because of the
5279 // way bitfields are treated special in each. But I am told that
5280 // 'size' for bitfield ivars is ignored by the runtime so it does
5281 // not matter. If it matters, there is enough info to get the
5282 // bitfield right!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005283 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005284 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005285 }
5286 // Return null for empty list.
5287 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005288 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005289 std::vector<llvm::Constant*> Values(3);
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005290 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005291 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5292 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005293 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005294 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005295 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005296 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005297 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5298 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005299 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005300 llvm::GlobalValue::InternalLinkage,
5301 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005302 Prefix + OID->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005303 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005304 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005305 GV->setSection("__DATA, __objc_const");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005306
Chris Lattnerf56501c2009-07-17 23:57:13 +00005307 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00005308 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005309}
5310
5311llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005312 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005313 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005314
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005315 if (!Entry) {
5316 // We use the initializer as a marker of whether this is a forward
5317 // reference or not. At module finalization we add the empty
5318 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005319 Entry =
5320 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5321 llvm::GlobalValue::ExternalLinkage,
5322 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005323 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005324 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005325 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005326
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005327 return Entry;
5328}
5329
5330/// GetOrEmitProtocol - Generate the protocol meta-data:
5331/// @code
5332/// struct _protocol_t {
5333/// id isa; // NULL
5334/// const char * const protocol_name;
5335/// const struct _protocol_list_t * protocol_list; // super protocols
5336/// const struct method_list_t * const instance_methods;
5337/// const struct method_list_t * const class_methods;
5338/// const struct method_list_t *optionalInstanceMethods;
5339/// const struct method_list_t *optionalClassMethods;
5340/// const struct _prop_list_t * properties;
5341/// const uint32_t size; // sizeof(struct _protocol_t)
5342/// const uint32_t flags; // = 0
5343/// }
5344/// @endcode
5345///
5346
5347llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005348 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005349 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005350
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005351 // Early exit if a defining object has already been generated.
5352 if (Entry && Entry->hasInitializer())
5353 return Entry;
5354
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005355 // Construct method lists.
5356 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5357 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005358 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005359 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005360 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005361 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005362 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5363 OptInstanceMethods.push_back(C);
5364 } else {
5365 InstanceMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005366 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005367 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005368
5369 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005370 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005371 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005372 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005373 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5374 OptClassMethods.push_back(C);
5375 } else {
5376 ClassMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005377 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005378 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005379
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005380 std::vector<llvm::Constant*> Values(10);
5381 // isa is NULL
Owen Anderson0b75f232009-07-31 20:28:54 +00005382 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005383 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005384 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5385 PD->protocol_begin(),
5386 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005387
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005388 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005389 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005390 "__DATA, __objc_const",
5391 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005392 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005393 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005394 "__DATA, __objc_const",
5395 ClassMethods);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005396 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005397 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005398 "__DATA, __objc_const",
5399 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005400 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005401 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005402 "__DATA, __objc_const",
5403 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005404 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005405 0, PD, ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005406 uint32_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005407 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005408 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0b75f232009-07-31 20:28:54 +00005409 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005410 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005411 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005412
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005413 if (Entry) {
5414 // Already created, fix the linkage and update the initializer.
Mike Stumpa6ca3342009-03-07 16:33:28 +00005415 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005416 Entry->setInitializer(Init);
5417 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005418 Entry =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005419 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
5420 false, llvm::GlobalValue::WeakAnyLinkage, Init,
5421 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005422 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005423 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005424 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005425 }
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005426 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005427 CGM.AddUsedGlobal(Entry);
5428
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005429 // Use this protocol meta-data to build protocol list table in section
5430 // __DATA, __objc_protolist
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005431 llvm::GlobalVariable *PTGV =
5432 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
5433 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
5434 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005435 PTGV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005436 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbarb25452a2009-04-15 02:56:18 +00005437 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005438 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005439 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005440 return Entry;
5441}
5442
5443/// EmitProtocolList - Generate protocol list meta-data:
5444/// @code
5445/// struct _protocol_list_t {
5446/// long protocol_count; // Note, this is 32/64 bit
5447/// struct _protocol_t[protocol_count];
5448/// }
5449/// @endcode
5450///
5451llvm::Constant *
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005452CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
5453 ObjCProtocolDecl::protocol_iterator begin,
5454 ObjCProtocolDecl::protocol_iterator end) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005455 std::vector<llvm::Constant*> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005456
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005457 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005458 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00005459 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005460
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005461 // FIXME: We shouldn't need to do this lookup here, should we?
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005462 llvm::SmallString<256> TmpName;
5463 Name.toVector(TmpName);
5464 llvm::GlobalVariable *GV =
5465 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005466 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005467 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005468
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005469 for (; begin != end; ++begin)
5470 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
5471
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005472 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00005473 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005474 ObjCTypes.ProtocolnfABIPtrTy));
5475
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005476 std::vector<llvm::Constant*> Values(2);
Owen Anderson170229f2009-07-14 23:10:40 +00005477 Values[0] =
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005478 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005479 Values[1] =
Owen Anderson47034e12009-07-28 18:33:04 +00005480 llvm::ConstantArray::get(
Owen Anderson9793f0e2009-07-29 22:16:19 +00005481 llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005482 ProtocolRefs.size()),
5483 ProtocolRefs);
5484
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005485 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Owen Andersonc10c8d32009-07-08 19:05:04 +00005486 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005487 llvm::GlobalValue::InternalLinkage,
5488 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005489 Name);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005490 GV->setSection("__DATA, __objc_const");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005491 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005492 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Chris Lattnerf56501c2009-07-17 23:57:13 +00005493 CGM.AddUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005494 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005495 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005496}
5497
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005498/// GetMethodDescriptionConstant - This routine build following meta-data:
5499/// struct _objc_method {
5500/// SEL _cmd;
5501/// char *method_type;
5502/// char *_imp;
5503/// }
5504
5505llvm::Constant *
5506CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
5507 std::vector<llvm::Constant*> Desc(3);
Owen Anderson170229f2009-07-14 23:10:40 +00005508 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005509 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5510 ObjCTypes.SelectorPtrTy);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005511 Desc[1] = GetMethodVarType(MD);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005512 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00005513 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005514 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005515}
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005516
5517/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
5518/// This code gen. amounts to generating code for:
5519/// @code
5520/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
5521/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005522///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00005523LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00005524 CodeGen::CodeGenFunction &CGF,
5525 QualType ObjectTy,
5526 llvm::Value *BaseValue,
5527 const ObjCIvarDecl *Ivar,
5528 unsigned CVRQualifiers) {
5529 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00005530 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5531 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005532}
5533
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005534llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005535 CodeGen::CodeGenFunction &CGF,
5536 const ObjCInterfaceDecl *Interface,
5537 const ObjCIvarDecl *Ivar) {
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005538 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005539}
5540
John McCall234eac82011-05-13 23:16:18 +00005541static void appendSelectorForMessageRefTable(std::string &buffer,
5542 Selector selector) {
5543 if (selector.isUnarySelector()) {
5544 buffer += selector.getNameForSlot(0);
5545 return;
5546 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005547
John McCall234eac82011-05-13 23:16:18 +00005548 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
5549 buffer += selector.getNameForSlot(i);
5550 buffer += '_';
5551 }
5552}
5553
John McCall9e8bb002011-05-14 03:10:52 +00005554/// Emit a "v-table" message send. We emit a weak hidden-visibility
5555/// struct, initially containing the selector pointer and a pointer to
5556/// a "fixup" variant of the appropriate objc_msgSend. To call, we
5557/// load and call the function pointer, passing the address of the
5558/// struct as the second parameter. The runtime determines whether
5559/// the selector is currently emitted using vtable dispatch; if so, it
5560/// substitutes a stub function which simply tail-calls through the
5561/// appropriate vtable slot, and if not, it substitues a stub function
5562/// which tail-calls objc_msgSend. Both stubs adjust the selector
5563/// argument to correctly point to the selector.
5564RValue
5565CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
5566 ReturnValueSlot returnSlot,
5567 QualType resultType,
5568 Selector selector,
5569 llvm::Value *arg0,
5570 QualType arg0Type,
5571 bool isSuper,
5572 const CallArgList &formalArgs,
5573 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00005574 // Compute the actual arguments.
5575 CallArgList args;
5576
John McCall9e8bb002011-05-14 03:10:52 +00005577 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00005578 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00005579 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
5580 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00005581
John McCall9e8bb002011-05-14 03:10:52 +00005582 // Second argument: a pointer to the message ref structure. Leave
5583 // the actual argument value blank for now.
John McCall234eac82011-05-13 23:16:18 +00005584 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
5585
5586 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
5587
5588 const CGFunctionInfo &fnInfo =
5589 CGM.getTypes().getFunctionInfo(resultType, args,
5590 FunctionType::ExtInfo());
5591
John McCall5880fb82011-05-14 21:12:11 +00005592 NullReturnState nullReturn;
5593
John McCall9e8bb002011-05-14 03:10:52 +00005594 // Find the function to call and the mangled name for the message
5595 // ref structure. Using a different mangled name wouldn't actually
5596 // be a problem; it would just be a waste.
5597 //
5598 // The runtime currently never uses vtable dispatch for anything
5599 // except normal, non-super message-sends.
5600 // FIXME: don't use this for that.
John McCall234eac82011-05-13 23:16:18 +00005601 llvm::Constant *fn = 0;
5602 std::string messageRefName("\01l_");
5603 if (CGM.ReturnTypeUsesSRet(fnInfo)) {
John McCall234eac82011-05-13 23:16:18 +00005604 if (isSuper) {
5605 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
5606 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005607 } else {
John McCall5880fb82011-05-14 21:12:11 +00005608 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00005609 fn = ObjCTypes.getMessageSendStretFixupFn();
5610 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005611 }
John McCall234eac82011-05-13 23:16:18 +00005612 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
5613 fn = ObjCTypes.getMessageSendFpretFixupFn();
5614 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00005615 } else {
John McCall234eac82011-05-13 23:16:18 +00005616 if (isSuper) {
5617 fn = ObjCTypes.getMessageSendSuper2FixupFn();
5618 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005619 } else {
John McCall234eac82011-05-13 23:16:18 +00005620 fn = ObjCTypes.getMessageSendFixupFn();
5621 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005622 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005623 }
John McCall234eac82011-05-13 23:16:18 +00005624 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
5625 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005626
John McCall234eac82011-05-13 23:16:18 +00005627 // Append the selector name, except use underscores anywhere we
5628 // would have used colons.
5629 appendSelectorForMessageRefTable(messageRefName, selector);
5630
5631 llvm::GlobalVariable *messageRef
5632 = CGM.getModule().getGlobalVariable(messageRefName);
5633 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00005634 // Build the message ref structure.
John McCall234eac82011-05-13 23:16:18 +00005635 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
5636 llvm::Constant *init =
5637 llvm::ConstantStruct::get(VMContext, values, 2, false);
5638 messageRef = new llvm::GlobalVariable(CGM.getModule(),
5639 init->getType(),
5640 /*constant*/ false,
5641 llvm::GlobalValue::WeakAnyLinkage,
5642 init,
5643 messageRefName);
5644 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
5645 messageRef->setAlignment(16);
5646 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
5647 }
5648 llvm::Value *mref =
5649 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
5650
John McCall9e8bb002011-05-14 03:10:52 +00005651 // Update the message ref argument.
John McCall234eac82011-05-13 23:16:18 +00005652 args[1].RV = RValue::get(mref);
5653
5654 // Load the function to call from the message ref table.
5655 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
5656 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
5657
5658 bool variadic = method ? method->isVariadic() : false;
5659 const llvm::FunctionType *fnType =
5660 CGF.getTypes().GetFunctionType(fnInfo, variadic);
5661 callee = CGF.Builder.CreateBitCast(callee,
5662 llvm::PointerType::getUnqual(fnType));
5663
John McCall5880fb82011-05-14 21:12:11 +00005664 RValue result = CGF.EmitCall(fnInfo, callee, returnSlot, args);
5665 return nullReturn.complete(CGF, result, resultType);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00005666}
5667
5668/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005669CodeGen::RValue
5670CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00005671 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005672 QualType ResultType,
5673 Selector Sel,
5674 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005675 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00005676 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005677 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00005678 return isVTableDispatchedSelector(Sel)
5679 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005680 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00005681 false, CallArgs, Method)
5682 : EmitMessageSend(CGF, Return, ResultType,
5683 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005684 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00005685 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00005686}
5687
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005688llvm::GlobalVariable *
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005689CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005690 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5691
Daniel Dunbara6468342009-03-02 05:18:14 +00005692 if (!GV) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005693 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005694 false, llvm::GlobalValue::ExternalLinkage,
5695 0, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005696 }
5697
5698 return GV;
5699}
5700
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005701llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5702 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005703 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005704
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005705 if (!Entry) {
Daniel Dunbar15894b72009-04-07 05:48:37 +00005706 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005707 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005708 Entry =
5709 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005710 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005711 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005712 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005713 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005714 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005715 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005716 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005717 CGM.AddUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005718 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005719
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005720 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005721}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005722
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005723llvm::Value *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005724CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005725 const ObjCInterfaceDecl *ID) {
5726 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005727
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005728 if (!Entry) {
5729 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5730 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005731 Entry =
5732 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005733 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005734 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005735 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005736 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005737 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005738 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005739 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005740 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005741 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005742
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005743 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005744}
5745
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005746/// EmitMetaClassRef - Return a Value * of the address of _class_t
5747/// meta-data
5748///
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005749llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5750 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005751 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5752 if (Entry)
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005753 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005754
Daniel Dunbar15894b72009-04-07 05:48:37 +00005755 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005756 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005757 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005758 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005759 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005760 MetaClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005761 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005762 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005763 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005764 ObjCTypes.ClassnfABIPtrTy));
5765
Daniel Dunbare60aa052009-04-15 19:03:14 +00005766 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005767 CGM.AddUsedGlobal(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005768
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005769 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005770}
5771
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005772/// GetClass - Return a reference to the class for the given interface
5773/// decl.
5774llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
5775 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005776 if (ID->isWeakImported()) {
Fariborz Jahanian95ace552009-11-17 22:42:00 +00005777 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5778 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5779 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5780 }
5781
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005782 return EmitClassRef(Builder, ID);
5783}
5784
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005785/// Generates a message send where the super is the receiver. This is
5786/// a message send to self with special delivery semantics indicating
5787/// which class's method should be called.
5788CodeGen::RValue
5789CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00005790 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005791 QualType ResultType,
5792 Selector Sel,
5793 const ObjCInterfaceDecl *Class,
5794 bool isCategoryImpl,
5795 llvm::Value *Receiver,
5796 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005797 const CodeGen::CallArgList &CallArgs,
5798 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005799 // ...
5800 // Create and init a super structure; this is a (receiver, class)
5801 // pair we will pass to objc_msgSendSuper.
5802 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00005803 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005804
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005805 llvm::Value *ReceiverAsObject =
5806 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
5807 CGF.Builder.CreateStore(ReceiverAsObject,
5808 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005809
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005810 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005811 llvm::Value *Target;
5812 if (IsClassMessage) {
5813 if (isCategoryImpl) {
5814 // Message sent to "super' in a class method defined in
5815 // a category implementation.
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005816 Target = EmitClassRef(CGF.Builder, Class);
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005817 Target = CGF.Builder.CreateStructGEP(Target, 0);
5818 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00005819 } else
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005820 Target = EmitMetaClassRef(CGF.Builder, Class);
Mike Stump658fe022009-07-30 22:28:39 +00005821 } else
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005822 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005823
Mike Stump18bb9282009-05-16 07:57:57 +00005824 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5825 // ObjCTypes types.
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005826 const llvm::Type *ClassTy =
5827 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
5828 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
5829 CGF.Builder.CreateStore(Target,
5830 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005831
John McCall9e8bb002011-05-14 03:10:52 +00005832 return (isVTableDispatchedSelector(Sel))
5833 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005834 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00005835 true, CallArgs, Method)
5836 : EmitMessageSend(CGF, Return, ResultType,
5837 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005838 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00005839 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005840}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005841
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005842llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00005843 Selector Sel, bool lval) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005844 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005845
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005846 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005847 llvm::Constant *Casted =
5848 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
5849 ObjCTypes.SelectorPtrTy);
5850 Entry =
5851 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
5852 llvm::GlobalValue::InternalLinkage,
5853 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005854 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005855 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005856 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005857
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00005858 if (lval)
5859 return Entry;
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005860 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005861}
Fariborz Jahanian06292952009-02-16 22:52:32 +00005862/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005863/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00005864///
5865void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005866 llvm::Value *src,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005867 llvm::Value *dst,
5868 llvm::Value *ivarOffset) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005869 const llvm::Type * SrcTy = src->getType();
5870 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005871 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005872 assert(Size <= 8 && "does not support size > 8");
5873 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5874 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005875 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5876 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005877 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5878 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005879 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5880 src, dst, ivarOffset);
Fariborz Jahanian06292952009-02-16 22:52:32 +00005881 return;
5882}
5883
5884/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5885/// objc_assign_strongCast (id src, id *dst)
5886///
5887void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005888 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005889 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005890 const llvm::Type * SrcTy = src->getType();
5891 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005892 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005893 assert(Size <= 8 && "does not support size > 8");
5894 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005895 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005896 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5897 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005898 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5899 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00005900 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00005901 src, dst, "weakassign");
5902 return;
5903}
5904
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005905void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005906 CodeGen::CodeGenFunction &CGF,
5907 llvm::Value *DestPtr,
5908 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00005909 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005910 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5911 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005912 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00005913 DestPtr, SrcPtr, Size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005914 return;
5915}
5916
Fariborz Jahanian06292952009-02-16 22:52:32 +00005917/// EmitObjCWeakRead - Code gen for loading value of a __weak
5918/// object: objc_read_weak (id *src)
5919///
5920llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005921 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005922 llvm::Value *AddrWeakObj) {
Eli Friedmana374b682009-03-07 03:57:15 +00005923 const llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005924 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5925 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00005926 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00005927 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00005928 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00005929 return read_weak;
5930}
5931
5932/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
5933/// objc_assign_weak (id src, id *dst)
5934///
5935void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005936 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005937 const llvm::Type * SrcTy = src->getType();
5938 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005939 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005940 assert(Size <= 8 && "does not support size > 8");
5941 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5942 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005943 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5944 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005945 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5946 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00005947 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00005948 src, dst, "weakassign");
5949 return;
5950}
5951
5952/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
5953/// objc_assign_global (id src, id *dst)
5954///
5955void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00005956 llvm::Value *src, llvm::Value *dst,
5957 bool threadlocal) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005958 const llvm::Type * SrcTy = src->getType();
5959 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005960 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005961 assert(Size <= 8 && "does not support size > 8");
5962 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5963 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005964 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5965 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005966 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5967 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00005968 if (!threadlocal)
5969 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
5970 src, dst, "globalassign");
5971 else
5972 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
5973 src, dst, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00005974 return;
5975}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005976
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005977void
John McCallbd309292010-07-06 01:34:17 +00005978CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
5979 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00005980 EmitAtSynchronizedStmt(CGF, S,
5981 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
5982 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00005983}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005984
John McCall2ca705e2010-07-24 00:37:23 +00005985llvm::Constant *
5986CGObjCNonFragileABIMac::GetEHType(QualType T) {
5987 // There's a particular fixed type info for 'id'.
5988 if (T->isObjCIdType() ||
5989 T->isObjCQualifiedIdType()) {
5990 llvm::Constant *IDEHType =
5991 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
5992 if (!IDEHType)
5993 IDEHType =
5994 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
5995 false,
5996 llvm::GlobalValue::ExternalLinkage,
5997 0, "OBJC_EHTYPE_id");
5998 return IDEHType;
5999 }
6000
6001 // All other types should be Objective-C interface pointer types.
6002 const ObjCObjectPointerType *PT =
6003 T->getAs<ObjCObjectPointerType>();
6004 assert(PT && "Invalid @catch type.");
6005 const ObjCInterfaceType *IT = PT->getInterfaceType();
6006 assert(IT && "Invalid @catch type.");
6007 return GetInterfaceEHType(IT->getDecl(), false);
6008}
6009
John McCallbd309292010-07-06 01:34:17 +00006010void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6011 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006012 EmitTryCatchStmt(CGF, S,
6013 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6014 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6015 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006016}
6017
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006018/// EmitThrowStmt - Generate code for a throw statement.
6019void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6020 const ObjCAtThrowStmt &S) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006021 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall17afe452010-10-16 08:21:07 +00006022 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
John McCalld5091822010-10-16 16:34:08 +00006023 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy,
6024 "tmp");
John McCall17afe452010-10-16 08:21:07 +00006025 llvm::Value *Args[] = { Exception };
6026 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(),
6027 Args, Args+1)
6028 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006029 } else {
John McCall17afe452010-10-16 08:21:07 +00006030 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn(), 0, 0)
6031 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006032 }
6033
John McCall17afe452010-10-16 08:21:07 +00006034 CGF.Builder.CreateUnreachable();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006035 CGF.Builder.ClearInsertionPoint();
6036}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006037
John McCall2ca705e2010-07-24 00:37:23 +00006038llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006039CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006040 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006041 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006042
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006043 // If we don't need a definition, return the entry if found or check
6044 // if we use an external reference.
6045 if (!ForDefinition) {
6046 if (Entry)
6047 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00006048
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006049 // If this type (or a super class) has the __objc_exception__
6050 // attribute, emit an external reference.
Douglas Gregor78bd61f2009-06-18 16:11:24 +00006051 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006052 return Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006053 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006054 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006055 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006056 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006057 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006058 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006059
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006060 // Otherwise we need to either make a new entry or fill in the
6061 // initializer.
6062 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar15894b72009-04-07 05:48:37 +00006063 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006064 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006065 llvm::GlobalVariable *VTableGV =
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006066 CGM.getModule().getGlobalVariable(VTableName);
6067 if (!VTableGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006068 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6069 false,
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006070 llvm::GlobalValue::ExternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006071 0, VTableName);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006072
Chris Lattner5e016ae2010-06-27 07:15:29 +00006073 llvm::Value *VTableIdx =
6074 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006075
6076 std::vector<llvm::Constant*> Values(3);
Owen Andersonade90fd2009-07-29 18:54:39 +00006077 Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006078 Values[1] = GetClassName(ID->getIdentifier());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006079 Values[2] = GetClassGlobal(ClassName);
Owen Anderson170229f2009-07-14 23:10:40 +00006080 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00006081 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006082
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006083 if (Entry) {
6084 Entry->setInitializer(Init);
6085 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00006086 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006087 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006088 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006089 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006090 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006091 }
6092
John McCall457a04e2010-10-22 21:05:15 +00006093 if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar15894b72009-04-07 05:48:37 +00006094 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar710cb202010-04-25 20:39:32 +00006095 Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
6096 ObjCTypes.EHTypeTy));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006097
6098 if (ForDefinition) {
6099 Entry->setSection("__DATA,__objc_const");
6100 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6101 } else {
6102 Entry->setSection("__DATA,__datacoal_nt,coalesced");
6103 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006104
6105 return Entry;
6106}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006107
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00006108/* *** */
6109
Daniel Dunbarb036db82008-08-13 03:21:16 +00006110CodeGen::CGObjCRuntime *
6111CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
David Chisnall067f0ed2011-03-22 21:21:24 +00006112 if (CGM.getLangOptions().ObjCNonFragileABI)
6113 return new CGObjCNonFragileABIMac(CGM);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00006114 return new CGObjCMac(CGM);
6115}