blob: 8c3e9a36e307bd16ae55fe95408e10e7fa2caf11 [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);
Douglas Gregora9d84932011-05-27 01:19:52 +00001689
Daniel Dunbarc475d422008-10-29 22:36:39 +00001690 return GetOrEmitProtocolRef(PD);
1691}
1692
Daniel Dunbarb036db82008-08-13 03:21:16 +00001693/*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001694// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1695struct _objc_protocol {
1696struct _objc_protocol_extension *isa;
1697char *protocol_name;
1698struct _objc_protocol_list *protocol_list;
1699struct _objc__method_prototype_list *instance_methods;
1700struct _objc__method_prototype_list *class_methods
1701};
Daniel Dunbarb036db82008-08-13 03:21:16 +00001702
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001703See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00001704*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00001705llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1706 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1707
1708 // Early exit if a defining object has already been generated.
1709 if (Entry && Entry->hasInitializer())
1710 return Entry;
1711
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00001712 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00001713 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00001714 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1715
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001716 // Construct method lists.
1717 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1718 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001719 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00001720 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001721 ObjCMethodDecl *MD = *i;
1722 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00001723 if (!C)
1724 return GetOrEmitProtocolRef(PD);
1725
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001726 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1727 OptInstanceMethods.push_back(C);
1728 } else {
1729 InstanceMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001730 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001731 }
1732
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001733 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00001734 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001735 ObjCMethodDecl *MD = *i;
1736 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00001737 if (!C)
1738 return GetOrEmitProtocolRef(PD);
1739
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001740 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1741 OptClassMethods.push_back(C);
1742 } else {
1743 ClassMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001744 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001745 }
1746
Daniel Dunbarb036db82008-08-13 03:21:16 +00001747 std::vector<llvm::Constant*> Values(5);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001748 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001749 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001750 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001751 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardec75f82008-08-21 21:57:41 +00001752 PD->protocol_begin(),
1753 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001754 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001755 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001756 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1757 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001758 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001759 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001760 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1761 ClassMethods);
Owen Anderson0e0189d2009-07-27 22:29:56 +00001762 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001763 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001764
Daniel Dunbarb036db82008-08-13 03:21:16 +00001765 if (Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001766 // Already created, fix the linkage and update the initializer.
1767 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001768 Entry->setInitializer(Init);
1769 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001770 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00001771 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001772 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001773 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001774 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00001775 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00001776 // FIXME: Is this necessary? Why only for protocol?
1777 Entry->setAlignment(4);
1778 }
Chris Lattnerf56501c2009-07-17 23:57:13 +00001779 CGM.AddUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001780
1781 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00001782}
1783
Daniel Dunbarc475d422008-10-29 22:36:39 +00001784llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00001785 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1786
1787 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001788 // We use the initializer as a marker of whether this is a forward
1789 // reference or not. At module finalization we add the empty
1790 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001791 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00001792 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarc475d422008-10-29 22:36:39 +00001793 llvm::GlobalValue::ExternalLinkage,
1794 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001795 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00001796 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00001797 // FIXME: Is this necessary? Why only for protocol?
1798 Entry->setAlignment(4);
1799 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001800
Daniel Dunbarb036db82008-08-13 03:21:16 +00001801 return Entry;
1802}
1803
1804/*
1805 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001806 uint32_t size;
1807 struct objc_method_description_list *optional_instance_methods;
1808 struct objc_method_description_list *optional_class_methods;
1809 struct objc_property_list *instance_properties;
Daniel Dunbarb036db82008-08-13 03:21:16 +00001810 };
1811*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001812llvm::Constant *
1813CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1814 const ConstantVector &OptInstanceMethods,
1815 const ConstantVector &OptClassMethods) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001816 uint64_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00001817 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001818 std::vector<llvm::Constant*> Values(4);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001819 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001820 Values[1] =
1821 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001822 + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001823 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1824 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001825 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001826 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001827 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1828 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001829 Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00001830 0, PD, ObjCTypes);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001831
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001832 // Return null if no extension bits are used.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001833 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Daniel Dunbarb036db82008-08-13 03:21:16 +00001834 Values[3]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00001835 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001836
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001837 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00001838 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001839
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001840 // No special section, but goes in llvm.used
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001841 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001842 Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001843 0, 0, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001844}
1845
1846/*
1847 struct objc_protocol_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001848 struct objc_protocol_list *next;
1849 long count;
1850 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00001851 };
1852*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00001853llvm::Constant *
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001854CGObjCMac::EmitProtocolList(llvm::Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001855 ObjCProtocolDecl::protocol_iterator begin,
1856 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00001857 std::vector<llvm::Constant*> ProtocolRefs;
1858
Daniel Dunbardec75f82008-08-21 21:57:41 +00001859 for (; begin != end; ++begin)
1860 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarb036db82008-08-13 03:21:16 +00001861
1862 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001863 if (ProtocolRefs.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00001864 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001865
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001866 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00001867 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbarb036db82008-08-13 03:21:16 +00001868
1869 std::vector<llvm::Constant*> Values(3);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001870 // This field is only used by the runtime.
Owen Anderson0b75f232009-07-31 20:28:54 +00001871 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001872 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001873 ProtocolRefs.size() - 1);
1874 Values[2] =
1875 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1876 ProtocolRefs.size()),
Daniel Dunbarb036db82008-08-13 03:21:16 +00001877 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001878
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00001879 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001880 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001881 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00001882 4, false);
Owen Andersonade90fd2009-07-29 18:54:39 +00001883 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001884}
1885
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00001886void CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
1887 std::vector<llvm::Constant*> &Properties,
1888 const Decl *Container,
1889 const ObjCProtocolDecl *PROTO,
1890 const ObjCCommonTypesHelper &ObjCTypes) {
1891 std::vector<llvm::Constant*> Prop(2);
1892 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
1893 E = PROTO->protocol_end(); P != E; ++P)
1894 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
1895 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
1896 E = PROTO->prop_end(); I != E; ++I) {
1897 const ObjCPropertyDecl *PD = *I;
1898 if (!PropertySet.insert(PD->getIdentifier()))
1899 continue;
1900 Prop[0] = GetPropertyName(PD->getIdentifier());
1901 Prop[1] = GetPropertyTypeString(PD, Container);
1902 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
1903 }
1904}
1905
Daniel Dunbarb036db82008-08-13 03:21:16 +00001906/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001907 struct _objc_property {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001908 const char * const name;
1909 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001910 };
1911
1912 struct _objc_property_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001913 uint32_t entsize; // sizeof (struct _objc_property)
1914 uint32_t prop_count;
1915 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001916 };
1917*/
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001918llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001919 const Decl *Container,
1920 const ObjCContainerDecl *OCD,
1921 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001922 std::vector<llvm::Constant*> Properties, Prop(2);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00001923 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001924 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
1925 E = OCD->prop_end(); I != E; ++I) {
Steve Naroffba3dc382009-01-11 12:47:58 +00001926 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00001927 PropertySet.insert(PD->getIdentifier());
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001928 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbar4932b362008-08-28 04:38:10 +00001929 Prop[1] = GetPropertyTypeString(PD, Container);
Owen Anderson0e0189d2009-07-27 22:29:56 +00001930 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001931 Prop));
1932 }
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00001933 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek0ef508d2010-09-01 01:21:15 +00001934 for (ObjCInterfaceDecl::all_protocol_iterator
1935 P = OID->all_referenced_protocol_begin(),
1936 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00001937 PushProtocolProperties(PropertySet, Properties, Container, (*P),
1938 ObjCTypes);
1939 }
1940 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
1941 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
1942 E = CD->protocol_end(); P != E; ++P)
1943 PushProtocolProperties(PropertySet, Properties, Container, (*P),
1944 ObjCTypes);
1945 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001946
1947 // Return null for empty list.
1948 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00001949 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001950
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001951 unsigned PropertySize =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00001952 CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001953 std::vector<llvm::Constant*> Values(3);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001954 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
1955 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001956 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001957 Properties.size());
Owen Anderson47034e12009-07-28 18:33:04 +00001958 Values[2] = llvm::ConstantArray::get(AT, Properties);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00001959 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001960
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001961 llvm::GlobalVariable *GV =
1962 CreateMetadataVar(Name, Init,
1963 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbarb25452a2009-04-15 02:56:18 +00001964 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001965 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbarb25452a2009-04-15 02:56:18 +00001966 true);
Owen Andersonade90fd2009-07-29 18:54:39 +00001967 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001968}
1969
1970/*
Daniel Dunbarb036db82008-08-13 03:21:16 +00001971 struct objc_method_description_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001972 int count;
1973 struct objc_method_description list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00001974 };
1975*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001976llvm::Constant *
1977CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
1978 std::vector<llvm::Constant*> Desc(2);
Owen Anderson170229f2009-07-14 23:10:40 +00001979 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001980 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1981 ObjCTypes.SelectorPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001982 Desc[1] = GetMethodVarType(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00001983 if (!Desc[1])
1984 return 0;
1985
Owen Anderson0e0189d2009-07-27 22:29:56 +00001986 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001987 Desc);
1988}
Daniel Dunbarb036db82008-08-13 03:21:16 +00001989
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001990llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001991 const char *Section,
1992 const ConstantVector &Methods) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00001993 // Return null for empty list.
1994 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00001995 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001996
1997 std::vector<llvm::Constant*> Values(2);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001998 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001999 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002000 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002001 Values[1] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002002 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002003
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002004 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002005 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002006 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002007}
2008
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002009/*
2010 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002011 char *category_name;
2012 char *class_name;
2013 struct _objc_method_list *instance_methods;
2014 struct _objc_method_list *class_methods;
2015 struct _objc_protocol_list *protocols;
2016 uint32_t size; // <rdar://4585769>
2017 struct _objc_property_list *instance_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002018 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002019*/
Daniel Dunbar92992502008-08-15 22:20:32 +00002020void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002021 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002022
Mike Stump18bb9282009-05-16 07:57:57 +00002023 // FIXME: This is poor design, the OCD should have a pointer to the category
2024 // decl. Additionally, note that Category can be null for the @implementation
2025 // w/o an @interface case. Sema should just create one for us as it does for
2026 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002027 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002028 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002029 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002030
2031 llvm::SmallString<256> ExtName;
2032 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2033 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002034
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002035 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002036 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002037 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002038 // Instance methods should always be defined.
2039 InstanceMethods.push_back(GetMethodConstant(*i));
2040 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002041 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002042 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002043 // Class methods should always be defined.
2044 ClassMethods.push_back(GetMethodConstant(*i));
2045 }
2046
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002047 std::vector<llvm::Constant*> Values(7);
2048 Values[0] = GetClassName(OCD->getIdentifier());
2049 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00002050 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002051 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002052 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002053 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002054 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002055 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002056 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002057 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002058 ClassMethods);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002059 if (Category) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002060 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002061 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002062 Category->protocol_begin(),
2063 Category->protocol_end());
2064 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002065 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002066 }
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002067 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002068
2069 // If there is no category @interface then there can be no properties.
2070 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002071 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002072 OCD, Category, ObjCTypes);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002073 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002074 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002075 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002076
Owen Anderson0e0189d2009-07-27 22:29:56 +00002077 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002078 Values);
2079
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002080 llvm::GlobalVariable *GV =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002081 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002082 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002083 4, true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002084 DefinedCategories.push_back(GV);
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00002085 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002086 // method definition entries must be clear for next implementation.
2087 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002088}
2089
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002090// FIXME: Get from somewhere?
2091enum ClassFlags {
2092 eClassFlags_Factory = 0x00001,
2093 eClassFlags_Meta = 0x00002,
2094 // <rdr://5142207>
2095 eClassFlags_HasCXXStructors = 0x02000,
2096 eClassFlags_Hidden = 0x20000,
2097 eClassFlags_ABI2_Hidden = 0x00010,
2098 eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
2099};
2100
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002101/*
2102 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002103 Class isa;
2104 Class super_class;
2105 const char *name;
2106 long version;
2107 long info;
2108 long instance_size;
2109 struct _objc_ivar_list *ivars;
2110 struct _objc_method_list *methods;
2111 struct _objc_cache *cache;
2112 struct _objc_protocol_list *protocols;
2113 // Objective-C 1.0 extensions (<rdr://4585769>)
2114 const char *ivar_layout;
2115 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002116 };
2117
2118 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002119*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002120void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002121 DefinedSymbols.insert(ID->getIdentifier());
2122
Chris Lattner86d7d912008-11-24 03:54:41 +00002123 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002124 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002125 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002126 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002127 llvm::Constant *Protocols =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002128 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00002129 Interface->all_referenced_protocol_begin(),
2130 Interface->all_referenced_protocol_end());
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002131 unsigned Flags = eClassFlags_Factory;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00002132 if (ID->getNumIvarInitializers())
2133 Flags |= eClassFlags_HasCXXStructors;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002134 unsigned Size =
Ken Dyckc8ae5502011-02-09 01:59:34 +00002135 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002136
2137 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00002138 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002139 Flags |= eClassFlags_Hidden;
2140
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002141 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002142 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002143 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002144 // Instance methods should always be defined.
2145 InstanceMethods.push_back(GetMethodConstant(*i));
2146 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002147 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002148 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002149 // Class methods should always be defined.
2150 ClassMethods.push_back(GetMethodConstant(*i));
2151 }
2152
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002153 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002154 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002155 ObjCPropertyImplDecl *PID = *i;
2156
2157 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2158 ObjCPropertyDecl *PD = PID->getPropertyDecl();
2159
2160 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
2161 if (llvm::Constant *C = GetMethodConstant(MD))
2162 InstanceMethods.push_back(C);
2163 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
2164 if (llvm::Constant *C = GetMethodConstant(MD))
2165 InstanceMethods.push_back(C);
2166 }
2167 }
2168
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002169 std::vector<llvm::Constant*> Values(12);
Daniel Dunbarccf61832009-05-03 08:56:52 +00002170 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002171 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002172 // Record a reference to the super class.
2173 LazySymbols.insert(Super->getIdentifier());
2174
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002175 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002176 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002177 ObjCTypes.ClassPtrTy);
2178 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002179 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002180 }
2181 Values[ 2] = GetClassName(ID->getIdentifier());
2182 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002183 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2184 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2185 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002186 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002187 Values[ 7] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002188 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002189 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002190 InstanceMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002191 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002192 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002193 Values[ 9] = Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002194 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002195 Values[11] = EmitClassExtension(ID);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002196 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002197 Values);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002198 std::string Name("\01L_OBJC_CLASS_");
2199 Name += ClassName;
2200 const char *Section = "__OBJC,__class,regular,no_dead_strip";
2201 // Check for a forward reference.
2202 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2203 if (GV) {
2204 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2205 "Forward metaclass reference has incorrect type.");
2206 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2207 GV->setInitializer(Init);
2208 GV->setSection(Section);
2209 GV->setAlignment(4);
2210 CGM.AddUsedGlobal(GV);
2211 }
2212 else
2213 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002214 DefinedClasses.push_back(GV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002215 // method definition entries must be clear for next implementation.
2216 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002217}
2218
2219llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2220 llvm::Constant *Protocols,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002221 const ConstantVector &Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002222 unsigned Flags = eClassFlags_Meta;
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002223 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002224
John McCall457a04e2010-10-22 21:05:15 +00002225 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002226 Flags |= eClassFlags_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002227
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002228 std::vector<llvm::Constant*> Values(12);
2229 // The isa for the metaclass is the root of the hierarchy.
2230 const ObjCInterfaceDecl *Root = ID->getClassInterface();
2231 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2232 Root = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002233 Values[ 0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002234 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002235 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002236 // The super class for the metaclass is emitted as the name of the
2237 // super class. The runtime fixes this up to point to the
2238 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002239 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002240 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002241 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002242 ObjCTypes.ClassPtrTy);
2243 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002244 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002245 }
2246 Values[ 2] = GetClassName(ID->getIdentifier());
2247 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002248 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2249 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2250 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002251 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002252 Values[ 7] =
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002253 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002254 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002255 Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002256 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002257 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002258 Values[ 9] = Protocols;
2259 // ivar_layout for metaclass is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002260 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002261 // The class extension is always unused for metaclasses.
Owen Anderson0b75f232009-07-31 20:28:54 +00002262 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002263 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002264 Values);
2265
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002266 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattner86d7d912008-11-24 03:54:41 +00002267 Name += ID->getNameAsCString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002268
2269 // Check for a forward reference.
2270 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2271 if (GV) {
2272 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2273 "Forward metaclass reference has incorrect type.");
2274 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2275 GV->setInitializer(Init);
2276 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00002277 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002278 llvm::GlobalValue::InternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002279 Init, Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002280 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002281 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbarae333842009-03-09 22:18:41 +00002282 GV->setAlignment(4);
Chris Lattnerf56501c2009-07-17 23:57:13 +00002283 CGM.AddUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002284
2285 return GV;
2286}
2287
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002288llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002289 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002290
Mike Stump18bb9282009-05-16 07:57:57 +00002291 // FIXME: Should we look these up somewhere other than the module. Its a bit
2292 // silly since we only generate these while processing an implementation, so
2293 // exactly one pointer would work if know when we entered/exitted an
2294 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002295
2296 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00002297 // Previously, metaclass with internal linkage may have been defined.
2298 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002299 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2300 true)) {
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002301 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2302 "Forward metaclass reference has incorrect type.");
2303 return GV;
2304 } else {
2305 // Generate as an external reference to keep a consistent
2306 // module. This will be patched up when we emit the metaclass.
Owen Andersonc10c8d32009-07-08 19:05:04 +00002307 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002308 llvm::GlobalValue::ExternalLinkage,
2309 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002310 Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002311 }
2312}
2313
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002314llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2315 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2316
2317 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2318 true)) {
2319 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2320 "Forward class metadata reference has incorrect type.");
2321 return GV;
2322 } else {
2323 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2324 llvm::GlobalValue::ExternalLinkage,
2325 0,
2326 Name);
2327 }
2328}
2329
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002330/*
2331 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002332 uint32_t size;
2333 const char *weak_ivar_layout;
2334 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002335 };
2336*/
2337llvm::Constant *
2338CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002339 uint64_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002340 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002341
2342 std::vector<llvm::Constant*> Values(3);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002343 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian6df69862009-04-22 23:00:43 +00002344 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002345 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002346 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002347
2348 // Return null if no extension bits are used.
2349 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002350 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002351
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002352 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002353 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002354 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002355 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002356 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002357}
2358
2359/*
2360 struct objc_ivar {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002361 char *ivar_name;
2362 char *ivar_type;
2363 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002364 };
2365
2366 struct objc_ivar_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002367 int ivar_count;
2368 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002369 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002370*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002371llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002372 bool ForClass) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002373 std::vector<llvm::Constant*> Ivars, Ivar(3);
2374
2375 // When emitting the root class GCC emits ivar entries for the
2376 // actual class structure. It is not clear if we need to follow this
2377 // behavior; for now lets try and get away with not doing it. If so,
2378 // the cleanest solution would be to make up an ObjCInterfaceDecl
2379 // for the class.
2380 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00002381 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002382
2383 ObjCInterfaceDecl *OID =
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002384 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002385
Daniel Dunbarf5c18462009-04-20 06:54:31 +00002386 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian7c809592009-06-04 01:19:09 +00002387 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002388
Daniel Dunbarf5c18462009-04-20 06:54:31 +00002389 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2390 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian7c809592009-06-04 01:19:09 +00002391 // Ignore unnamed bit-fields.
2392 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002393 continue;
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00002394 Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2395 Ivar[1] = GetMethodVarType(IVD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002396 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00002397 ComputeIvarBaseOffset(CGM, OID, IVD));
Owen Anderson0e0189d2009-07-27 22:29:56 +00002398 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002399 }
2400
2401 // Return null for empty list.
2402 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002403 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002404
2405 std::vector<llvm::Constant*> Values(2);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002406 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002407 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002408 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002409 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002410 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002411
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002412 llvm::GlobalVariable *GV;
2413 if (ForClass)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002414 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002415 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002416 4, true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002417 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002418 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002419 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002420 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002421 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002422}
2423
2424/*
2425 struct objc_method {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002426 SEL method_name;
2427 char *method_types;
2428 void *method;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002429 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002430
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002431 struct objc_method_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002432 struct objc_method_list *obsolete;
2433 int count;
2434 struct objc_method methods_list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002435 };
2436*/
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002437
2438/// GetMethodConstant - Return a struct objc_method constant for the
2439/// given method if it has been defined. The result is null if the
2440/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002441llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00002442 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002443 if (!Fn)
2444 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002445
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002446 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002447 Method[0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002448 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002449 ObjCTypes.SelectorPtrTy);
2450 Method[1] = GetMethodVarType(MD);
Owen Andersonade90fd2009-07-29 18:54:39 +00002451 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002452 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002453}
2454
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002455llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002456 const char *Section,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002457 const ConstantVector &Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002458 // Return null for empty list.
2459 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002460 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002461
2462 std::vector<llvm::Constant*> Values(3);
Owen Anderson0b75f232009-07-31 20:28:54 +00002463 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002464 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002465 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002466 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002467 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002468 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002469
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002470 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002471 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002472 ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002473}
2474
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00002475llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002476 const ObjCContainerDecl *CD) {
Daniel Dunbard2386812009-10-19 01:21:19 +00002477 llvm::SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00002478 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002479
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00002480 CodeGenTypes &Types = CGM.getTypes();
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00002481 const llvm::FunctionType *MethodTy =
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00002482 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002483 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00002484 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002485 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00002486 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002487 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002488 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002489
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002490 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002491}
2492
Daniel Dunbar30c65362009-03-09 20:09:19 +00002493llvm::GlobalVariable *
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002494CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00002495 llvm::Constant *Init,
2496 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00002497 unsigned Align,
2498 bool AddToUsed) {
Daniel Dunbar30c65362009-03-09 20:09:19 +00002499 const llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002500 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002501 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerf56501c2009-07-17 23:57:13 +00002502 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbar30c65362009-03-09 20:09:19 +00002503 if (Section)
2504 GV->setSection(Section);
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00002505 if (Align)
2506 GV->setAlignment(Align);
2507 if (AddToUsed)
Chris Lattnerf56501c2009-07-17 23:57:13 +00002508 CGM.AddUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00002509 return GV;
2510}
2511
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002512llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00002513 // Abuse this interface function as a place to finalize.
2514 FinishModule();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002515 return NULL;
2516}
2517
Chris Lattnerd4808922009-03-22 21:03:39 +00002518llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002519 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00002520}
2521
Chris Lattnerd4808922009-03-22 21:03:39 +00002522llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002523 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00002524}
2525
David Chisnall168b80f2010-12-26 22:13:16 +00002526llvm::Constant *CGObjCMac::GetGetStructFunction() {
2527 return ObjCTypes.getCopyStructFn();
2528}
2529llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00002530 return ObjCTypes.getCopyStructFn();
2531}
2532
Chris Lattnerd4808922009-03-22 21:03:39 +00002533llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002534 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00002535}
2536
John McCallbd309292010-07-06 01:34:17 +00002537void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
2538 return EmitTryOrSynchronizedStmt(CGF, S);
2539}
2540
2541void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
2542 const ObjCAtSynchronizedStmt &S) {
2543 return EmitTryOrSynchronizedStmt(CGF, S);
2544}
2545
John McCall65bea082010-07-21 06:59:36 +00002546namespace {
John McCallcda666c2010-07-21 07:22:38 +00002547 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00002548 const Stmt &S;
John McCall2dd7d442010-08-04 05:59:32 +00002549 llvm::Value *SyncArgSlot;
John McCall65bea082010-07-21 06:59:36 +00002550 llvm::Value *CallTryExitVar;
2551 llvm::Value *ExceptionData;
2552 ObjCTypesHelper &ObjCTypes;
2553 PerformFragileFinally(const Stmt *S,
John McCall2dd7d442010-08-04 05:59:32 +00002554 llvm::Value *SyncArgSlot,
John McCall65bea082010-07-21 06:59:36 +00002555 llvm::Value *CallTryExitVar,
2556 llvm::Value *ExceptionData,
2557 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00002558 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00002559 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
2560
2561 void Emit(CodeGenFunction &CGF, bool IsForEH) {
2562 // Check whether we need to call objc_exception_try_exit.
2563 // In optimized code, this branch will always be folded.
2564 llvm::BasicBlock *FinallyCallExit =
2565 CGF.createBasicBlock("finally.call_exit");
2566 llvm::BasicBlock *FinallyNoCallExit =
2567 CGF.createBasicBlock("finally.no_call_exit");
2568 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
2569 FinallyCallExit, FinallyNoCallExit);
2570
2571 CGF.EmitBlock(FinallyCallExit);
2572 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
2573 ->setDoesNotThrow();
2574
2575 CGF.EmitBlock(FinallyNoCallExit);
2576
2577 if (isa<ObjCAtTryStmt>(S)) {
2578 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00002579 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
2580 // Save the current cleanup destination in case there's
2581 // control flow inside the finally statement.
2582 llvm::Value *CurCleanupDest =
2583 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
2584
John McCall65bea082010-07-21 06:59:36 +00002585 CGF.EmitStmt(FinallyStmt->getFinallyBody());
2586
John McCallcebe0ca2010-08-11 00:16:14 +00002587 if (CGF.HaveInsertPoint()) {
2588 CGF.Builder.CreateStore(CurCleanupDest,
2589 CGF.getNormalCleanupDestSlot());
2590 } else {
2591 // Currently, the end of the cleanup must always exist.
2592 CGF.EnsureInsertPoint();
2593 }
2594 }
John McCall65bea082010-07-21 06:59:36 +00002595 } else {
2596 // Emit objc_sync_exit(expr); as finally's sole statement for
2597 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00002598 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall65bea082010-07-21 06:59:36 +00002599 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
2600 ->setDoesNotThrow();
2601 }
2602 }
2603 };
John McCall42227ed2010-07-31 23:20:56 +00002604
2605 class FragileHazards {
2606 CodeGenFunction &CGF;
2607 llvm::SmallVector<llvm::Value*, 20> Locals;
2608 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
2609
2610 llvm::InlineAsm *ReadHazard;
2611 llvm::InlineAsm *WriteHazard;
2612
2613 llvm::FunctionType *GetAsmFnType();
2614
2615 void collectLocals();
2616 void emitReadHazard(CGBuilderTy &Builder);
2617
2618 public:
2619 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00002620
John McCall42227ed2010-07-31 23:20:56 +00002621 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00002622 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00002623 };
2624}
2625
2626/// Create the fragile-ABI read and write hazards based on the current
2627/// state of the function, which is presumed to be immediately prior
2628/// to a @try block. These hazards are used to maintain correct
2629/// semantics in the face of optimization and the fragile ABI's
2630/// cavalier use of setjmp/longjmp.
2631FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
2632 collectLocals();
2633
2634 if (Locals.empty()) return;
2635
2636 // Collect all the blocks in the function.
2637 for (llvm::Function::iterator
2638 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
2639 BlocksBeforeTry.insert(&*I);
2640
2641 llvm::FunctionType *AsmFnTy = GetAsmFnType();
2642
2643 // Create a read hazard for the allocas. This inhibits dead-store
2644 // optimizations and forces the values to memory. This hazard is
2645 // inserted before any 'throwing' calls in the protected scope to
2646 // reflect the possibility that the variables might be read from the
2647 // catch block if the call throws.
2648 {
2649 std::string Constraint;
2650 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2651 if (I) Constraint += ',';
2652 Constraint += "*m";
2653 }
2654
2655 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2656 }
2657
2658 // Create a write hazard for the allocas. This inhibits folding
2659 // loads across the hazard. This hazard is inserted at the
2660 // beginning of the catch path to reflect the possibility that the
2661 // variables might have been written within the protected scope.
2662 {
2663 std::string Constraint;
2664 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2665 if (I) Constraint += ',';
2666 Constraint += "=*m";
2667 }
2668
2669 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2670 }
2671}
2672
2673/// Emit a write hazard at the current location.
2674void FragileHazards::emitWriteHazard() {
2675 if (Locals.empty()) return;
2676
2677 CGF.Builder.CreateCall(WriteHazard, Locals.begin(), Locals.end())
2678 ->setDoesNotThrow();
2679}
2680
John McCall42227ed2010-07-31 23:20:56 +00002681void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
2682 assert(!Locals.empty());
2683 Builder.CreateCall(ReadHazard, Locals.begin(), Locals.end())
2684 ->setDoesNotThrow();
2685}
2686
2687/// Emit read hazards in all the protected blocks, i.e. all the blocks
2688/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00002689void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00002690 if (Locals.empty()) return;
2691
2692 CGBuilderTy Builder(CGF.getLLVMContext());
2693
2694 // Iterate through all blocks, skipping those prior to the try.
2695 for (llvm::Function::iterator
2696 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
2697 llvm::BasicBlock &BB = *FI;
2698 if (BlocksBeforeTry.count(&BB)) continue;
2699
2700 // Walk through all the calls in the block.
2701 for (llvm::BasicBlock::iterator
2702 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
2703 llvm::Instruction &I = *BI;
2704
2705 // Ignore instructions that aren't non-intrinsic calls.
2706 // These are the only calls that can possibly call longjmp.
2707 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
2708 if (isa<llvm::IntrinsicInst>(I))
2709 continue;
2710
2711 // Ignore call sites marked nounwind. This may be questionable,
2712 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
2713 llvm::CallSite CS(&I);
2714 if (CS.doesNotThrow()) continue;
2715
John McCall2dd7d442010-08-04 05:59:32 +00002716 // Insert a read hazard before the call. This will ensure that
2717 // any writes to the locals are performed before making the
2718 // call. If the call throws, then this is sufficient to
2719 // guarantee correctness as long as it doesn't also write to any
2720 // locals.
John McCall42227ed2010-07-31 23:20:56 +00002721 Builder.SetInsertPoint(&BB, BI);
2722 emitReadHazard(Builder);
2723 }
2724 }
2725}
2726
2727static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
2728 if (V) S.insert(V);
2729}
2730
2731void FragileHazards::collectLocals() {
2732 // Compute a set of allocas to ignore.
2733 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
2734 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
2735 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
2736 addIfPresent(AllocasToIgnore, CGF.EHCleanupDest);
2737
2738 // Collect all the allocas currently in the function. This is
2739 // probably way too aggressive.
2740 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
2741 for (llvm::BasicBlock::iterator
2742 I = Entry.begin(), E = Entry.end(); I != E; ++I)
2743 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
2744 Locals.push_back(&*I);
2745}
2746
2747llvm::FunctionType *FragileHazards::GetAsmFnType() {
John McCall9dc0db22011-05-15 01:53:33 +00002748 llvm::SmallVector<const llvm::Type *, 16> tys(Locals.size());
2749 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
2750 tys[i] = Locals[i]->getType();
2751 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00002752}
2753
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002754/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002755
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002756 Objective-C setjmp-longjmp (sjlj) Exception Handling
2757 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002758
John McCallbd309292010-07-06 01:34:17 +00002759 A catch buffer is a setjmp buffer plus:
2760 - a pointer to the exception that was caught
2761 - a pointer to the previous exception data buffer
2762 - two pointers of reserved storage
2763 Therefore catch buffers form a stack, with a pointer to the top
2764 of the stack kept in thread-local storage.
2765
2766 objc_exception_try_enter pushes a catch buffer onto the EH stack.
2767 objc_exception_try_exit pops the given catch buffer, which is
2768 required to be the top of the EH stack.
2769 objc_exception_throw pops the top of the EH stack, writes the
2770 thrown exception into the appropriate field, and longjmps
2771 to the setjmp buffer. It crashes the process (with a printf
2772 and an abort()) if there are no catch buffers on the stack.
2773 objc_exception_extract just reads the exception pointer out of the
2774 catch buffer.
2775
2776 There's no reason an implementation couldn't use a light-weight
2777 setjmp here --- something like __builtin_setjmp, but API-compatible
2778 with the heavyweight setjmp. This will be more important if we ever
2779 want to implement correct ObjC/C++ exception interactions for the
2780 fragile ABI.
2781
2782 Note that for this use of setjmp/longjmp to be correct, we may need
2783 to mark some local variables volatile: if a non-volatile local
2784 variable is modified between the setjmp and the longjmp, it has
2785 indeterminate value. For the purposes of LLVM IR, it may be
2786 sufficient to make loads and stores within the @try (to variables
2787 declared outside the @try) volatile. This is necessary for
2788 optimized correctness, but is not currently being done; this is
2789 being tracked as rdar://problem/8160285
2790
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002791 The basic framework for a @try-catch-finally is as follows:
2792 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002793 objc_exception_data d;
2794 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00002795 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002796
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002797 objc_exception_try_enter(&d);
2798 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002799 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002800 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002801 // exception path
2802 id _caught = objc_exception_extract(&d);
2803
2804 // enter new try scope for handlers
2805 if (!setjmp(d.jmp_buf)) {
2806 ... match exception and execute catch blocks ...
2807
2808 // fell off end, rethrow.
2809 _rethrow = _caught;
2810 ... jump-through-finally to finally_rethrow ...
2811 } else {
2812 // exception in catch block
2813 _rethrow = objc_exception_extract(&d);
2814 _call_try_exit = false;
2815 ... jump-through-finally to finally_rethrow ...
2816 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002817 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002818 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002819
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002820 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00002821 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002822 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00002823
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002824 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002825 ... dispatch to finally destination ...
2826
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002827 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002828 objc_exception_throw(_rethrow);
2829
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002830 finally_end:
2831 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002832
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002833 This framework differs slightly from the one gcc uses, in that gcc
2834 uses _rethrow to determine if objc_exception_try_exit should be called
2835 and if the object should be rethrown. This breaks in the face of
2836 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002837
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002838 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002839
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002840 - If there are no catch blocks, then we avoid emitting the second
2841 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002842
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002843 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
2844 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002845
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002846 - FIXME: If there is no @finally block we can do a few more
2847 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002848
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002849 Rethrows and Jumps-Through-Finally
2850 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002851
John McCallbd309292010-07-06 01:34:17 +00002852 '@throw;' is supported by pushing the currently-caught exception
2853 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002854
John McCallbd309292010-07-06 01:34:17 +00002855 Branches through the @finally block are handled with an ordinary
2856 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
2857 exceptions are not compatible with C++ exceptions, and this is
2858 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002859
John McCallbd309292010-07-06 01:34:17 +00002860 @synchronized(expr) { stmt; } is emitted as if it were:
2861 id synch_value = expr;
2862 objc_sync_enter(synch_value);
2863 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002864*/
2865
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00002866void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2867 const Stmt &S) {
2868 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00002869
2870 // A destination for the fall-through edges of the catch handlers to
2871 // jump to.
2872 CodeGenFunction::JumpDest FinallyEnd =
2873 CGF.getJumpDestInCurrentScope("finally.end");
2874
2875 // A destination for the rethrow edge of the catch handlers to jump
2876 // to.
2877 CodeGenFunction::JumpDest FinallyRethrow =
2878 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002879
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002880 // For @synchronized, call objc_sync_enter(sync.expr). The
2881 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00002882 // @synchronized. We can't avoid a temp here because we need the
2883 // value to be preserved. If the backend ever does liveness
2884 // correctly after setjmp, this will be unnecessary.
2885 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002886 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00002887 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002888 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2889 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallbd309292010-07-06 01:34:17 +00002890 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
2891 ->setDoesNotThrow();
John McCall2dd7d442010-08-04 05:59:32 +00002892
2893 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
2894 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002895 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002896
John McCall2dd7d442010-08-04 05:59:32 +00002897 // Allocate memory for the setjmp buffer. This needs to be kept
2898 // live throughout the try and catch blocks.
2899 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2900 "exceptiondata.ptr");
2901
John McCall42227ed2010-07-31 23:20:56 +00002902 // Create the fragile hazards. Note that this will not capture any
2903 // of the allocas required for exception processing, but will
2904 // capture the current basic block (which extends all the way to the
2905 // setjmp call) as "before the @try".
2906 FragileHazards Hazards(CGF);
2907
John McCallbd309292010-07-06 01:34:17 +00002908 // Create a flag indicating whether the cleanup needs to call
2909 // objc_exception_try_exit. This is true except when
2910 // - no catches match and we're branching through the cleanup
2911 // just to rethrow the exception, or
2912 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00002913 // The setjmp-safety rule here is that we should always store to this
2914 // variable in a place that dominates the branch through the cleanup
2915 // without passing through any setjmps.
John McCallbd309292010-07-06 01:34:17 +00002916 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlssonda0e4562009-02-07 21:26:04 +00002917 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002918
John McCall9916e3f2010-10-04 23:42:51 +00002919 // A slot containing the exception to rethrow. Only needed when we
2920 // have both a @catch and a @finally.
2921 llvm::Value *PropagatingExnVar = 0;
2922
John McCallbd309292010-07-06 01:34:17 +00002923 // Push a normal cleanup to leave the try scope.
John McCallcda666c2010-07-21 07:22:38 +00002924 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00002925 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00002926 CallTryExitVar,
2927 ExceptionData,
2928 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00002929
2930 // Enter a try block:
2931 // - Call objc_exception_try_enter to push ExceptionData on top of
2932 // the EH stack.
2933 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
2934 ->setDoesNotThrow();
2935
2936 // - Call setjmp on the exception data buffer.
2937 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
2938 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
2939 llvm::Value *SetJmpBuffer =
2940 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, GEPIndexes+3, "setjmp_buffer");
2941 llvm::CallInst *SetJmpResult =
2942 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
2943 SetJmpResult->setDoesNotThrow();
2944
2945 // If setjmp returned 0, enter the protected block; otherwise,
2946 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00002947 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
2948 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00002949 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00002950 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
2951 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00002952
John McCallbd309292010-07-06 01:34:17 +00002953 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00002954 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00002955 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002956 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00002957 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00002958
2959 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002960
John McCallbd309292010-07-06 01:34:17 +00002961 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00002962 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00002963
John McCall42227ed2010-07-31 23:20:56 +00002964 // Don't optimize loads of the in-scope locals across this point.
2965 Hazards.emitWriteHazard();
2966
John McCallbd309292010-07-06 01:34:17 +00002967 // For a @synchronized (or a @try with no catches), just branch
2968 // through the cleanup to the rethrow block.
2969 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
2970 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00002971 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00002972 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00002973
2974 // Otherwise, we have to match against the caught exceptions.
2975 } else {
John McCall2dd7d442010-08-04 05:59:32 +00002976 // Retrieve the exception object. We may emit multiple blocks but
2977 // nothing can cross this so the value is already in SSA form.
2978 llvm::CallInst *Caught =
2979 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
2980 ExceptionData, "caught");
2981 Caught->setDoesNotThrow();
2982
John McCallbd309292010-07-06 01:34:17 +00002983 // Push the exception to rethrow onto the EH value stack for the
2984 // benefit of any @throws in the handlers.
2985 CGF.ObjCEHValueStack.push_back(Caught);
2986
Douglas Gregor96c79492010-04-23 22:50:49 +00002987 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002988
John McCall2dd7d442010-08-04 05:59:32 +00002989 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallbd309292010-07-06 01:34:17 +00002990
John McCall2dd7d442010-08-04 05:59:32 +00002991 llvm::BasicBlock *CatchBlock = 0;
2992 llvm::BasicBlock *CatchHandler = 0;
2993 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00002994 // Save the currently-propagating exception before
2995 // objc_exception_try_enter clears the exception slot.
2996 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
2997 "propagating_exception");
2998 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
2999
John McCall2dd7d442010-08-04 05:59:32 +00003000 // Enter a new exception try block (in case a @catch block
3001 // throws an exception).
3002 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3003 ->setDoesNotThrow();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003004
John McCall2dd7d442010-08-04 05:59:32 +00003005 llvm::CallInst *SetJmpResult =
3006 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3007 "setjmp.result");
3008 SetJmpResult->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003009
John McCall2dd7d442010-08-04 05:59:32 +00003010 llvm::Value *Threw =
3011 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3012
3013 CatchBlock = CGF.createBasicBlock("catch");
3014 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3015 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3016
3017 CGF.EmitBlock(CatchBlock);
3018 }
3019
3020 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003021
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003022 // Handle catch list. As a special case we check if everything is
3023 // matched and avoid generating code for falling off the end if
3024 // so.
3025 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00003026 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3027 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003028
Douglas Gregor46a572b2010-04-26 16:46:50 +00003029 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff7cae42b2009-07-10 23:34:53 +00003030 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar523208f2008-09-27 07:36:24 +00003031
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003032 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003033 if (!CatchParam) {
3034 AllMatched = true;
3035 } else {
John McCall9dd450b2009-09-21 23:43:11 +00003036 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003037
John McCallbd309292010-07-06 01:34:17 +00003038 // catch(id e) always matches under this ABI, since only
3039 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00003040 // FIXME: For the time being we also match id<X>; this should
3041 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00003042 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003043 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003044 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003045
John McCallbd309292010-07-06 01:34:17 +00003046 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003047 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00003048 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3049
Anders Carlsson9396a892008-09-11 09:15:33 +00003050 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00003051 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003052 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00003053
3054 // These types work out because ConvertType(id) == i8*.
Steve Naroff371b8fb2009-03-03 19:52:17 +00003055 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson9396a892008-09-11 09:15:33 +00003056 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003057
Anders Carlsson9396a892008-09-11 09:15:33 +00003058 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003059
3060 // The scope of the catch variable ends right here.
3061 CatchVarCleanups.ForceCleanup();
3062
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003063 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003064 break;
3065 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003066
Steve Naroff7cae42b2009-07-10 23:34:53 +00003067 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00003068 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00003069
3070 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00003071 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3072 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003073
3074 // Check if the @catch block matches the exception object.
John McCall96fa4842010-05-17 21:00:27 +00003075 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003076
John McCallbd309292010-07-06 01:34:17 +00003077 llvm::CallInst *Match =
Chris Lattnerc6406db2009-04-22 02:26:14 +00003078 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3079 Class, Caught, "match");
John McCallbd309292010-07-06 01:34:17 +00003080 Match->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003081
John McCallbd309292010-07-06 01:34:17 +00003082 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3083 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003084
3085 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00003086 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003087
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003088 // Emit the @catch block.
3089 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00003090
3091 // Collect any cleanups for the catch variable. The scope lasts until
3092 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00003093 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00003094
John McCall1c9c3fd2010-10-15 04:57:14 +00003095 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003096 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003097
John McCallbd309292010-07-06 01:34:17 +00003098 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003099 llvm::Value *Tmp =
3100 CGF.Builder.CreateBitCast(Caught,
3101 CGF.ConvertType(CatchParam->getType()),
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003102 "tmp");
Steve Naroff371b8fb2009-03-03 19:52:17 +00003103 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003104
Anders Carlsson9396a892008-09-11 09:15:33 +00003105 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003106
3107 // We're done with the catch variable.
3108 CatchVarCleanups.ForceCleanup();
3109
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003110 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003111
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003112 CGF.EmitBlock(NextCatchBlock);
3113 }
3114
John McCallbd309292010-07-06 01:34:17 +00003115 CGF.ObjCEHValueStack.pop_back();
3116
John McCall2dd7d442010-08-04 05:59:32 +00003117 // If nothing wanted anything to do with the caught exception,
3118 // kill the extract call.
3119 if (Caught->use_empty())
3120 Caught->eraseFromParent();
3121
3122 if (!AllMatched)
3123 CGF.EmitBranchThroughCleanup(FinallyRethrow);
3124
3125 if (HasFinally) {
3126 // Emit the exception handler for the @catch blocks.
3127 CGF.EmitBlock(CatchHandler);
3128
3129 // In theory we might now need a write hazard, but actually it's
3130 // unnecessary because there's no local-accessing code between
3131 // the try's write hazard and here.
3132 //Hazards.emitWriteHazard();
3133
John McCall9916e3f2010-10-04 23:42:51 +00003134 // Extract the new exception and save it to the
3135 // propagating-exception slot.
3136 assert(PropagatingExnVar);
3137 llvm::CallInst *NewCaught =
3138 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3139 ExceptionData, "caught");
3140 NewCaught->setDoesNotThrow();
3141 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
3142
John McCall2dd7d442010-08-04 05:59:32 +00003143 // Don't pop the catch handler; the throw already did.
3144 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003145 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003146 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003147 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003148
John McCall42227ed2010-07-31 23:20:56 +00003149 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00003150 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003151
John McCallbd309292010-07-06 01:34:17 +00003152 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00003153 CGF.Builder.restoreIP(TryFallthroughIP);
3154 if (CGF.HaveInsertPoint())
3155 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00003156 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00003157 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003158
John McCallbd309292010-07-06 01:34:17 +00003159 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00003160 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00003161 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00003162 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00003163 // If we have a propagating-exception variable, check it.
3164 llvm::Value *PropagatingExn;
3165 if (PropagatingExnVar) {
3166 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00003167
John McCall9916e3f2010-10-04 23:42:51 +00003168 // Otherwise, just look in the buffer for the exception to throw.
3169 } else {
3170 llvm::CallInst *Caught =
3171 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3172 ExceptionData);
3173 Caught->setDoesNotThrow();
3174 PropagatingExn = Caught;
3175 }
3176
3177 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
John McCallbd309292010-07-06 01:34:17 +00003178 ->setDoesNotThrow();
3179 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00003180 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003181
John McCall42227ed2010-07-31 23:20:56 +00003182 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003183}
3184
3185void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003186 const ObjCAtThrowStmt &S) {
Anders Carlssone005aa12008-09-09 16:16:55 +00003187 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003188
Anders Carlssone005aa12008-09-09 16:16:55 +00003189 if (const Expr *ThrowExpr = S.getThrowExpr()) {
3190 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003191 ExceptionAsObject =
Anders Carlssone005aa12008-09-09 16:16:55 +00003192 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
3193 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003194 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003195 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00003196 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00003197 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003198
John McCallbd309292010-07-06 01:34:17 +00003199 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3200 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003201 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003202
3203 // Clear the insertion point to indicate we are in unreachable code.
3204 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003205}
3206
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003207/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003208/// object: objc_read_weak (id *src)
3209///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003210llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003211 llvm::Value *AddrWeakObj) {
Eli Friedmana374b682009-03-07 03:57:15 +00003212 const llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003213 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3214 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3215 ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00003216 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003217 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00003218 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003219 return read_weak;
3220}
3221
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003222/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
3223/// objc_assign_weak (id src, id *dst)
3224///
3225void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003226 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003227 const llvm::Type * SrcTy = src->getType();
3228 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003229 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003230 assert(Size <= 8 && "does not support size > 8");
3231 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003232 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003233 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3234 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003235 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3236 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00003237 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003238 src, dst, "weakassign");
3239 return;
3240}
3241
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003242/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
3243/// objc_assign_global (id src, id *dst)
3244///
3245void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00003246 llvm::Value *src, llvm::Value *dst,
3247 bool threadlocal) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003248 const llvm::Type * SrcTy = src->getType();
3249 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003250 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003251 assert(Size <= 8 && "does not support size > 8");
3252 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003253 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003254 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3255 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003256 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3257 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00003258 if (!threadlocal)
3259 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
3260 src, dst, "globalassign");
3261 else
3262 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
3263 src, dst, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003264 return;
3265}
3266
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003267/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003268/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003269///
3270void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003271 llvm::Value *src, llvm::Value *dst,
3272 llvm::Value *ivarOffset) {
3273 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003274 const llvm::Type * SrcTy = src->getType();
3275 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003276 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003277 assert(Size <= 8 && "does not support size > 8");
3278 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003279 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003280 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3281 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003282 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3283 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003284 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3285 src, dst, ivarOffset);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003286 return;
3287}
3288
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003289/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
3290/// objc_assign_strongCast (id src, id *dst)
3291///
3292void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003293 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003294 const llvm::Type * SrcTy = src->getType();
3295 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003296 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003297 assert(Size <= 8 && "does not support size > 8");
3298 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003299 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003300 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3301 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003302 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3303 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00003304 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003305 src, dst, "weakassign");
3306 return;
3307}
3308
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003309void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003310 llvm::Value *DestPtr,
3311 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003312 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003313 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3314 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003315 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003316 DestPtr, SrcPtr, size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003317 return;
3318}
3319
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003320/// EmitObjCValueForIvar - Code Gen for ivar reference.
3321///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003322LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3323 QualType ObjectTy,
3324 llvm::Value *BaseValue,
3325 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003326 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00003327 const ObjCInterfaceDecl *ID =
3328 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003329 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3330 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003331}
3332
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003333llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00003334 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003335 const ObjCIvarDecl *Ivar) {
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003336 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003337 return llvm::ConstantInt::get(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003338 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3339 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003340}
3341
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003342/* *** Private Interface *** */
3343
3344/// EmitImageInfo - Emit the image info marker used to encode some module
3345/// level information.
3346///
3347/// See: <rdr://4810609&4810587&4810587>
3348/// struct IMAGE_INFO {
3349/// unsigned version;
3350/// unsigned flags;
3351/// };
3352enum ImageInfoFlags {
Daniel Dunbar5e639272010-04-25 20:39:01 +00003353 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003354 eImageInfo_GarbageCollected = (1 << 1),
3355 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003356 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
3357
Daniel Dunbar5e639272010-04-25 20:39:01 +00003358 // A flag indicating that the module has no instances of a @synthesize of a
3359 // superclass variable. <rdar://problem/6803242>
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003360 eImageInfo_CorrectedSynthesize = (1 << 4)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003361};
3362
Daniel Dunbar5e639272010-04-25 20:39:01 +00003363void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003364 unsigned version = 0; // Version is unused?
3365 unsigned flags = 0;
3366
3367 // FIXME: Fix and continue?
3368 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
3369 flags |= eImageInfo_GarbageCollected;
3370 if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
3371 flags |= eImageInfo_GCOnly;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003372
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003373 // We never allow @synthesize of a superclass property.
3374 flags |= eImageInfo_CorrectedSynthesize;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003375
Chris Lattner5e016ae2010-06-27 07:15:29 +00003376 const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
3377
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003378 // Emitted as int[2];
3379 llvm::Constant *values[2] = {
Chris Lattner5e016ae2010-06-27 07:15:29 +00003380 llvm::ConstantInt::get(Int32Ty, version),
3381 llvm::ConstantInt::get(Int32Ty, flags)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003382 };
Chris Lattner5e016ae2010-06-27 07:15:29 +00003383 llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003384
3385 const char *Section;
3386 if (ObjCABI == 1)
3387 Section = "__OBJC, __image_info,regular";
3388 else
3389 Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003390 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003391 CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
Owen Anderson47034e12009-07-28 18:33:04 +00003392 llvm::ConstantArray::get(AT, values, 2),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003393 Section,
3394 0,
3395 true);
3396 GV->setConstant(true);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003397}
3398
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003399
3400// struct objc_module {
3401// unsigned long version;
3402// unsigned long size;
3403// const char *name;
3404// Symtab symtab;
3405// };
3406
3407// FIXME: Get from somewhere
3408static const int ModuleVersion = 7;
3409
3410void CGObjCMac::EmitModuleInfo() {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003411 uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003412
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003413 std::vector<llvm::Constant*> Values(4);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003414 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
3415 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbar92992502008-08-15 22:20:32 +00003416 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbarb036db82008-08-13 03:21:16 +00003417 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003418 Values[3] = EmitModuleSymbols();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003419 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson0e0189d2009-07-27 22:29:56 +00003420 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003421 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00003422 4, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003423}
3424
3425llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003426 unsigned NumClasses = DefinedClasses.size();
3427 unsigned NumCategories = DefinedCategories.size();
3428
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003429 // Return null if no symbols were defined.
3430 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00003431 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003432
3433 std::vector<llvm::Constant*> Values(5);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003434 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Anderson0b75f232009-07-31 20:28:54 +00003435 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003436 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3437 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003438
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003439 // The runtime expects exactly the list of defined classes followed
3440 // by the list of defined categories, in a single array.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003441 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003442 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00003443 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003444 ObjCTypes.Int8PtrTy);
3445 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003446 Symbols[NumClasses + i] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003447 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003448 ObjCTypes.Int8PtrTy);
3449
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003450 Values[4] =
Owen Anderson9793f0e2009-07-29 22:16:19 +00003451 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003452 NumClasses + NumCategories),
3453 Symbols);
3454
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00003455 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003456
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003457 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003458 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3459 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003460 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003461 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003462}
3463
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003464llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003465 const ObjCInterfaceDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003466 LazySymbols.insert(ID->getIdentifier());
3467
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003468 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003469
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003470 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003471 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00003472 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003473 ObjCTypes.ClassPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003474 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003475 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3476 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003477 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003478 }
3479
Daniel Dunbarc76493a2009-11-29 21:23:36 +00003480 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003481}
3482
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00003483llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
3484 bool lvalue) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003485 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003486
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003487 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003488 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00003489 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003490 ObjCTypes.SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003491 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003492 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3493 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003494 4, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003495 }
3496
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00003497 if (lvalue)
3498 return Entry;
Daniel Dunbarc76493a2009-11-29 21:23:36 +00003499 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003500}
3501
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00003502llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003503 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003504
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003505 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003506 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003507 llvm::ConstantArray::get(VMContext,
3508 Ident->getNameStart()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003509 ((ObjCABI == 2) ?
3510 "__TEXT,__objc_classname,cstring_literals" :
3511 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003512 1, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003513
Owen Anderson170229f2009-07-14 23:10:40 +00003514 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003515}
3516
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00003517llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
3518 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
3519 I = MethodDefinitions.find(MD);
3520 if (I != MethodDefinitions.end())
3521 return I->second;
3522
3523 if (MD->hasBody() && MD->getPCHLevel() > 0) {
3524 // MD isn't emitted yet because it comes from PCH.
3525 CGM.EmitTopLevelDecl(const_cast<ObjCMethodDecl*>(MD));
3526 assert(MethodDefinitions[MD] && "EmitTopLevelDecl didn't emit the method!");
3527 return MethodDefinitions[MD];
3528 }
3529
3530 return NULL;
3531}
3532
Fariborz Jahanian01dff422009-03-05 19:17:31 +00003533/// GetIvarLayoutName - Returns a unique constant for the given
3534/// ivar layout bitmap.
3535llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003536 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003537 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00003538}
3539
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003540void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003541 unsigned int BytePos,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003542 bool ForStrongLayout,
3543 bool &HasUnion) {
3544 const RecordDecl *RD = RT->getDecl();
3545 // FIXME - Use iterator.
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003546 llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003547 const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003548 const llvm::StructLayout *RecLayout =
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003549 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003550
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003551 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3552 ForStrongLayout, HasUnion);
3553}
3554
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +00003555void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003556 const llvm::StructLayout *Layout,
3557 const RecordDecl *RD,
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003558 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003559 unsigned int BytePos, bool ForStrongLayout,
3560 bool &HasUnion) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003561 bool IsUnion = (RD && RD->isUnion());
3562 uint64_t MaxUnionIvarSize = 0;
3563 uint64_t MaxSkippedUnionIvarSize = 0;
3564 FieldDecl *MaxField = 0;
3565 FieldDecl *MaxSkippedField = 0;
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003566 FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003567 uint64_t MaxFieldOffset = 0;
3568 uint64_t MaxSkippedFieldOffset = 0;
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003569 uint64_t LastBitfieldOrUnnamedOffset = 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003570
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003571 if (RecFields.empty())
3572 return;
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003573 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3574 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3575
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003576 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003577 FieldDecl *Field = RecFields[i];
Daniel Dunbar62b10702009-05-03 23:35:23 +00003578 uint64_t FieldOffset;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00003579 if (RD) {
Daniel Dunbard51c1a62010-04-14 17:02:21 +00003580 // Note that 'i' here is actually the field index inside RD of Field,
3581 // although this dependency is hidden.
3582 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Ken Dyckc5ca8762011-04-14 00:43:09 +00003583 FieldOffset = RL.getFieldOffset(i) / ByteSizeInBits;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00003584 } else
Daniel Dunbar62b10702009-05-03 23:35:23 +00003585 FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003586
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003587 // Skip over unnamed or bitfields
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003588 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003589 LastFieldBitfieldOrUnnamed = Field;
3590 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003591 continue;
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003592 }
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003593
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003594 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003595 QualType FQT = Field->getType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003596 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003597 if (FQT->isUnionType())
3598 HasUnion = true;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003599
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003600 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003601 BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003602 ForStrongLayout, HasUnion);
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003603 continue;
3604 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003605
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003606 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003607 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003608 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003609 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003610 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003611 FQT = CArray->getElementType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003612 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3613 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003614 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003615 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003616 FQT = CArray->getElementType();
3617 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003618
3619 assert(!FQT->isUnionType() &&
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003620 "layout for array of unions not supported");
Fariborz Jahanian9a7d57d2011-01-03 19:23:18 +00003621 if (FQT->isRecordType() && ElCount) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003622 int OldIndex = IvarsInfo.size() - 1;
3623 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003624
Ted Kremenekc23c7e62009-07-29 21:53:49 +00003625 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003626 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003627 ForStrongLayout, HasUnion);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003628
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003629 // Replicate layout information for each array element. Note that
3630 // one element is already done.
3631 uint64_t ElIx = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003632 for (int FirstIndex = IvarsInfo.size() - 1,
3633 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003634 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003635 for (int i = OldIndex+1; i <= FirstIndex; ++i)
3636 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
3637 IvarsInfo[i].ivar_size));
3638 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
3639 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
3640 SkipIvars[i].ivar_size));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003641 }
3642 continue;
3643 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003644 }
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003645 // At this point, we are done with Record/Union and array there of.
3646 // For other arrays we are down to its element type.
John McCall8ccfcb52009-09-24 19:53:00 +00003647 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003648
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003649 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall8ccfcb52009-09-24 19:53:00 +00003650 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3651 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00003652 if (IsUnion) {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003653 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00003654 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003655 MaxUnionIvarSize = UnionIvarSize;
3656 MaxField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003657 MaxFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003658 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00003659 } else {
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003660 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003661 FieldSize / WordSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003662 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003663 } else if ((ForStrongLayout &&
John McCall8ccfcb52009-09-24 19:53:00 +00003664 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3665 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00003666 if (IsUnion) {
Mike Stump18bb9282009-05-16 07:57:57 +00003667 // FIXME: Why the asymmetry? We divide by word size in bits on other
3668 // side.
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003669 uint64_t UnionIvarSize = FieldSize;
Daniel Dunbar22007d32009-05-03 13:32:01 +00003670 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003671 MaxSkippedUnionIvarSize = UnionIvarSize;
3672 MaxSkippedField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003673 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003674 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00003675 } else {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003676 // FIXME: Why the asymmetry, we divide by byte size in bits here?
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003677 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003678 FieldSize / ByteSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003679 }
3680 }
3681 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003682
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003683 if (LastFieldBitfieldOrUnnamed) {
3684 if (LastFieldBitfieldOrUnnamed->isBitField()) {
3685 // Last field was a bitfield. Must update skip info.
3686 Expr *BitWidth = LastFieldBitfieldOrUnnamed->getBitWidth();
3687 uint64_t BitFieldSize =
3688 BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
3689 GC_IVAR skivar;
3690 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
3691 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3692 + ((BitFieldSize % ByteSizeInBits) != 0);
3693 SkipIvars.push_back(skivar);
3694 } else {
3695 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
3696 // Last field was unnamed. Must update skip info.
3697 unsigned FieldSize
3698 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
3699 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
3700 FieldSize / ByteSizeInBits));
3701 }
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003702 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003703
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003704 if (MaxField)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003705 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003706 MaxUnionIvarSize));
3707 if (MaxSkippedField)
Daniel Dunbar5b743912009-05-03 23:31:46 +00003708 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003709 MaxSkippedUnionIvarSize));
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00003710}
3711
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00003712/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
3713/// the computations and returning the layout bitmap (for ivar or blocks) in
3714/// the given argument BitMap string container. Routine reads
3715/// two containers, IvarsInfo and SkipIvars which are assumed to be
3716/// filled already by the caller.
3717llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string& BitMap) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003718 unsigned int WordsToScan, WordsToSkip;
Benjamin Kramerabd5b902009-10-13 10:07:13 +00003719 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003720
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003721 // Build the string of skip/scan nibbles
Fariborz Jahaniance5676572009-04-24 17:15:27 +00003722 llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003723 unsigned int WordSize =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003724 CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003725 if (IvarsInfo[0].ivar_bytepos == 0) {
3726 WordsToSkip = 0;
3727 WordsToScan = IvarsInfo[0].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003728 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003729 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3730 WordsToScan = IvarsInfo[0].ivar_size;
3731 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003732 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003733 unsigned int TailPrevGCObjC =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003734 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003735 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003736 // consecutive 'scanned' object pointers.
3737 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003738 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003739 // Skip over 'gc'able object pointer which lay over each other.
3740 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
3741 continue;
3742 // Must skip over 1 or more words. We save current skip/scan values
3743 // and start a new pair.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003744 SKIP_SCAN SkScan;
3745 SkScan.skip = WordsToSkip;
3746 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003747 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003748
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003749 // Skip the hole.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003750 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3751 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003752 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003753 WordsToSkip = 0;
3754 WordsToScan = IvarsInfo[i].ivar_size;
3755 }
3756 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003757 if (WordsToScan > 0) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003758 SKIP_SCAN SkScan;
3759 SkScan.skip = WordsToSkip;
3760 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003761 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003762 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003763
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003764 if (!SkipIvars.empty()) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003765 unsigned int LastIndex = SkipIvars.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003766 int LastByteSkipped =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003767 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003768 LastIndex = IvarsInfo.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003769 int LastByteScanned =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003770 IvarsInfo[LastIndex].ivar_bytepos +
3771 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003772 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramerd20ef752009-12-25 15:43:36 +00003773 if (LastByteSkipped > LastByteScanned) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003774 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003775 SKIP_SCAN SkScan;
3776 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3777 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003778 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003779 }
3780 }
3781 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3782 // as 0xMN.
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003783 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003784 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003785 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3786 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3787 // 0xM0 followed by 0x0N detected.
3788 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
3789 for (int j = i+1; j < SkipScan; j++)
3790 SkipScanIvars[j] = SkipScanIvars[j+1];
3791 --SkipScan;
3792 }
3793 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003794
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003795 // Generate the string.
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003796 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003797 unsigned char byte;
3798 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
3799 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
3800 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
3801 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003802
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003803 // first skip big.
3804 for (unsigned int ix = 0; ix < skip_big; ix++)
3805 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003806
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003807 // next (skip small, scan)
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003808 if (skip_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003809 byte = skip_small << 4;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003810 if (scan_big > 0) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003811 byte |= 0xf;
3812 --scan_big;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003813 } else if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003814 byte |= scan_small;
3815 scan_small = 0;
3816 }
3817 BitMap += byte;
3818 }
3819 // next scan big
3820 for (unsigned int ix = 0; ix < scan_big; ix++)
3821 BitMap += (unsigned char)(0x0f);
3822 // last scan small
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003823 if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003824 byte = scan_small;
3825 BitMap += byte;
3826 }
3827 }
3828 // null terminate string.
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003829 unsigned char zero = 0;
3830 BitMap += zero;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003831
3832 llvm::GlobalVariable * Entry =
3833 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3834 llvm::ConstantArray::get(VMContext, BitMap.c_str()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003835 ((ObjCABI == 2) ?
3836 "__TEXT,__objc_classname,cstring_literals" :
3837 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003838 1, true);
3839 return getConstantGEP(VMContext, Entry, 0, 0);
3840}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003841
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003842/// BuildIvarLayout - Builds ivar layout bitmap for the class
3843/// implementation for the __strong or __weak case.
3844/// The layout map displays which words in ivar list must be skipped
3845/// and which must be scanned by GC (see below). String is built of bytes.
3846/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
3847/// of words to skip and right nibble is count of words to scan. So, each
3848/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
3849/// represented by a 0x00 byte which also ends the string.
3850/// 1. when ForStrongLayout is true, following ivars are scanned:
3851/// - id, Class
3852/// - object *
3853/// - __strong anything
3854///
3855/// 2. When ForStrongLayout is false, following ivars are scanned:
3856/// - __weak anything
3857///
3858llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
3859 const ObjCImplementationDecl *OMD,
3860 bool ForStrongLayout) {
3861 bool hasUnion = false;
3862
3863 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
3864 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
3865 return llvm::Constant::getNullValue(PtrTy);
3866
Fariborz Jahaniana50b3a22010-08-20 21:21:08 +00003867 llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003868 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
Fariborz Jahaniana50b3a22010-08-20 21:21:08 +00003869 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003870
Fariborz Jahaniana50b3a22010-08-20 21:21:08 +00003871 llvm::SmallVector<FieldDecl*, 32> RecFields;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003872 for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
3873 RecFields.push_back(cast<FieldDecl>(Ivars[k]));
3874
3875 if (RecFields.empty())
3876 return llvm::Constant::getNullValue(PtrTy);
3877
3878 SkipIvars.clear();
3879 IvarsInfo.clear();
3880
3881 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
3882 if (IvarsInfo.empty())
3883 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00003884 // Sort on byte position in case we encounterred a union nested in
3885 // the ivar list.
3886 if (hasUnion && !IvarsInfo.empty())
3887 std::sort(IvarsInfo.begin(), IvarsInfo.end());
3888 if (hasUnion && !SkipIvars.empty())
3889 std::sort(SkipIvars.begin(), SkipIvars.end());
3890
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003891 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00003892 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003893
3894 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003895 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00003896 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar56df9772010-08-17 22:39:59 +00003897 OMD->getClassInterface()->getName().data());
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00003898 const unsigned char *s = (unsigned char*)BitMap.c_str();
3899 for (unsigned i = 0; i < BitMap.size(); i++)
3900 if (!(s[i] & 0xf0))
3901 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
3902 else
3903 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
3904 printf("\n");
3905 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003906 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00003907}
3908
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003909llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003910 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3911
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003912 // FIXME: Avoid std::string copying.
3913 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003914 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Owen Anderson41a75022009-08-13 21:57:51 +00003915 llvm::ConstantArray::get(VMContext, Sel.getAsString()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003916 ((ObjCABI == 2) ?
3917 "__TEXT,__objc_methname,cstring_literals" :
3918 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003919 1, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003920
Owen Anderson170229f2009-07-14 23:10:40 +00003921 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003922}
3923
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003924// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003925llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003926 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
3927}
3928
Daniel Dunbarf5c18462009-04-20 06:54:31 +00003929llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00003930 std::string TypeStr;
3931 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
3932
3933 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarb036db82008-08-13 03:21:16 +00003934
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003935 if (!Entry)
3936 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson41a75022009-08-13 21:57:51 +00003937 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003938 ((ObjCABI == 2) ?
3939 "__TEXT,__objc_methtype,cstring_literals" :
3940 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003941 1, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003942
Owen Anderson170229f2009-07-14 23:10:40 +00003943 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003944}
3945
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003946llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003947 std::string TypeStr;
Douglas Gregora9d84932011-05-27 01:19:52 +00003948 if (CGM.getContext().getObjCEncodingForMethodDecl(
3949 const_cast<ObjCMethodDecl*>(D),
3950 TypeStr))
3951 return 0;
Devang Patel4b6e4bb2009-03-04 18:21:39 +00003952
3953 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3954
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003955 if (!Entry)
3956 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson41a75022009-08-13 21:57:51 +00003957 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003958 ((ObjCABI == 2) ?
3959 "__TEXT,__objc_methtype,cstring_literals" :
3960 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003961 1, true);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00003962
Owen Anderson170229f2009-07-14 23:10:40 +00003963 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003964}
3965
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003966// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003967llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003968 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003969
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003970 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003971 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003972 llvm::ConstantArray::get(VMContext,
3973 Ident->getNameStart()),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003974 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003975 1, true);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003976
Owen Anderson170229f2009-07-14 23:10:40 +00003977 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003978}
3979
3980// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00003981// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003982llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003983CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
3984 const Decl *Container) {
Daniel Dunbar4932b362008-08-28 04:38:10 +00003985 std::string TypeStr;
3986 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003987 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
3988}
3989
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003990void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003991 const ObjCContainerDecl *CD,
Daniel Dunbard2386812009-10-19 01:21:19 +00003992 llvm::SmallVectorImpl<char> &Name) {
3993 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00003994 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00003995 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
3996 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003997 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00003998 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramerb11416d2010-04-17 09:33:03 +00003999 OS << '(' << CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00004000 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004001}
4002
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004003void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004004 EmitModuleInfo();
4005
Daniel Dunbarc475d422008-10-29 22:36:39 +00004006 // Emit the dummy bodies for any protocols which were referenced but
4007 // never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004008 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerf56501c2009-07-17 23:57:13 +00004009 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4010 if (I->second->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00004011 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004012
Daniel Dunbarc475d422008-10-29 22:36:39 +00004013 std::vector<llvm::Constant*> Values(5);
Owen Anderson0b75f232009-07-31 20:28:54 +00004014 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004015 Values[1] = GetClassName(I->first);
Owen Anderson0b75f232009-07-31 20:28:54 +00004016 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004017 Values[3] = Values[4] =
Owen Anderson0b75f232009-07-31 20:28:54 +00004018 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004019 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004020 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarc475d422008-10-29 22:36:39 +00004021 Values));
Chris Lattnerf56501c2009-07-17 23:57:13 +00004022 CGM.AddUsedGlobal(I->second);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004023 }
4024
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004025 // Add assembler directives to add lazy undefined symbol references
4026 // for classes which are referenced but not defined. This is
4027 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00004028 //
4029 // FIXME: It would be nice if we had an LLVM construct for this.
4030 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
4031 llvm::SmallString<256> Asm;
4032 Asm += CGM.getModule().getModuleInlineAsm();
4033 if (!Asm.empty() && Asm.back() != '\n')
4034 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004035
Daniel Dunbard027a922009-09-07 00:20:42 +00004036 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbard027a922009-09-07 00:20:42 +00004037 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4038 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar07d07852009-10-18 21:17:35 +00004039 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4040 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnera299f2c2010-04-17 18:26:20 +00004041 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004042 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnera299f2c2010-04-17 18:26:20 +00004043 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004044 }
4045
4046 for (size_t i = 0; i < DefinedCategoryNames.size(); ++i) {
4047 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4048 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4049 }
Chris Lattnera299f2c2010-04-17 18:26:20 +00004050
Daniel Dunbard027a922009-09-07 00:20:42 +00004051 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004052 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004053}
4054
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004055CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004056 : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00004057 ObjCTypes(cgm) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004058 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004059 ObjCABI = 2;
4060}
4061
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004062/* *** */
4063
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004064ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004065 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004066 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4067 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004068
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004069 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004070 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004071 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004072 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Benjamin Kramerabd5b902009-10-13 10:07:13 +00004073 Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004074
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004075 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004076 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004077 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004078
Mike Stump18bb9282009-05-16 07:57:57 +00004079 // FIXME: It would be nice to unify this with the opaque type, so that the IR
4080 // comes out a bit cleaner.
Daniel Dunbarb036db82008-08-13 03:21:16 +00004081 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004082 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004083
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004084 // I'm not sure I like this. The implicit coordination is a bit
4085 // gross. We should solve this in a reasonable fashion because this
4086 // is a pretty common task (match some runtime data structure with
4087 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004088
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004089 // FIXME: This is leaked.
4090 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004091
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004092 // struct _objc_super {
4093 // id self;
4094 // Class cls;
4095 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00004096 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00004097 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00004098 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004099 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004100 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith938f40b2011-06-11 17:19:42 +00004101 Ctx.getObjCIdType(), 0, 0, false, false));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004102 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith938f40b2011-06-11 17:19:42 +00004103 Ctx.getObjCClassType(), 0, 0, false, false));
Douglas Gregord5058122010-02-11 01:19:42 +00004104 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004105
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004106 SuperCTy = Ctx.getTagDeclType(RD);
4107 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004108
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004109 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004110 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4111
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004112 // struct _prop_t {
4113 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004114 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004115 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004116 PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004117 CGM.getModule().addTypeName("struct._prop_t",
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004118 PropertyTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004119
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004120 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004121 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004122 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004123 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004124 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004125 PropertyListTy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004126 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004127 llvm::ArrayType::get(PropertyTy, 0),
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004128 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004129 CGM.getModule().addTypeName("struct._prop_list_t",
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004130 PropertyListTy);
4131 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004132 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004133
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004134 // struct _objc_method {
4135 // SEL _cmd;
4136 // char *method_type;
4137 // char *_imp;
4138 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004139 MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004140 Int8PtrTy,
4141 Int8PtrTy,
4142 NULL);
4143 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004144
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004145 // struct _objc_cache *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004146 CacheTy = llvm::OpaqueType::get(VMContext);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004147 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004148 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004149}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004150
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004151ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004152 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004153 // struct _objc_method_description {
4154 // SEL name;
4155 // char *types;
4156 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004157 MethodDescriptionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004158 llvm::StructType::get(VMContext, SelectorPtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004159 Int8PtrTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00004160 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004161 CGM.getModule().addTypeName("struct._objc_method_description",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004162 MethodDescriptionTy);
4163
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004164 // struct _objc_method_description_list {
4165 // int count;
4166 // struct _objc_method_description[1];
4167 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004168 MethodDescriptionListTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004169 llvm::StructType::get(VMContext, IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004170 llvm::ArrayType::get(MethodDescriptionTy, 0),
Daniel Dunbarb036db82008-08-13 03:21:16 +00004171 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004172 CGM.getModule().addTypeName("struct._objc_method_description_list",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004173 MethodDescriptionListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004174
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004175 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004176 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004177 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004178
Daniel Dunbarb036db82008-08-13 03:21:16 +00004179 // Protocol description structures
4180
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004181 // struct _objc_protocol_extension {
4182 // uint32_t size; // sizeof(struct _objc_protocol_extension)
4183 // struct _objc_method_description_list *optional_instance_methods;
4184 // struct _objc_method_description_list *optional_class_methods;
4185 // struct _objc_property_list *instance_properties;
4186 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004187 ProtocolExtensionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004188 llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004189 MethodDescriptionListPtrTy,
4190 MethodDescriptionListPtrTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00004191 PropertyListPtrTy,
4192 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004193 CGM.getModule().addTypeName("struct._objc_protocol_extension",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004194 ProtocolExtensionTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004195
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004196 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004197 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004198
Daniel Dunbarc475d422008-10-29 22:36:39 +00004199 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00004200
Owen Andersonc36edfe2009-08-13 23:27:53 +00004201 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
4202 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004203
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004204 const llvm::Type *T =
Mike Stump11289f42009-09-09 15:08:12 +00004205 llvm::StructType::get(VMContext,
Owen Anderson758428f2009-08-05 23:18:46 +00004206 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004207 LongTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004208 llvm::ArrayType::get(ProtocolTyHolder, 0),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004209 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004210 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
4211
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004212 // struct _objc_protocol {
4213 // struct _objc_protocol_extension *isa;
4214 // char *protocol_name;
4215 // struct _objc_protocol **_objc_protocol_list;
4216 // struct _objc_method_description_list *instance_methods;
4217 // struct _objc_method_description_list *class_methods;
4218 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004219 T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004220 Int8PtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004221 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Daniel Dunbarb036db82008-08-13 03:21:16 +00004222 MethodDescriptionListPtrTy,
4223 MethodDescriptionListPtrTy,
4224 NULL);
4225 cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
4226
4227 ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004228 CGM.getModule().addTypeName("struct._objc_protocol_list",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004229 ProtocolListTy);
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004230 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004231 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004232
4233 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004234 CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004235 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004236
4237 // Class description structures
4238
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004239 // struct _objc_ivar {
4240 // char *ivar_name;
4241 // char *ivar_type;
4242 // int ivar_offset;
4243 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004244 IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004245 Int8PtrTy,
4246 IntTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004247 NULL);
4248 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
4249
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004250 // struct _objc_ivar_list *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004251 IvarListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004252 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004253 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004254
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004255 // struct _objc_method_list *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004256 MethodListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004257 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004258 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004259
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004260 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004261 ClassExtensionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004262 llvm::StructType::get(VMContext, IntTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004263 Int8PtrTy,
4264 PropertyListPtrTy,
4265 NULL);
4266 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004267 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004268
Owen Andersonc36edfe2009-08-13 23:27:53 +00004269 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004270
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004271 // struct _objc_class {
4272 // Class isa;
4273 // Class super_class;
4274 // char *name;
4275 // long version;
4276 // long info;
4277 // long instance_size;
4278 // struct _objc_ivar_list *ivars;
4279 // struct _objc_method_list *methods;
4280 // struct _objc_cache *cache;
4281 // struct _objc_protocol_list *protocols;
4282 // char *ivar_layout;
4283 // struct _objc_class_ext *ext;
4284 // };
Owen Anderson758428f2009-08-05 23:18:46 +00004285 T = llvm::StructType::get(VMContext,
4286 llvm::PointerType::getUnqual(ClassTyHolder),
Owen Anderson9793f0e2009-07-29 22:16:19 +00004287 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004288 Int8PtrTy,
4289 LongTy,
4290 LongTy,
4291 LongTy,
4292 IvarListPtrTy,
4293 MethodListPtrTy,
4294 CachePtrTy,
4295 ProtocolListPtrTy,
4296 Int8PtrTy,
4297 ClassExtensionPtrTy,
4298 NULL);
4299 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004300
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004301 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
4302 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004303 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004304
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004305 // struct _objc_category {
4306 // char *category_name;
4307 // char *class_name;
4308 // struct _objc_method_list *instance_method;
4309 // struct _objc_method_list *class_method;
4310 // uint32_t size; // sizeof(struct _objc_category)
4311 // struct _objc_property_list *instance_properties;// category's @property
4312 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004313 CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004314 Int8PtrTy,
4315 MethodListPtrTy,
4316 MethodListPtrTy,
4317 ProtocolListPtrTy,
4318 IntTy,
4319 PropertyListPtrTy,
4320 NULL);
4321 CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
4322
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004323 // Global metadata structures
4324
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004325 // struct _objc_symtab {
4326 // long sel_ref_cnt;
4327 // SEL *refs;
4328 // short cls_def_cnt;
4329 // short cat_def_cnt;
4330 // char *defs[cls_def_cnt + cat_def_cnt];
4331 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004332 SymtabTy = llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004333 SelectorPtrTy,
4334 ShortTy,
4335 ShortTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004336 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004337 NULL);
4338 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004339 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004340
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00004341 // struct _objc_module {
4342 // long version;
4343 // long size; // sizeof(struct _objc_module)
4344 // char *name;
4345 // struct _objc_symtab* symtab;
4346 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004347 ModuleTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004348 llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004349 LongTy,
4350 Int8PtrTy,
4351 SymtabPtrTy,
4352 NULL);
4353 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00004354
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004355
Mike Stump18bb9282009-05-16 07:57:57 +00004356 // FIXME: This is the size of the setjmp buffer and should be target
4357 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00004358 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004359
Anders Carlsson9ff22482008-09-09 10:10:21 +00004360 // Exceptions
Owen Anderson9793f0e2009-07-29 22:16:19 +00004361 const llvm::Type *StackPtrTy = llvm::ArrayType::get(
Benjamin Kramerabd5b902009-10-13 10:07:13 +00004362 llvm::Type::getInt8PtrTy(VMContext), 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004363
4364 ExceptionDataTy =
Chris Lattner5e016ae2010-06-27 07:15:29 +00004365 llvm::StructType::get(VMContext,
4366 llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
4367 SetJmpBufferSize),
Anders Carlsson9ff22482008-09-09 10:10:21 +00004368 StackPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004369 CGM.getModule().addTypeName("struct._objc_exception_data",
Anders Carlsson9ff22482008-09-09 10:10:21 +00004370 ExceptionDataTy);
4371
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00004372}
4373
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004374ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004375 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004376 // struct _method_list_t {
4377 // uint32_t entsize; // sizeof(struct _objc_method)
4378 // uint32_t method_count;
4379 // struct _objc_method method_list[method_count];
4380 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004381 MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004382 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004383 llvm::ArrayType::get(MethodTy, 0),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004384 NULL);
4385 CGM.getModule().addTypeName("struct.__method_list_t",
4386 MethodListnfABITy);
4387 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004388 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004389
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004390 // struct _protocol_t {
4391 // id isa; // NULL
4392 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004393 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004394 // const struct method_list_t * const instance_methods;
4395 // const struct method_list_t * const class_methods;
4396 // const struct method_list_t *optionalInstanceMethods;
4397 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004398 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004399 // const uint32_t size; // sizeof(struct _protocol_t)
4400 // const uint32_t flags; // = 0
4401 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004402
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004403 // Holder for struct _protocol_list_t *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004404 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004405
Owen Anderson758428f2009-08-05 23:18:46 +00004406 ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004407 Int8PtrTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004408 llvm::PointerType::getUnqual(
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004409 ProtocolListTyHolder),
4410 MethodListnfABIPtrTy,
4411 MethodListnfABIPtrTy,
4412 MethodListnfABIPtrTy,
4413 MethodListnfABIPtrTy,
4414 PropertyListPtrTy,
4415 IntTy,
4416 IntTy,
4417 NULL);
4418 CGM.getModule().addTypeName("struct._protocol_t",
4419 ProtocolnfABITy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004420
4421 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004422 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004423
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004424 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004425 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004426 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004427 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004428 ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004429 llvm::ArrayType::get(
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004430 ProtocolnfABIPtrTy, 0),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004431 NULL);
4432 CGM.getModule().addTypeName("struct._objc_protocol_list",
4433 ProtocolListnfABITy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004434 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004435 ProtocolListnfABITy);
4436
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004437 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004438 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004439
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004440 // struct _ivar_t {
4441 // unsigned long int *offset; // pointer to ivar offset location
4442 // char *name;
4443 // char *type;
4444 // uint32_t alignment;
4445 // uint32_t size;
4446 // }
Mike Stump11289f42009-09-09 15:08:12 +00004447 IvarnfABITy = llvm::StructType::get(VMContext,
Owen Anderson758428f2009-08-05 23:18:46 +00004448 llvm::PointerType::getUnqual(LongTy),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004449 Int8PtrTy,
4450 Int8PtrTy,
4451 IntTy,
4452 IntTy,
4453 NULL);
4454 CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004455
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004456 // struct _ivar_list_t {
4457 // uint32 entsize; // sizeof(struct _ivar_t)
4458 // uint32 count;
4459 // struct _iver_t list[count];
4460 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004461 IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004462 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004463 llvm::ArrayType::get(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004464 IvarnfABITy, 0),
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004465 NULL);
4466 CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004467
Owen Anderson9793f0e2009-07-29 22:16:19 +00004468 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004469
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004470 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004471 // uint32_t const flags;
4472 // uint32_t const instanceStart;
4473 // uint32_t const instanceSize;
4474 // uint32_t const reserved; // only when building for 64bit targets
4475 // const uint8_t * const ivarLayout;
4476 // const char *const name;
4477 // const struct _method_list_t * const baseMethods;
4478 // const struct _objc_protocol_list *const baseProtocols;
4479 // const struct _ivar_list_t *const ivars;
4480 // const uint8_t * const weakIvarLayout;
4481 // const struct _prop_list_t * const properties;
4482 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004483
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004484 // FIXME. Add 'reserved' field in 64bit abi mode!
Owen Anderson758428f2009-08-05 23:18:46 +00004485 ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004486 IntTy,
4487 IntTy,
4488 Int8PtrTy,
4489 Int8PtrTy,
4490 MethodListnfABIPtrTy,
4491 ProtocolListnfABIPtrTy,
4492 IvarListnfABIPtrTy,
4493 Int8PtrTy,
4494 PropertyListPtrTy,
4495 NULL);
4496 CGM.getModule().addTypeName("struct._class_ro_t",
4497 ClassRonfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004498
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004499 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
John McCall9dc0db22011-05-15 01:53:33 +00004500 const llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
4501 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
4502 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004503
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004504 // struct _class_t {
4505 // struct _class_t *isa;
4506 // struct _class_t * const superclass;
4507 // void *cache;
4508 // IMP *vtable;
4509 // struct class_ro_t *ro;
4510 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004511
Owen Andersonc36edfe2009-08-13 23:27:53 +00004512 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Owen Anderson170229f2009-07-14 23:10:40 +00004513 ClassnfABITy =
Owen Anderson758428f2009-08-05 23:18:46 +00004514 llvm::StructType::get(VMContext,
4515 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004516 llvm::PointerType::getUnqual(ClassTyHolder),
4517 CachePtrTy,
4518 llvm::PointerType::getUnqual(ImpnfABITy),
4519 llvm::PointerType::getUnqual(ClassRonfABITy),
4520 NULL);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004521 CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
4522
4523 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004524 ClassnfABITy);
4525
Fariborz Jahanian71394042009-01-23 23:53:38 +00004526 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004527 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004528
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004529 // struct _category_t {
4530 // const char * const name;
4531 // struct _class_t *const cls;
4532 // const struct _method_list_t * const instance_methods;
4533 // const struct _method_list_t * const class_methods;
4534 // const struct _protocol_list_t * const protocols;
4535 // const struct _prop_list_t * const properties;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00004536 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004537 CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
Fariborz Jahanian71394042009-01-23 23:53:38 +00004538 ClassnfABIPtrTy,
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00004539 MethodListnfABIPtrTy,
4540 MethodListnfABIPtrTy,
4541 ProtocolListnfABIPtrTy,
4542 PropertyListPtrTy,
4543 NULL);
4544 CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004545
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004546 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004547 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4548 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004549
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004550 // MessageRefTy - LLVM for:
4551 // struct _message_ref_t {
4552 // IMP messenger;
4553 // SEL name;
4554 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004555
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004556 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00004557 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00004558 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00004559 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004560 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004561 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith938f40b2011-06-11 17:19:42 +00004562 Ctx.VoidPtrTy, 0, 0, false, false));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004563 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith938f40b2011-06-11 17:19:42 +00004564 Ctx.getObjCSelType(), 0, 0, false, false));
Douglas Gregord5058122010-02-11 01:19:42 +00004565 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004566
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004567 MessageRefCTy = Ctx.getTagDeclType(RD);
4568 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4569 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004570
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004571 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004572 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004573
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004574 // SuperMessageRefTy - LLVM for:
4575 // struct _super_message_ref_t {
4576 // SUPER_IMP messenger;
4577 // SEL name;
4578 // };
Owen Anderson758428f2009-08-05 23:18:46 +00004579 SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004580 SelectorPtrTy,
4581 NULL);
4582 CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004583
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004584 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004585 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
4586
Daniel Dunbarb1559a42009-03-01 04:46:24 +00004587
4588 // struct objc_typeinfo {
4589 // const void** vtable; // objc_ehtype_vtable + 2
4590 // const char* name; // c++ typeinfo string
4591 // Class cls;
4592 // };
Owen Anderson758428f2009-08-05 23:18:46 +00004593 EHTypeTy = llvm::StructType::get(VMContext,
4594 llvm::PointerType::getUnqual(Int8PtrTy),
Daniel Dunbarb1559a42009-03-01 04:46:24 +00004595 Int8PtrTy,
4596 ClassnfABIPtrTy,
4597 NULL);
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00004598 CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004599 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00004600}
4601
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004602llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004603 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004604
Fariborz Jahanian71394042009-01-23 23:53:38 +00004605 return NULL;
4606}
4607
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004608void CGObjCNonFragileABIMac::AddModuleClassList(const
4609 std::vector<llvm::GlobalValue*>
4610 &Container,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004611 const char *SymbolName,
4612 const char *SectionName) {
4613 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004614
Daniel Dunbar19573e72009-05-15 21:48:48 +00004615 if (!NumClasses)
4616 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004617
Daniel Dunbar19573e72009-05-15 21:48:48 +00004618 std::vector<llvm::Constant*> Symbols(NumClasses);
4619 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00004620 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00004621 ObjCTypes.Int8PtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004622 llvm::Constant* Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004623 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004624 NumClasses),
4625 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004626
Daniel Dunbar19573e72009-05-15 21:48:48 +00004627 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00004628 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004629 llvm::GlobalValue::InternalLinkage,
4630 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00004631 SymbolName);
Daniel Dunbar710cb202010-04-25 20:39:32 +00004632 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00004633 GV->setSection(SectionName);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004634 CGM.AddUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00004635}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004636
Fariborz Jahanian71394042009-01-23 23:53:38 +00004637void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4638 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004639
Daniel Dunbar19573e72009-05-15 21:48:48 +00004640 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00004641 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004642 AddModuleClassList(DefinedClasses,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004643 "\01L_OBJC_LABEL_CLASS_$",
4644 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahanian67260552009-11-17 21:37:35 +00004645
Fariborz Jahanian67260552009-11-17 21:37:35 +00004646 for (unsigned i = 0; i < DefinedClasses.size(); i++) {
4647 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
4648 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4649 continue;
4650 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahanian67260552009-11-17 21:37:35 +00004651 }
4652
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004653 for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
4654 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
4655 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4656 continue;
4657 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4658 }
Fariborz Jahanian67260552009-11-17 21:37:35 +00004659
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004660 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004661 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4662 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004663
Fariborz Jahanian279abd32009-01-30 20:55:31 +00004664 // Build list of all implemented category addresses in array
4665 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004666 AddModuleClassList(DefinedCategories,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004667 "\01L_OBJC_LABEL_CATEGORY_$",
4668 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004669 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004670 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4671 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004672
Daniel Dunbar5e639272010-04-25 20:39:01 +00004673 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00004674}
4675
John McCall9e8bb002011-05-14 03:10:52 +00004676/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
4677/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004678/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004679/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00004680bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
4681 // At various points we've experimented with using vtable-based
4682 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004683 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
4684 default:
John McCall9e8bb002011-05-14 03:10:52 +00004685 llvm_unreachable("Invalid dispatch method!");
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004686 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00004687 return false;
John McCall9e8bb002011-05-14 03:10:52 +00004688 case CodeGenOptions::NonLegacy:
4689 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004690 case CodeGenOptions::Mixed:
4691 break;
4692 }
4693
4694 // If so, see whether this selector is in the white-list of things which must
4695 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00004696 if (VTableDispatchMethods.empty()) {
4697 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
4698 VTableDispatchMethods.insert(GetNullarySelector("class"));
4699 VTableDispatchMethods.insert(GetNullarySelector("self"));
4700 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
4701 VTableDispatchMethods.insert(GetNullarySelector("length"));
4702 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004703
John McCall9e8bb002011-05-14 03:10:52 +00004704 // These are vtable-based if GC is disabled.
4705 // Optimistically use vtable dispatch for hybrid compiles.
4706 if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) {
4707 VTableDispatchMethods.insert(GetNullarySelector("retain"));
4708 VTableDispatchMethods.insert(GetNullarySelector("release"));
4709 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
4710 }
4711
4712 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
4713 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
4714 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
4715 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
4716 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
4717 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
4718 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
4719
4720 // These are vtable-based if GC is enabled.
4721 // Optimistically use vtable dispatch for hybrid compiles.
4722 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
4723 VTableDispatchMethods.insert(GetNullarySelector("hash"));
4724 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
4725
4726 // "countByEnumeratingWithState:objects:count"
4727 IdentifierInfo *KeyIdents[] = {
4728 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
4729 &CGM.getContext().Idents.get("objects"),
4730 &CGM.getContext().Idents.get("count")
4731 };
4732 VTableDispatchMethods.insert(
4733 CGM.getContext().Selectors.getSelector(3, KeyIdents));
4734 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004735 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004736
John McCall9e8bb002011-05-14 03:10:52 +00004737 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004738}
4739
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004740// Metadata flags
4741enum MetaDataDlags {
4742 CLS = 0x0,
4743 CLS_META = 0x1,
4744 CLS_ROOT = 0x2,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004745 OBJC2_CLS_HIDDEN = 0x10,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004746 CLS_EXCEPTION = 0x20
4747};
4748/// BuildClassRoTInitializer - generate meta-data for:
4749/// struct _class_ro_t {
4750/// uint32_t const flags;
4751/// uint32_t const instanceStart;
4752/// uint32_t const instanceSize;
4753/// uint32_t const reserved; // only when building for 64bit targets
4754/// const uint8_t * const ivarLayout;
4755/// const char *const name;
4756/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004757/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004758/// const struct _ivar_list_t *const ivars;
4759/// const uint8_t * const weakIvarLayout;
4760/// const struct _prop_list_t * const properties;
4761/// }
4762///
4763llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004764 unsigned flags,
4765 unsigned InstanceStart,
4766 unsigned InstanceSize,
4767 const ObjCImplementationDecl *ID) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004768 std::string ClassName = ID->getNameAsString();
4769 std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004770 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4771 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
4772 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004773 // FIXME. For 64bit targets add 0 here.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004774 Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4775 : BuildIvarLayout(ID, true);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004776 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004777 // const struct _method_list_t * const baseMethods;
4778 std::vector<llvm::Constant*> Methods;
4779 std::string MethodListName("\01l_OBJC_$_");
4780 if (flags & CLS_META) {
4781 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004782 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004783 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004784 // Class methods should always be defined.
4785 Methods.push_back(GetMethodConstant(*i));
4786 }
4787 } else {
4788 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004789 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004790 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004791 // Instance methods should always be defined.
4792 Methods.push_back(GetMethodConstant(*i));
4793 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004794 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004795 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004796 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004797
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004798 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4799 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004800
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004801 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
4802 if (llvm::Constant *C = GetMethodConstant(MD))
4803 Methods.push_back(C);
4804 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
4805 if (llvm::Constant *C = GetMethodConstant(MD))
4806 Methods.push_back(C);
4807 }
4808 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004809 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004810 Values[ 5] = EmitMethodList(MethodListName,
4811 "__DATA, __objc_const", Methods);
4812
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004813 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4814 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004815 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00004816 + OID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00004817 OID->all_referenced_protocol_begin(),
4818 OID->all_referenced_protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004819
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00004820 if (flags & CLS_META)
Owen Anderson0b75f232009-07-31 20:28:54 +00004821 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00004822 else
4823 Values[ 7] = EmitIvarList(ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004824 Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4825 : BuildIvarLayout(ID, false);
Fariborz Jahanian066347e2009-01-28 22:18:42 +00004826 if (flags & CLS_META)
Owen Anderson0b75f232009-07-31 20:28:54 +00004827 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian066347e2009-01-28 22:18:42 +00004828 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00004829 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4830 ID, ID->getClassInterface(), ObjCTypes);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004831 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004832 Values);
4833 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004834 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
4835 llvm::GlobalValue::InternalLinkage,
4836 Init,
4837 (flags & CLS_META) ?
4838 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
4839 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00004840 CLASS_RO_GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00004841 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00004842 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004843 return CLASS_RO_GV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00004844
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004845}
4846
4847/// BuildClassMetaData - This routine defines that to-level meta-data
4848/// for the given ClassName for:
4849/// struct _class_t {
4850/// struct _class_t *isa;
4851/// struct _class_t * const superclass;
4852/// void *cache;
4853/// IMP *vtable;
4854/// struct class_ro_t *ro;
4855/// }
4856///
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004857llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004858 std::string &ClassName,
4859 llvm::Constant *IsAGV,
4860 llvm::Constant *SuperClassGV,
4861 llvm::Constant *ClassRoGV,
4862 bool HiddenVisibility) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004863 std::vector<llvm::Constant*> Values(5);
4864 Values[0] = IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004865 Values[1] = SuperClassGV;
4866 if (!Values[1])
4867 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004868 Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
4869 Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4870 Values[4] = ClassRoGV; // &CLASS_RO_GV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004871 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004872 Values);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00004873 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4874 GV->setInitializer(Init);
Fariborz Jahanian04087232009-01-31 01:07:39 +00004875 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00004876 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00004877 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian82208252009-01-31 00:59:10 +00004878 if (HiddenVisibility)
4879 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004880 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004881}
4882
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004883bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00004884CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004885 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004886}
4887
Daniel Dunbar961202372009-05-03 12:57:56 +00004888void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00004889 uint32_t &InstanceStart,
4890 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004891 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00004892 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004893
Daniel Dunbar9b042e02009-05-04 23:23:09 +00004894 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00004895 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00004896
4897 // If there are no fields, the start is the same as the end.
4898 if (!RL.getFieldCount())
4899 InstanceStart = InstanceSize;
4900 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00004901 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00004902}
4903
Fariborz Jahanian71394042009-01-23 23:53:38 +00004904void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
4905 std::string ClassName = ID->getNameAsString();
4906 if (!ObjCEmptyCacheVar) {
4907 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004908 CGM.getModule(),
4909 ObjCTypes.CacheTy,
4910 false,
4911 llvm::GlobalValue::ExternalLinkage,
4912 0,
4913 "_objc_empty_cache");
4914
Fariborz Jahanian71394042009-01-23 23:53:38 +00004915 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004916 CGM.getModule(),
4917 ObjCTypes.ImpnfABITy,
4918 false,
4919 llvm::GlobalValue::ExternalLinkage,
4920 0,
4921 "_objc_empty_vtable");
Fariborz Jahanian71394042009-01-23 23:53:38 +00004922 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004923 assert(ID->getClassInterface() &&
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004924 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00004925 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004926 uint32_t InstanceStart =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00004927 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004928 uint32_t InstanceSize = InstanceStart;
4929 uint32_t flags = CLS_META;
Daniel Dunbar15894b72009-04-07 05:48:37 +00004930 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4931 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004932
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004933 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004934
4935 bool classIsHidden =
John McCall457a04e2010-10-22 21:05:15 +00004936 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00004937 if (classIsHidden)
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004938 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00004939 if (ID->getNumIvarInitializers())
4940 flags |= eClassFlags_ABI2_HasCXXStructors;
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004941 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004942 // class is root
4943 flags |= CLS_ROOT;
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00004944 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004945 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004946 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004947 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00004948 const ObjCInterfaceDecl *Root = ID->getClassInterface();
4949 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4950 Root = Super;
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004951 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00004952 if (Root->isWeakImported())
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004953 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00004954 // work on super class metadata symbol.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004955 std::string SuperClassName =
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004956 ObjCMetaClassName +
4957 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004958 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00004959 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00004960 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004961 }
4962 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4963 InstanceStart,
4964 InstanceSize,ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004965 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004966 llvm::GlobalVariable *MetaTClass =
Fariborz Jahanian82208252009-01-31 00:59:10 +00004967 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4968 classIsHidden);
Fariborz Jahanian67260552009-11-17 21:37:35 +00004969 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00004970
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004971 // Metadata for the class
4972 flags = CLS;
Fariborz Jahanian82208252009-01-31 00:59:10 +00004973 if (classIsHidden)
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004974 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00004975 if (ID->getNumIvarInitializers())
4976 flags |= eClassFlags_ABI2_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00004977
Douglas Gregor78bd61f2009-06-18 16:11:24 +00004978 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
Daniel Dunbar8f28d012009-04-08 04:21:03 +00004979 flags |= CLS_EXCEPTION;
4980
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004981 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004982 flags |= CLS_ROOT;
4983 SuperClassGV = 0;
Chris Lattnerb433b272009-04-19 06:02:28 +00004984 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004985 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00004986 std::string RootClassName =
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004987 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00004988 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00004989 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00004990 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004991 }
Daniel Dunbar961202372009-05-03 12:57:56 +00004992 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004993 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00004994 InstanceStart,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004995 InstanceSize,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00004996 ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004997
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004998 TClassName = ObjCClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004999 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005000 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5001 classIsHidden);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005002 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005003
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005004 // Determine if this class is also "non-lazy".
5005 if (ImplementationIsNonLazy(ID))
5006 DefinedNonLazyClasses.push_back(ClassMD);
5007
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005008 // Force the definition of the EHType if necessary.
5009 if (flags & CLS_EXCEPTION)
5010 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005011 // Make sure method definition entries are all clear for next implementation.
5012 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005013}
5014
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005015/// GenerateProtocolRef - This routine is called to generate code for
5016/// a protocol reference expression; as in:
5017/// @code
5018/// @protocol(Proto1);
5019/// @endcode
5020/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5021/// which will hold address of the protocol meta-data.
5022///
5023llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005024 const ObjCProtocolDecl *PD) {
5025
Fariborz Jahanian464423d2009-04-10 18:47:34 +00005026 // This routine is called for @protocol only. So, we must build definition
5027 // of protocol's meta-data (not a reference to it!)
5028 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005029 llvm::Constant *Init =
5030 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
5031 ObjCTypes.ExternalProtocolPtrTy);
5032
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005033 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar56df9772010-08-17 22:39:59 +00005034 ProtocolName += PD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005035
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005036 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5037 if (PTGV)
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005038 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005039 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005040 CGM.getModule(),
5041 Init->getType(), false,
5042 llvm::GlobalValue::WeakAnyLinkage,
5043 Init,
5044 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005045 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5046 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005047 CGM.AddUsedGlobal(PTGV);
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005048 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005049}
5050
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005051/// GenerateCategory - Build metadata for a category implementation.
5052/// struct _category_t {
5053/// const char * const name;
5054/// struct _class_t *const cls;
5055/// const struct _method_list_t * const instance_methods;
5056/// const struct _method_list_t * const class_methods;
5057/// const struct _protocol_list_t * const protocols;
5058/// const struct _prop_list_t * const properties;
5059/// }
5060///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005061void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005062 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005063 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005064 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5065 "_$_" + OCD->getNameAsString());
5066 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar15894b72009-04-07 05:48:37 +00005067 Interface->getNameAsString());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005068
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005069 std::vector<llvm::Constant*> Values(6);
5070 Values[0] = GetClassName(OCD->getIdentifier());
5071 // meta-class entry symbol
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005072 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005073 if (Interface->isWeakImported())
Fariborz Jahanian3ad8dcf2009-11-17 22:02:21 +00005074 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5075
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005076 Values[1] = ClassGV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005077 std::vector<llvm::Constant*> Methods;
5078 std::string MethodListName(Prefix);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005079 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005080 "_$_" + OCD->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005081
5082 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005083 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005084 // Instance methods should always be defined.
5085 Methods.push_back(GetMethodConstant(*i));
5086 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005087
5088 Values[2] = EmitMethodList(MethodListName,
5089 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005090 Methods);
5091
5092 MethodListName = Prefix;
5093 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5094 OCD->getNameAsString();
5095 Methods.clear();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005096 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005097 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005098 // Class methods should always be defined.
5099 Methods.push_back(GetMethodConstant(*i));
5100 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005101
5102 Values[3] = EmitMethodList(MethodListName,
5103 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005104 Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005105 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00005106 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005107 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005108 llvm::SmallString<256> ExtName;
5109 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5110 << OCD->getName();
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005111 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005112 + Interface->getName() + "_$_"
5113 + Category->getName(),
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005114 Category->protocol_begin(),
5115 Category->protocol_end());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005116 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5117 OCD, Category, ObjCTypes);
Mike Stump658fe022009-07-30 22:28:39 +00005118 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00005119 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5120 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005121 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005122
5123 llvm::Constant *Init =
5124 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005125 Values);
5126 llvm::GlobalVariable *GCATV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005127 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005128 false,
5129 llvm::GlobalValue::InternalLinkage,
5130 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005131 ExtCatName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005132 GCATV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005133 CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005134 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005135 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005136 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005137
5138 // Determine if this category is also "non-lazy".
5139 if (ImplementationIsNonLazy(OCD))
5140 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005141 // method definition entries must be clear for next implementation.
5142 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005143}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005144
5145/// GetMethodConstant - Return a struct objc_method constant for the
5146/// given method if it has been defined. The result is null if the
5147/// method has not been defined. The return value has type MethodPtrTy.
5148llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005149 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005150 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005151 if (!Fn)
5152 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005153
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005154 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005155 Method[0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00005156 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005157 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005158 Method[1] = GetMethodVarType(MD);
Owen Andersonade90fd2009-07-29 18:54:39 +00005159 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005160 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005161}
5162
5163/// EmitMethodList - Build meta-data for method declarations
5164/// struct _method_list_t {
5165/// uint32_t entsize; // sizeof(struct _objc_method)
5166/// uint32_t method_count;
5167/// struct _objc_method method_list[method_count];
5168/// }
5169///
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005170llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
5171 const char *Section,
5172 const ConstantVector &Methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005173 // Return null for empty list.
5174 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005175 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005176
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005177 std::vector<llvm::Constant*> Values(3);
5178 // sizeof(struct _objc_method)
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005179 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005180 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005181 // method_count
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005182 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005183 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005184 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005185 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005186 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005187
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005188 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005189 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005190 llvm::GlobalValue::InternalLinkage,
5191 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005192 Name);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005193 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005194 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005195 GV->setSection(Section);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005196 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00005197 return llvm::ConstantExpr::getBitCast(GV,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005198 ObjCTypes.MethodListnfABIPtrTy);
5199}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005200
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005201/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5202/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005203llvm::GlobalVariable *
5204CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5205 const ObjCIvarDecl *Ivar) {
5206 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar3f86b9c2009-05-05 00:36:57 +00005207 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregorbcced4e2009-04-09 21:40:53 +00005208 '.' + Ivar->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005209 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005210 CGM.getModule().getGlobalVariable(Name);
5211 if (!IvarOffsetGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005212 IvarOffsetGV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005213 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005214 false,
5215 llvm::GlobalValue::ExternalLinkage,
5216 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005217 Name);
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005218 return IvarOffsetGV;
5219}
5220
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005221llvm::Constant *
5222CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5223 const ObjCIvarDecl *Ivar,
5224 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005225 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005226 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005227 Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005228 IvarOffsetGV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005229 CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005230
Mike Stump18bb9282009-05-16 07:57:57 +00005231 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
5232 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005233 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5234 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall457a04e2010-10-22 21:05:15 +00005235 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00005236 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00005237 else
Fariborz Jahanianbc3c77b2009-04-06 18:30:00 +00005238 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendlingf7d45982011-05-04 21:37:25 +00005239 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005240 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005241}
5242
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005243/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005244/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005245/// IvarListnfABIPtrTy.
5246/// struct _ivar_t {
5247/// unsigned long int *offset; // pointer to ivar offset location
5248/// char *name;
5249/// char *type;
5250/// uint32_t alignment;
5251/// uint32_t size;
5252/// }
5253/// struct _ivar_list_t {
5254/// uint32 entsize; // sizeof(struct _ivar_t)
5255/// uint32 count;
5256/// struct _iver_t list[count];
5257/// }
5258///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005259
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005260llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005261 const ObjCImplementationDecl *ID) {
5262
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005263 std::vector<llvm::Constant*> Ivars, Ivar(5);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005264
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005265 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5266 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005267
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005268 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005269
Daniel Dunbarae032262009-04-20 00:33:43 +00005270 // Collect declared and synthesized ivars in a small vector.
Fariborz Jahanian63a224a2009-03-31 18:11:23 +00005271 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian7c809592009-06-04 01:19:09 +00005272 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005273
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005274 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
5275 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian7c809592009-06-04 01:19:09 +00005276 // Ignore unnamed bit-fields.
5277 if (!IVD->getDeclName())
5278 continue;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005279 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar961202372009-05-03 12:57:56 +00005280 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005281 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5282 Ivar[2] = GetMethodVarType(IVD);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005283 const llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005284 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005285 unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005286 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005287 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005288 Align = llvm::Log2_32(Align);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005289 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00005290 // NOTE. Size of a bitfield does not match gcc's, because of the
5291 // way bitfields are treated special in each. But I am told that
5292 // 'size' for bitfield ivars is ignored by the runtime so it does
5293 // not matter. If it matters, there is enough info to get the
5294 // bitfield right!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005295 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005296 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005297 }
5298 // Return null for empty list.
5299 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005300 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005301 std::vector<llvm::Constant*> Values(3);
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005302 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005303 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5304 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005305 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005306 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005307 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005308 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005309 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5310 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005311 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005312 llvm::GlobalValue::InternalLinkage,
5313 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005314 Prefix + OID->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005315 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005316 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005317 GV->setSection("__DATA, __objc_const");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005318
Chris Lattnerf56501c2009-07-17 23:57:13 +00005319 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00005320 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005321}
5322
5323llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005324 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005325 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005326
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005327 if (!Entry) {
5328 // We use the initializer as a marker of whether this is a forward
5329 // reference or not. At module finalization we add the empty
5330 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005331 Entry =
5332 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5333 llvm::GlobalValue::ExternalLinkage,
5334 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005335 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005336 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005337 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005338
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005339 return Entry;
5340}
5341
5342/// GetOrEmitProtocol - Generate the protocol meta-data:
5343/// @code
5344/// struct _protocol_t {
5345/// id isa; // NULL
5346/// const char * const protocol_name;
5347/// const struct _protocol_list_t * protocol_list; // super protocols
5348/// const struct method_list_t * const instance_methods;
5349/// const struct method_list_t * const class_methods;
5350/// const struct method_list_t *optionalInstanceMethods;
5351/// const struct method_list_t *optionalClassMethods;
5352/// const struct _prop_list_t * properties;
5353/// const uint32_t size; // sizeof(struct _protocol_t)
5354/// const uint32_t flags; // = 0
5355/// }
5356/// @endcode
5357///
5358
5359llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005360 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005361 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005362
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005363 // Early exit if a defining object has already been generated.
5364 if (Entry && Entry->hasInitializer())
5365 return Entry;
5366
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005367 // Construct method lists.
5368 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5369 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005370 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005371 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005372 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005373 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00005374 if (!C)
5375 return GetOrEmitProtocolRef(PD);
5376
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005377 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5378 OptInstanceMethods.push_back(C);
5379 } else {
5380 InstanceMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005381 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005382 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005383
5384 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005385 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005386 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005387 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00005388 if (!C)
5389 return GetOrEmitProtocolRef(PD);
5390
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005391 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5392 OptClassMethods.push_back(C);
5393 } else {
5394 ClassMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005395 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005396 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005397
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005398 std::vector<llvm::Constant*> Values(10);
5399 // isa is NULL
Owen Anderson0b75f232009-07-31 20:28:54 +00005400 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005401 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005402 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5403 PD->protocol_begin(),
5404 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005405
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005406 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005407 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005408 "__DATA, __objc_const",
5409 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005410 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005411 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005412 "__DATA, __objc_const",
5413 ClassMethods);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005414 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005415 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005416 "__DATA, __objc_const",
5417 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005418 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005419 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005420 "__DATA, __objc_const",
5421 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005422 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005423 0, PD, ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005424 uint32_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005425 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005426 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0b75f232009-07-31 20:28:54 +00005427 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005428 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005429 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005430
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005431 if (Entry) {
5432 // Already created, fix the linkage and update the initializer.
Mike Stumpa6ca3342009-03-07 16:33:28 +00005433 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005434 Entry->setInitializer(Init);
5435 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005436 Entry =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005437 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
5438 false, llvm::GlobalValue::WeakAnyLinkage, Init,
5439 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005440 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005441 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005442 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005443 }
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005444 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005445 CGM.AddUsedGlobal(Entry);
5446
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005447 // Use this protocol meta-data to build protocol list table in section
5448 // __DATA, __objc_protolist
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005449 llvm::GlobalVariable *PTGV =
5450 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
5451 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
5452 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005453 PTGV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005454 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbarb25452a2009-04-15 02:56:18 +00005455 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005456 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005457 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005458 return Entry;
5459}
5460
5461/// EmitProtocolList - Generate protocol list meta-data:
5462/// @code
5463/// struct _protocol_list_t {
5464/// long protocol_count; // Note, this is 32/64 bit
5465/// struct _protocol_t[protocol_count];
5466/// }
5467/// @endcode
5468///
5469llvm::Constant *
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005470CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
5471 ObjCProtocolDecl::protocol_iterator begin,
5472 ObjCProtocolDecl::protocol_iterator end) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005473 std::vector<llvm::Constant*> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005474
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005475 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005476 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00005477 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005478
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005479 // FIXME: We shouldn't need to do this lookup here, should we?
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005480 llvm::SmallString<256> TmpName;
5481 Name.toVector(TmpName);
5482 llvm::GlobalVariable *GV =
5483 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005484 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005485 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005486
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005487 for (; begin != end; ++begin)
5488 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
5489
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005490 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00005491 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005492 ObjCTypes.ProtocolnfABIPtrTy));
5493
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005494 std::vector<llvm::Constant*> Values(2);
Owen Anderson170229f2009-07-14 23:10:40 +00005495 Values[0] =
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005496 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005497 Values[1] =
Owen Anderson47034e12009-07-28 18:33:04 +00005498 llvm::ConstantArray::get(
Owen Anderson9793f0e2009-07-29 22:16:19 +00005499 llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005500 ProtocolRefs.size()),
5501 ProtocolRefs);
5502
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005503 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Owen Andersonc10c8d32009-07-08 19:05:04 +00005504 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005505 llvm::GlobalValue::InternalLinkage,
5506 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005507 Name);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005508 GV->setSection("__DATA, __objc_const");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005509 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005510 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Chris Lattnerf56501c2009-07-17 23:57:13 +00005511 CGM.AddUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005512 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005513 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005514}
5515
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005516/// GetMethodDescriptionConstant - This routine build following meta-data:
5517/// struct _objc_method {
5518/// SEL _cmd;
5519/// char *method_type;
5520/// char *_imp;
5521/// }
5522
5523llvm::Constant *
5524CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
5525 std::vector<llvm::Constant*> Desc(3);
Owen Anderson170229f2009-07-14 23:10:40 +00005526 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005527 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5528 ObjCTypes.SelectorPtrTy);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005529 Desc[1] = GetMethodVarType(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00005530 if (!Desc[1])
5531 return 0;
5532
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005533 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00005534 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005535 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005536}
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005537
5538/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
5539/// This code gen. amounts to generating code for:
5540/// @code
5541/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
5542/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005543///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00005544LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00005545 CodeGen::CodeGenFunction &CGF,
5546 QualType ObjectTy,
5547 llvm::Value *BaseValue,
5548 const ObjCIvarDecl *Ivar,
5549 unsigned CVRQualifiers) {
5550 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00005551 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5552 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005553}
5554
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005555llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005556 CodeGen::CodeGenFunction &CGF,
5557 const ObjCInterfaceDecl *Interface,
5558 const ObjCIvarDecl *Ivar) {
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005559 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005560}
5561
John McCall234eac82011-05-13 23:16:18 +00005562static void appendSelectorForMessageRefTable(std::string &buffer,
5563 Selector selector) {
5564 if (selector.isUnarySelector()) {
5565 buffer += selector.getNameForSlot(0);
5566 return;
5567 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005568
John McCall234eac82011-05-13 23:16:18 +00005569 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
5570 buffer += selector.getNameForSlot(i);
5571 buffer += '_';
5572 }
5573}
5574
John McCall9e8bb002011-05-14 03:10:52 +00005575/// Emit a "v-table" message send. We emit a weak hidden-visibility
5576/// struct, initially containing the selector pointer and a pointer to
5577/// a "fixup" variant of the appropriate objc_msgSend. To call, we
5578/// load and call the function pointer, passing the address of the
5579/// struct as the second parameter. The runtime determines whether
5580/// the selector is currently emitted using vtable dispatch; if so, it
5581/// substitutes a stub function which simply tail-calls through the
5582/// appropriate vtable slot, and if not, it substitues a stub function
5583/// which tail-calls objc_msgSend. Both stubs adjust the selector
5584/// argument to correctly point to the selector.
5585RValue
5586CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
5587 ReturnValueSlot returnSlot,
5588 QualType resultType,
5589 Selector selector,
5590 llvm::Value *arg0,
5591 QualType arg0Type,
5592 bool isSuper,
5593 const CallArgList &formalArgs,
5594 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00005595 // Compute the actual arguments.
5596 CallArgList args;
5597
John McCall9e8bb002011-05-14 03:10:52 +00005598 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00005599 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00005600 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
5601 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00005602
John McCall9e8bb002011-05-14 03:10:52 +00005603 // Second argument: a pointer to the message ref structure. Leave
5604 // the actual argument value blank for now.
John McCall234eac82011-05-13 23:16:18 +00005605 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
5606
5607 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
5608
5609 const CGFunctionInfo &fnInfo =
5610 CGM.getTypes().getFunctionInfo(resultType, args,
5611 FunctionType::ExtInfo());
5612
John McCall5880fb82011-05-14 21:12:11 +00005613 NullReturnState nullReturn;
5614
John McCall9e8bb002011-05-14 03:10:52 +00005615 // Find the function to call and the mangled name for the message
5616 // ref structure. Using a different mangled name wouldn't actually
5617 // be a problem; it would just be a waste.
5618 //
5619 // The runtime currently never uses vtable dispatch for anything
5620 // except normal, non-super message-sends.
5621 // FIXME: don't use this for that.
John McCall234eac82011-05-13 23:16:18 +00005622 llvm::Constant *fn = 0;
5623 std::string messageRefName("\01l_");
5624 if (CGM.ReturnTypeUsesSRet(fnInfo)) {
John McCall234eac82011-05-13 23:16:18 +00005625 if (isSuper) {
5626 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
5627 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005628 } else {
John McCall5880fb82011-05-14 21:12:11 +00005629 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00005630 fn = ObjCTypes.getMessageSendStretFixupFn();
5631 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005632 }
John McCall234eac82011-05-13 23:16:18 +00005633 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
5634 fn = ObjCTypes.getMessageSendFpretFixupFn();
5635 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00005636 } else {
John McCall234eac82011-05-13 23:16:18 +00005637 if (isSuper) {
5638 fn = ObjCTypes.getMessageSendSuper2FixupFn();
5639 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005640 } else {
John McCall234eac82011-05-13 23:16:18 +00005641 fn = ObjCTypes.getMessageSendFixupFn();
5642 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005643 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005644 }
John McCall234eac82011-05-13 23:16:18 +00005645 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
5646 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005647
John McCall234eac82011-05-13 23:16:18 +00005648 // Append the selector name, except use underscores anywhere we
5649 // would have used colons.
5650 appendSelectorForMessageRefTable(messageRefName, selector);
5651
5652 llvm::GlobalVariable *messageRef
5653 = CGM.getModule().getGlobalVariable(messageRefName);
5654 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00005655 // Build the message ref structure.
John McCall234eac82011-05-13 23:16:18 +00005656 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
5657 llvm::Constant *init =
5658 llvm::ConstantStruct::get(VMContext, values, 2, false);
5659 messageRef = new llvm::GlobalVariable(CGM.getModule(),
5660 init->getType(),
5661 /*constant*/ false,
5662 llvm::GlobalValue::WeakAnyLinkage,
5663 init,
5664 messageRefName);
5665 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
5666 messageRef->setAlignment(16);
5667 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
5668 }
5669 llvm::Value *mref =
5670 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
5671
John McCall9e8bb002011-05-14 03:10:52 +00005672 // Update the message ref argument.
John McCall234eac82011-05-13 23:16:18 +00005673 args[1].RV = RValue::get(mref);
5674
5675 // Load the function to call from the message ref table.
5676 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
5677 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
5678
5679 bool variadic = method ? method->isVariadic() : false;
5680 const llvm::FunctionType *fnType =
5681 CGF.getTypes().GetFunctionType(fnInfo, variadic);
5682 callee = CGF.Builder.CreateBitCast(callee,
5683 llvm::PointerType::getUnqual(fnType));
5684
John McCall5880fb82011-05-14 21:12:11 +00005685 RValue result = CGF.EmitCall(fnInfo, callee, returnSlot, args);
5686 return nullReturn.complete(CGF, result, resultType);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00005687}
5688
5689/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005690CodeGen::RValue
5691CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00005692 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005693 QualType ResultType,
5694 Selector Sel,
5695 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005696 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00005697 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005698 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00005699 return isVTableDispatchedSelector(Sel)
5700 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005701 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00005702 false, CallArgs, Method)
5703 : EmitMessageSend(CGF, Return, ResultType,
5704 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005705 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00005706 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00005707}
5708
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005709llvm::GlobalVariable *
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005710CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005711 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5712
Daniel Dunbara6468342009-03-02 05:18:14 +00005713 if (!GV) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005714 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005715 false, llvm::GlobalValue::ExternalLinkage,
5716 0, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005717 }
5718
5719 return GV;
5720}
5721
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005722llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5723 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005724 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005725
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005726 if (!Entry) {
Daniel Dunbar15894b72009-04-07 05:48:37 +00005727 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005728 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005729 Entry =
5730 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005731 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005732 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005733 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005734 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005735 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005736 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005737 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005738 CGM.AddUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005739 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005740
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005741 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005742}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005743
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005744llvm::Value *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005745CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005746 const ObjCInterfaceDecl *ID) {
5747 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005748
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005749 if (!Entry) {
5750 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5751 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005752 Entry =
5753 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005754 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005755 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005756 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005757 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005758 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005759 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005760 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005761 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005762 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005763
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005764 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005765}
5766
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005767/// EmitMetaClassRef - Return a Value * of the address of _class_t
5768/// meta-data
5769///
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005770llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5771 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005772 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5773 if (Entry)
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005774 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005775
Daniel Dunbar15894b72009-04-07 05:48:37 +00005776 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005777 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005778 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005779 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005780 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005781 MetaClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005782 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005783 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005784 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005785 ObjCTypes.ClassnfABIPtrTy));
5786
Daniel Dunbare60aa052009-04-15 19:03:14 +00005787 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005788 CGM.AddUsedGlobal(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005789
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005790 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005791}
5792
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005793/// GetClass - Return a reference to the class for the given interface
5794/// decl.
5795llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
5796 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005797 if (ID->isWeakImported()) {
Fariborz Jahanian95ace552009-11-17 22:42:00 +00005798 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5799 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5800 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5801 }
5802
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005803 return EmitClassRef(Builder, ID);
5804}
5805
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005806/// Generates a message send where the super is the receiver. This is
5807/// a message send to self with special delivery semantics indicating
5808/// which class's method should be called.
5809CodeGen::RValue
5810CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00005811 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005812 QualType ResultType,
5813 Selector Sel,
5814 const ObjCInterfaceDecl *Class,
5815 bool isCategoryImpl,
5816 llvm::Value *Receiver,
5817 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005818 const CodeGen::CallArgList &CallArgs,
5819 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005820 // ...
5821 // Create and init a super structure; this is a (receiver, class)
5822 // pair we will pass to objc_msgSendSuper.
5823 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00005824 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005825
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005826 llvm::Value *ReceiverAsObject =
5827 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
5828 CGF.Builder.CreateStore(ReceiverAsObject,
5829 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005830
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005831 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005832 llvm::Value *Target;
5833 if (IsClassMessage) {
5834 if (isCategoryImpl) {
5835 // Message sent to "super' in a class method defined in
5836 // a category implementation.
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005837 Target = EmitClassRef(CGF.Builder, Class);
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005838 Target = CGF.Builder.CreateStructGEP(Target, 0);
5839 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00005840 } else
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005841 Target = EmitMetaClassRef(CGF.Builder, Class);
Mike Stump658fe022009-07-30 22:28:39 +00005842 } else
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005843 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005844
Mike Stump18bb9282009-05-16 07:57:57 +00005845 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5846 // ObjCTypes types.
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005847 const llvm::Type *ClassTy =
5848 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
5849 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
5850 CGF.Builder.CreateStore(Target,
5851 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005852
John McCall9e8bb002011-05-14 03:10:52 +00005853 return (isVTableDispatchedSelector(Sel))
5854 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005855 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00005856 true, CallArgs, Method)
5857 : EmitMessageSend(CGF, Return, ResultType,
5858 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005859 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00005860 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005861}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005862
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005863llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00005864 Selector Sel, bool lval) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005865 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005866
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005867 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005868 llvm::Constant *Casted =
5869 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
5870 ObjCTypes.SelectorPtrTy);
5871 Entry =
5872 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
5873 llvm::GlobalValue::InternalLinkage,
5874 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005875 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005876 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005877 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005878
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00005879 if (lval)
5880 return Entry;
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005881 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005882}
Fariborz Jahanian06292952009-02-16 22:52:32 +00005883/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005884/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00005885///
5886void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005887 llvm::Value *src,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005888 llvm::Value *dst,
5889 llvm::Value *ivarOffset) {
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)
5895 : 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);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005900 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5901 src, dst, ivarOffset);
Fariborz Jahanian06292952009-02-16 22:52:32 +00005902 return;
5903}
5904
5905/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5906/// objc_assign_strongCast (id src, id *dst)
5907///
5908void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005909 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005910 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005911 const llvm::Type * SrcTy = src->getType();
5912 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005913 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005914 assert(Size <= 8 && "does not support size > 8");
5915 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005916 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005917 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5918 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005919 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5920 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00005921 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00005922 src, dst, "weakassign");
5923 return;
5924}
5925
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005926void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005927 CodeGen::CodeGenFunction &CGF,
5928 llvm::Value *DestPtr,
5929 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00005930 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005931 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5932 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005933 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00005934 DestPtr, SrcPtr, Size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005935 return;
5936}
5937
Fariborz Jahanian06292952009-02-16 22:52:32 +00005938/// EmitObjCWeakRead - Code gen for loading value of a __weak
5939/// object: objc_read_weak (id *src)
5940///
5941llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005942 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005943 llvm::Value *AddrWeakObj) {
Eli Friedmana374b682009-03-07 03:57:15 +00005944 const llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005945 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5946 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00005947 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00005948 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00005949 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00005950 return read_weak;
5951}
5952
5953/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
5954/// objc_assign_weak (id src, id *dst)
5955///
5956void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005957 llvm::Value *src, llvm::Value *dst) {
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);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00005968 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00005969 src, dst, "weakassign");
5970 return;
5971}
5972
5973/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
5974/// objc_assign_global (id src, id *dst)
5975///
5976void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00005977 llvm::Value *src, llvm::Value *dst,
5978 bool threadlocal) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005979 const llvm::Type * SrcTy = src->getType();
5980 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005981 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005982 assert(Size <= 8 && "does not support size > 8");
5983 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5984 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005985 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5986 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005987 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5988 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00005989 if (!threadlocal)
5990 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
5991 src, dst, "globalassign");
5992 else
5993 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
5994 src, dst, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00005995 return;
5996}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005997
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005998void
John McCallbd309292010-07-06 01:34:17 +00005999CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6000 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006001 EmitAtSynchronizedStmt(CGF, S,
6002 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6003 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00006004}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006005
John McCall2ca705e2010-07-24 00:37:23 +00006006llvm::Constant *
6007CGObjCNonFragileABIMac::GetEHType(QualType T) {
6008 // There's a particular fixed type info for 'id'.
6009 if (T->isObjCIdType() ||
6010 T->isObjCQualifiedIdType()) {
6011 llvm::Constant *IDEHType =
6012 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6013 if (!IDEHType)
6014 IDEHType =
6015 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6016 false,
6017 llvm::GlobalValue::ExternalLinkage,
6018 0, "OBJC_EHTYPE_id");
6019 return IDEHType;
6020 }
6021
6022 // All other types should be Objective-C interface pointer types.
6023 const ObjCObjectPointerType *PT =
6024 T->getAs<ObjCObjectPointerType>();
6025 assert(PT && "Invalid @catch type.");
6026 const ObjCInterfaceType *IT = PT->getInterfaceType();
6027 assert(IT && "Invalid @catch type.");
6028 return GetInterfaceEHType(IT->getDecl(), false);
6029}
6030
John McCallbd309292010-07-06 01:34:17 +00006031void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6032 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006033 EmitTryCatchStmt(CGF, S,
6034 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6035 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6036 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006037}
6038
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006039/// EmitThrowStmt - Generate code for a throw statement.
6040void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6041 const ObjCAtThrowStmt &S) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006042 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall17afe452010-10-16 08:21:07 +00006043 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
John McCalld5091822010-10-16 16:34:08 +00006044 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy,
6045 "tmp");
John McCall17afe452010-10-16 08:21:07 +00006046 llvm::Value *Args[] = { Exception };
6047 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(),
6048 Args, Args+1)
6049 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006050 } else {
John McCall17afe452010-10-16 08:21:07 +00006051 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn(), 0, 0)
6052 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006053 }
6054
John McCall17afe452010-10-16 08:21:07 +00006055 CGF.Builder.CreateUnreachable();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006056 CGF.Builder.ClearInsertionPoint();
6057}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006058
John McCall2ca705e2010-07-24 00:37:23 +00006059llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006060CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006061 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006062 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006063
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006064 // If we don't need a definition, return the entry if found or check
6065 // if we use an external reference.
6066 if (!ForDefinition) {
6067 if (Entry)
6068 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00006069
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006070 // If this type (or a super class) has the __objc_exception__
6071 // attribute, emit an external reference.
Douglas Gregor78bd61f2009-06-18 16:11:24 +00006072 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006073 return Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006074 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006075 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006076 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006077 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006078 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006079 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006080
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006081 // Otherwise we need to either make a new entry or fill in the
6082 // initializer.
6083 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar15894b72009-04-07 05:48:37 +00006084 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006085 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006086 llvm::GlobalVariable *VTableGV =
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006087 CGM.getModule().getGlobalVariable(VTableName);
6088 if (!VTableGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006089 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6090 false,
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006091 llvm::GlobalValue::ExternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006092 0, VTableName);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006093
Chris Lattner5e016ae2010-06-27 07:15:29 +00006094 llvm::Value *VTableIdx =
6095 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006096
6097 std::vector<llvm::Constant*> Values(3);
Owen Andersonade90fd2009-07-29 18:54:39 +00006098 Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006099 Values[1] = GetClassName(ID->getIdentifier());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006100 Values[2] = GetClassGlobal(ClassName);
Owen Anderson170229f2009-07-14 23:10:40 +00006101 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00006102 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006103
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006104 if (Entry) {
6105 Entry->setInitializer(Init);
6106 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00006107 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006108 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006109 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006110 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006111 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006112 }
6113
John McCall457a04e2010-10-22 21:05:15 +00006114 if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar15894b72009-04-07 05:48:37 +00006115 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar710cb202010-04-25 20:39:32 +00006116 Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
6117 ObjCTypes.EHTypeTy));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006118
6119 if (ForDefinition) {
6120 Entry->setSection("__DATA,__objc_const");
6121 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6122 } else {
6123 Entry->setSection("__DATA,__datacoal_nt,coalesced");
6124 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006125
6126 return Entry;
6127}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006128
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00006129/* *** */
6130
Daniel Dunbarb036db82008-08-13 03:21:16 +00006131CodeGen::CGObjCRuntime *
6132CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
David Chisnall067f0ed2011-03-22 21:21:24 +00006133 if (CGM.getLangOptions().ObjCNonFragileABI)
6134 return new CGObjCNonFragileABIMac(CGM);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00006135 return new CGObjCMac(CGM);
6136}