blob: 8c3e9a36e307bd16ae55fe95408e10e7fa2caf11 [file] [log] [blame]
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattnerfc8f0e12011-04-15 05:22:18 +000010// This provides Objective-C code generation targeting the Apple runtime.
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000015
Daniel Dunbar198bcb42010-03-31 01:09:11 +000016#include "CGRecordLayout.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000017#include "CodeGenModule.h"
Daniel Dunbarb7ec2462008-08-16 03:19:19 +000018#include "CodeGenFunction.h"
John McCalld16c2cf2011-02-08 08:22:06 +000019#include "CGBlocks.h"
John McCall36f893c2011-01-28 11:13:47 +000020#include "CGCleanup.h"
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000021#include "clang/AST/ASTContext.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000022#include "clang/AST/Decl.h"
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000023#include "clang/AST/DeclObjC.h"
Anders Carlsson19cc4ab2009-07-18 19:43:29 +000024#include "clang/AST/RecordLayout.h"
Chris Lattner16f00492009-04-26 01:32:48 +000025#include "clang/AST/StmtObjC.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000026#include "clang/Basic/LangOptions.h"
Chandler Carruth06057ce2010-06-15 23:19:56 +000027#include "clang/Frontend/CodeGenOptions.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000028
John McCall87bb5822010-07-31 23:20:56 +000029#include "llvm/InlineAsm.h"
30#include "llvm/IntrinsicInst.h"
Owen Anderson69243822009-07-13 04:10:07 +000031#include "llvm/LLVMContext.h"
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000032#include "llvm/Module.h"
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +000033#include "llvm/ADT/DenseSet.h"
Daniel Dunbar33063492009-09-07 00:20:42 +000034#include "llvm/ADT/SetVector.h"
35#include "llvm/ADT/SmallString.h"
Fariborz Jahanian191dcd72009-12-12 21:26:21 +000036#include "llvm/ADT/SmallPtrSet.h"
John McCall8e3f8612010-07-13 22:12:14 +000037#include "llvm/Support/CallSite.h"
Daniel Dunbar33063492009-09-07 00:20:42 +000038#include "llvm/Support/raw_ostream.h"
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +000039#include "llvm/Target/TargetData.h"
Torok Edwinf42e4a62009-08-24 13:25:12 +000040#include <cstdio>
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000041
42using namespace clang;
Daniel Dunbar46f45b92008-09-09 01:06:48 +000043using namespace CodeGen;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000044
Daniel Dunbar97776872009-04-22 07:32:20 +000045
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000046namespace {
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000047
Daniel Dunbar6bff2512009-08-03 17:06:42 +000048typedef std::vector<llvm::Constant*> ConstantVector;
Daniel Dunbarae226fa2008-08-27 02:31:56 +000049
Daniel Dunbar6bff2512009-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 Dunbar6efc0c52008-08-13 03:21:16 +000052
Fariborz Jahanianee0af742009-01-21 22:04:16 +000053class ObjCCommonTypesHelper {
Owen Andersona1cf15f2009-07-14 23:10:40 +000054protected:
55 llvm::LLVMContext &VMContext;
Daniel Dunbar6bff2512009-08-03 17:06:42 +000056
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000057private:
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +000065 llvm::Constant *getMessageSendFn() const {
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +000070 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000071
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +000077 llvm::Constant *getMessageSendStretFn() const {
John McCall0774cb82011-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 Dunbar6bff2512009-08-03 17:06:42 +000082
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000083 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000084
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +000090 llvm::Constant *getMessageSendFpretFn() const {
John McCall0774cb82011-05-15 01:53:33 +000091 const llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
92 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(
Owen Anderson0032b272009-08-13 21:57:51 +000093 llvm::Type::getDoubleTy(VMContext),
John McCall0774cb82011-05-15 01:53:33 +000094 params, true),
95 "objc_msgSend_fpret");
Daniel Dunbar6bff2512009-08-03 17:06:42 +000096
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000097 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000098
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +0000104 llvm::Constant *getMessageSendSuperFn() const {
John McCall0774cb82011-05-15 01:53:33 +0000105 const llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000106 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000107 params, true),
108 "objc_msgSendSuper");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000109 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000110
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +0000115 llvm::Constant *getMessageSendSuperFn2() const {
John McCall0774cb82011-05-15 01:53:33 +0000116 const llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000117 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000118 params, true),
119 "objc_msgSendSuper2");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000120 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000121
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +0000126 llvm::Constant *getMessageSendSuperStretFn() const {
John McCall0774cb82011-05-15 01:53:33 +0000127 const llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000128 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000129 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000130 "objc_msgSendSuper_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000131 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000132
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +0000137 llvm::Constant *getMessageSendSuperStretFn2() const {
John McCall0774cb82011-05-15 01:53:33 +0000138 const llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000139 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000140 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000141 "objc_msgSendSuper2_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000142 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000143
Fariborz Jahaniand0f8a8d2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000148
Fariborz Jahaniand0f8a8d2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000153
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000154protected:
155 CodeGen::CodeGenModule &CGM;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000156
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000157public:
Fariborz Jahanian0a855d02009-03-23 19:10:40 +0000158 const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000159 const llvm::Type *Int8PtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000160
Daniel Dunbar2bedbf82008-08-12 05:28:47 +0000161 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
162 const llvm::Type *ObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000163
Fariborz Jahanian6d657c42008-11-18 20:18:11 +0000164 /// PtrObjectPtrTy - LLVM type for id *
165 const llvm::Type *PtrObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000166
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000167 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Daniel Dunbar2bedbf82008-08-12 05:28:47 +0000168 const llvm::Type *SelectorPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000169 /// ProtocolPtrTy - LLVM type for external protocol handles
170 /// (typeof(Protocol))
171 const llvm::Type *ExternalProtocolPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000172
Daniel Dunbar19cd87e2008-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 Dunbar6bff2512009-08-03 17:06:42 +0000177
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000178 /// SuperTy - LLVM type for struct objc_super.
179 const llvm::StructType *SuperTy;
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000180 /// SuperPtrTy - LLVM type for struct objc_super *.
181 const llvm::Type *SuperPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000182
Fariborz Jahanian30bc5712009-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 Dunbar6bff2512009-08-03 17:06:42 +0000186
Fariborz Jahanian30bc5712009-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 Dunbar6bff2512009-08-03 17:06:42 +0000192
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000193 // MethodTy - LLVM type for struct objc_method.
194 const llvm::StructType *MethodTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000195
Fariborz Jahaniand55b6fc2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000200
Chris Lattner72db6c32009-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 McCallead608a2010-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 Lattner72db6c32009-04-22 02:44:54 +0000208 Params.push_back(IdType);
209 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000210 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-04-22 02:44:54 +0000211 Params.push_back(Ctx.BoolTy);
212 const llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000213 Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000214 FunctionType::ExtInfo()),
215 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000216 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
217 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000218
Chris Lattner72db6c32009-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 McCallead608a2010-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 Lattner72db6c32009-04-22 02:44:54 +0000226 Params.push_back(IdType);
227 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000228 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-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 McCall04a67a62010-02-05 21:31:56 +0000233 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000234 FunctionType::ExtInfo()),
235 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000236 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
237 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000238
Fariborz Jahanian6cc59062010-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 Lattner72db6c32009-04-22 02:44:54 +0000257 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbarc1ab9002009-07-11 20:32:50 +0000258 CodeGen::CodeGenTypes &Types = CGM.getTypes();
259 ASTContext &Ctx = CGM.getContext();
Chris Lattner72db6c32009-04-22 02:44:54 +0000260 // void objc_enumerationMutation (id)
John McCallead608a2010-02-26 00:48:12 +0000261 llvm::SmallVector<CanQualType,1> Params;
262 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Daniel Dunbarc1ab9002009-07-11 20:32:50 +0000263 const llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000264 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000265 FunctionType::ExtInfo()),
266 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000267 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
268 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000269
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000270 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattner72db6c32009-04-22 02:44:54 +0000271 llvm::Constant *getGcReadWeakFn() {
272 // id objc_read_weak (id *)
John McCall0774cb82011-05-15 01:53:33 +0000273 const llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000274 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000275 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000276 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000277 }
278
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000279 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner96508e12009-04-17 22:12:36 +0000280 llvm::Constant *getGcAssignWeakFn() {
281 // id objc_assign_weak (id, id *)
John McCall0774cb82011-05-15 01:53:33 +0000282 const llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner96508e12009-04-17 22:12:36 +0000283 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000284 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner96508e12009-04-17 22:12:36 +0000285 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
286 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000287
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000288 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000289 llvm::Constant *getGcAssignGlobalFn() {
290 // id objc_assign_global(id, id *)
John McCall0774cb82011-05-15 01:53:33 +0000291 const llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000292 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000293 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000294 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
295 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000296
Fariborz Jahanian021a7a62010-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 McCall0774cb82011-05-15 01:53:33 +0000300 const llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000301 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000302 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000303 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
304 }
305
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000306 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000307 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +0000308 // id objc_assign_ivar(id, id *, ptrdiff_t)
John McCall0774cb82011-05-15 01:53:33 +0000309 const llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
310 CGM.PtrDiffTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000311 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000312 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000313 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
314 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000315
Fariborz Jahanian082b02e2009-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 McCall0774cb82011-05-15 01:53:33 +0000319 const llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
320 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000321 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
322 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000323
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000324 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000325 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000326 // id objc_assign_strongCast(id, id *)
John McCall0774cb82011-05-15 01:53:33 +0000327 const llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000328 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000329 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000330 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
331 }
Anders Carlssonf57c5b22009-02-16 22:59:18 +0000332
333 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000334 llvm::Constant *getExceptionThrowFn() {
335 // void objc_exception_throw(id)
John McCall0774cb82011-05-15 01:53:33 +0000336 const llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerbbccd612009-04-22 02:38:11 +0000337 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000338 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000339 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
340 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000341
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000342 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
343 llvm::Constant *getExceptionRethrowFn() {
344 // void objc_exception_rethrow(void)
John McCall0774cb82011-05-15 01:53:33 +0000345 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000346 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
347 }
348
Daniel Dunbar1c566672009-02-24 01:43:46 +0000349 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000350 llvm::Constant *getSyncEnterFn() {
351 // void objc_sync_enter (id)
John McCall0774cb82011-05-15 01:53:33 +0000352 const llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000353 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000354 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000355 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
356 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000357
Daniel Dunbar1c566672009-02-24 01:43:46 +0000358 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000359 llvm::Constant *getSyncExitFn() {
360 // void objc_sync_exit (id)
John McCall0774cb82011-05-15 01:53:33 +0000361 const llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerbbccd612009-04-22 02:38:11 +0000362 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000363 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000364 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
365 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000366
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000367 llvm::Constant *getSendFn(bool IsSuper) const {
368 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
369 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000370
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000371 llvm::Constant *getSendFn2(bool IsSuper) const {
372 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
373 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000374
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000375 llvm::Constant *getSendStretFn(bool IsSuper) const {
376 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
377 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000378
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000379 llvm::Constant *getSendStretFn2(bool IsSuper) const {
380 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
381 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000382
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000383 llvm::Constant *getSendFpretFn(bool IsSuper) const {
384 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
385 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000386
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000387 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
388 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
389 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000390
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000391 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
392 ~ObjCCommonTypesHelper(){}
393};
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000394
Fariborz Jahanianee0af742009-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 Jahanianee0af742009-01-21 22:04:16 +0000398public:
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000399 /// SymtabTy - LLVM type for struct objc_symtab.
400 const llvm::StructType *SymtabTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000401 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
402 const llvm::Type *SymtabPtrTy;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000403 /// ModuleTy - LLVM type for struct objc_module.
404 const llvm::StructType *ModuleTy;
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000405
Daniel Dunbar6efc0c52008-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 Dunbar6efc0c52008-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 Dunbar86e253a2008-08-22 20:34:54 +0000429 /// CategoryTy - LLVM type for struct objc_category.
430 const llvm::StructType *CategoryTy;
Daniel Dunbar27f9d772008-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 Dunbar27f9d772008-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 Dunbar27f9d772008-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 Dunbar6bff2512009-08-03 17:06:42 +0000449
Anders Carlsson124526b2008-09-09 10:10:21 +0000450 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
451 const llvm::Type *ExceptionDataTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000452
Anders Carlsson124526b2008-09-09 10:10:21 +0000453 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000454 llvm::Constant *getExceptionTryEnterFn() {
John McCall0774cb82011-05-15 01:53:33 +0000455 const llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000456 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000457 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000458 "objc_exception_try_enter");
Chris Lattner34b02a12009-04-22 02:26:14 +0000459 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000460
461 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000462 llvm::Constant *getExceptionTryExitFn() {
John McCall0774cb82011-05-15 01:53:33 +0000463 const llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000464 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000465 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000466 "objc_exception_try_exit");
Chris Lattner34b02a12009-04-22 02:26:14 +0000467 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000468
469 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000470 llvm::Constant *getExceptionExtractFn() {
John McCall0774cb82011-05-15 01:53:33 +0000471 const llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000472 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000473 params, false),
Chris Lattner34b02a12009-04-22 02:26:14 +0000474 "objc_exception_extract");
Chris Lattner34b02a12009-04-22 02:26:14 +0000475 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000476
Anders Carlsson124526b2008-09-09 10:10:21 +0000477 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000478 llvm::Constant *getExceptionMatchFn() {
John McCall0774cb82011-05-15 01:53:33 +0000479 const llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000480 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000481 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000482 "objc_exception_match");
483
Chris Lattner34b02a12009-04-22 02:26:14 +0000484 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000485
Anders Carlsson124526b2008-09-09 10:10:21 +0000486 /// SetJmpFn - LLVM _setjmp function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000487 llvm::Constant *getSetJmpFn() {
John McCall0774cb82011-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 Lattner34b02a12009-04-22 02:26:14 +0000493 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000494
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000495public:
496 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000497 ~ObjCTypesHelper() {}
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000498};
499
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000500/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000501/// modern abi
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000502class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000503public:
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000504
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000505 // MethodListnfABITy - LLVM for struct _method_list_t
506 const llvm::StructType *MethodListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000507
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000508 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
509 const llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000510
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000511 // ProtocolnfABITy = LLVM for struct _protocol_t
512 const llvm::StructType *ProtocolnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000513
Daniel Dunbar948e2582009-02-15 07:36:20 +0000514 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
515 const llvm::Type *ProtocolnfABIPtrTy;
516
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000517 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
518 const llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000519
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000520 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
521 const llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000522
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000523 // ClassnfABITy - LLVM for struct _class_t
524 const llvm::StructType *ClassnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000525
Fariborz Jahanianaa23b572009-01-23 23:53:38 +0000526 // ClassnfABIPtrTy - LLVM for struct _class_t*
527 const llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000528
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000529 // IvarnfABITy - LLVM for struct _ivar_t
530 const llvm::StructType *IvarnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000531
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000532 // IvarListnfABITy - LLVM for struct _ivar_list_t
533 const llvm::StructType *IvarListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000534
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000535 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
536 const llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000537
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000538 // ClassRonfABITy - LLVM for struct _class_ro_t
539 const llvm::StructType *ClassRonfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000540
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000541 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
542 const llvm::Type *ImpnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000543
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000544 // CategorynfABITy - LLVM for struct _category_t
545 const llvm::StructType *CategorynfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000546
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000547 // New types for nonfragile abi messaging.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000548
Fariborz Jahanian2e4672b2009-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 Jahanian83a8a752009-02-04 20:42:28 +0000555 // MessageRefCTy - clang type for struct _message_ref_t
556 QualType MessageRefCTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000557
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000558 // MessageRefPtrTy - LLVM for struct _message_ref_t*
559 const llvm::Type *MessageRefPtrTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000560 // MessageRefCPtrTy - clang type for struct _message_ref_t*
561 QualType MessageRefCPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000562
Fariborz Jahanianef163782009-02-05 01:13:09 +0000563 // MessengerTy - Type of the messenger (shown as IMP above)
564 const llvm::FunctionType *MessengerTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000565
Fariborz Jahanian2e4672b2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000572
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000573 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
574 const llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000575
Chris Lattner1c02f862009-04-22 02:53:24 +0000576 llvm::Constant *getMessageSendFixupFn() {
577 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
John McCall0774cb82011-05-15 01:53:33 +0000578 const llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000579 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000580 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000581 "objc_msgSend_fixup");
582 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000583
Chris Lattner1c02f862009-04-22 02:53:24 +0000584 llvm::Constant *getMessageSendFpretFixupFn() {
585 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
John McCall0774cb82011-05-15 01:53:33 +0000586 const llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000587 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000588 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000589 "objc_msgSend_fpret_fixup");
590 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000591
Chris Lattner1c02f862009-04-22 02:53:24 +0000592 llvm::Constant *getMessageSendStretFixupFn() {
593 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
John McCall0774cb82011-05-15 01:53:33 +0000594 const llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000595 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000596 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000597 "objc_msgSend_stret_fixup");
598 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000599
Chris Lattner1c02f862009-04-22 02:53:24 +0000600 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000601 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000602 // struct _super_message_ref_t*, ...)
John McCall0774cb82011-05-15 01:53:33 +0000603 const llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000604 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000605 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000606 "objc_msgSendSuper2_fixup");
607 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000608
Chris Lattner1c02f862009-04-22 02:53:24 +0000609 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000610 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000611 // struct _super_message_ref_t*, ...)
John McCall0774cb82011-05-15 01:53:33 +0000612 const llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000613 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000614 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000615 "objc_msgSendSuper2_stret_fixup");
616 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000617
Chris Lattner8a569112009-04-22 02:15:23 +0000618 llvm::Constant *getObjCEndCatchFn() {
John McCall0774cb82011-05-15 01:53:33 +0000619 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattner8a569112009-04-22 02:15:23 +0000620 "objc_end_catch");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000621
Chris Lattner8a569112009-04-22 02:15:23 +0000622 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000623
Chris Lattner8a569112009-04-22 02:15:23 +0000624 llvm::Constant *getObjCBeginCatchFn() {
John McCall0774cb82011-05-15 01:53:33 +0000625 const llvm::Type *params[] = { Int8PtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000626 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000627 params, false),
Chris Lattner8a569112009-04-22 02:15:23 +0000628 "objc_begin_catch");
629 }
Daniel Dunbare588b992009-03-01 04:46:24 +0000630
631 const llvm::StructType *EHTypeTy;
632 const llvm::Type *EHTypePtrTy;
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000633
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000634 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
635 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000636};
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000637
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000638class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000639public:
640 // FIXME - accessibility
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000641 class GC_IVAR {
Fariborz Jahanian820e0202009-03-11 00:07:04 +0000642 public:
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000643 unsigned ivar_bytepos;
644 unsigned ivar_size;
645 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000646 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar0941b492009-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 Jahaniana5a10c32009-03-10 16:22:08 +0000652 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000653
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000654 class SKIP_SCAN {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000655 public:
656 unsigned skip;
657 unsigned scan;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000658 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000659 : skip(_skip), scan(_scan) {}
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000660 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000661
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000662protected:
663 CodeGen::CodeGenModule &CGM;
Owen Anderson69243822009-07-13 04:10:07 +0000664 llvm::LLVMContext &VMContext;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000665 // FIXME! May not be needing this after all.
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000666 unsigned ObjCABI;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000667
Fariborz Jahanian9397e1d2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000671
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000672 /// LazySymbols - Symbols to generate a lazy reference for. See
673 /// DefinedSymbols and FinishModule().
Daniel Dunbar33063492009-09-07 00:20:42 +0000674 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000675
Daniel Dunbar242d4dc2008-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 Dunbar33063492009-09-07 00:20:42 +0000680 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000681
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000682 /// ClassNames - uniqued class names.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000683 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000684
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000685 /// MethodVarNames - uniqued method variable names.
686 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000687
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +0000688 /// DefinedCategoryNames - list of category names in form Class_Category.
689 llvm::SetVector<std::string> DefinedCategoryNames;
690
Daniel Dunbar6efc0c52008-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 Dunbar6bff2512009-08-03 17:06:42 +0000694
Daniel Dunbarc45ef602008-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 Dunbar6bff2512009-08-03 17:06:42 +0000698
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000699 /// PropertyNames - uniqued method variable names.
700 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000701
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000702 /// ClassReferences - uniqued class references.
703 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000704
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000705 /// SelectorReferences - uniqued selector references.
706 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000707
Daniel Dunbar6efc0c52008-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 Dunbar6bff2512009-08-03 17:06:42 +0000712
Daniel Dunbar0c0e7a62008-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 Dunbar6bff2512009-08-03 17:06:42 +0000716
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000717 /// DefinedClasses - List of defined classes.
718 std::vector<llvm::GlobalValue*> DefinedClasses;
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000719
720 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
721 std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000722
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000723 /// DefinedCategories - List of defined categories.
724 std::vector<llvm::GlobalValue*> DefinedCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000725
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000726 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
727 std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000728
Fariborz Jahanian56210f72009-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 Dunbarc575ce72009-10-19 01:21:19 +0000733 llvm::SmallVectorImpl<char> &NameOut);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000734
Fariborz Jahanian56210f72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000739
Fariborz Jahanian56210f72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000742
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000743 // FIXME: This is a horrible name.
744 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +0000745 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000746
Fariborz Jahanian56210f72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000750
Fariborz Jahanian56210f72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000754
Fariborz Jahanian058a1b72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000758
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +0000759 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
760
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000761 /// BuildIvarLayout - Builds ivar layout bitmap for the class
762 /// implementation for the __strong or __weak case.
763 ///
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000764 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
765 bool ForStrongLayout);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +0000766
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +0000767 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000768
Daniel Dunbard58edcb2009-05-03 14:10:34 +0000769 void BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000770 unsigned int BytePos, bool ForStrongLayout,
771 bool &HasUnion);
Daniel Dunbar5a5a8032009-05-03 21:05:10 +0000772 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000773 const llvm::StructLayout *Layout,
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000774 const RecordDecl *RD,
Chris Lattnerf1690852009-03-31 08:48:01 +0000775 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000776 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahanian81adc052009-04-24 16:17:09 +0000777 bool &HasUnion);
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000778
Fariborz Jahaniand80d81b2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000783
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000784 /// EmitPropertyList - Emit the given property list. The return
785 /// value has type PropertyListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000786 llvm::Constant *EmitPropertyList(llvm::Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000787 const Decl *Container,
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000788 const ObjCContainerDecl *OCD,
789 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000790
Fariborz Jahanian191dcd72009-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 Jahanianda320092009-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 Jahanianb21f07e2009-03-08 20:18:37 +0000802
Daniel Dunbarfd65d372009-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 Lattnerad64e022009-07-17 23:57:13 +0000808 /// global to the "llvm.used" list.
Daniel Dunbar35bd7632009-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 Dunbarc1583062009-04-14 17:42:51 +0000816 /// "llvm.used".
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000817 llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000818 llvm::Constant *Init,
819 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +0000820 unsigned Align,
821 bool AddToUsed);
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000822
John McCall944c8432011-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 Dunbar3e5f0d82009-04-20 06:54:31 +0000833
Daniel Dunbarfce176b2010-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 Jahanianee0af742009-01-21 22:04:16 +0000838public:
Owen Anderson69243822009-07-13 04:10:07 +0000839 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
Mike Stump1eb44332009-09-09 15:08:12 +0000840 CGM(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000841
David Chisnall0d13f6f2010-01-23 02:40:42 +0000842 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000843
Fariborz Jahanian493dab72009-01-26 21:38:32 +0000844 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
845 const ObjCContainerDecl *CD=0);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000846
Fariborz Jahanianda320092009-01-29 19:24:30 +0000847 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000848
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +0000853
Fariborz Jahanianda320092009-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 McCall6b5a61b2011-02-07 10:33:21 +0000859 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
860 const CGBlockInfo &blockInfo);
Fariborz Jahanian89ecd412010-08-04 16:57:49 +0000861
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000862};
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000863
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000864class CGObjCMac : public CGObjCCommonMac {
865private:
866 ObjCTypesHelper ObjCTypes;
Daniel Dunbarf77ac862008-08-11 21:35:06 +0000867
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000868 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000869 /// information.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000870 void EmitModuleInfo();
871
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000872 /// EmitModuleSymols - Emit module symbols, the list of defined
873 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000874 llvm::Constant *EmitModuleSymbols();
875
Daniel Dunbarf77ac862008-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 Dunbar6efc0c52008-08-13 03:21:16 +0000879
Daniel Dunbar27f9d772008-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 Dunbar6bff2512009-08-03 17:06:42 +0000887 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000888 const ObjCInterfaceDecl *ID);
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +0000889
890 /// EmitSuperClassRef - Emits reference to class's main metadata class.
891 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar27f9d772008-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 Jahanian46b86c62009-01-28 19:12:34 +0000899 bool ForClass);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000900
Daniel Dunbarf56f1912008-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 Dunbar27f9d772008-08-21 04:36:09 +0000906 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000907 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000908 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
909 llvm::Constant *Protocols,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000910 const ConstantVector &Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000911
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000912 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000913
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000914 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000915
916 /// EmitMethodList - Emit the method list for the given
Daniel Dunbaraf05bb92008-08-26 08:29:31 +0000917 /// implementation. The return value has type MethodListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000918 llvm::Constant *EmitMethodList(llvm::Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000919 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000920 const ConstantVector &Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000921
922 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000923 /// method declarations.
Daniel Dunbar6efc0c52008-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 Dunbar9c29bf52009-10-18 20:48:59 +0000933 llvm::Constant *EmitMethodDescList(llvm::Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000934 const char *Section,
935 const ConstantVector &Methods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000936
Daniel Dunbar0c0e7a62008-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 Jahanianda320092009-01-29 19:24:30 +0000940 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-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 Jahanianda320092009-01-29 19:24:30 +0000946 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000947
Daniel Dunbar6efc0c52008-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 Dunbarae226fa2008-08-27 02:31:56 +0000952 llvm::Constant *
953 EmitProtocolExtension(const ObjCProtocolDecl *PD,
954 const ConstantVector &OptInstanceMethods,
955 const ConstantVector &OptClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000956
957 /// EmitProtocolList - Generate the list of referenced
958 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000959 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Daniel Dunbardbc933702008-08-21 21:57:41 +0000960 ObjCProtocolDecl::protocol_iterator begin,
961 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000962
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000963 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
964 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +0000965 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
966 bool lval=false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000967
968public:
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000969 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000970
Fariborz Jahanianaa23b572009-01-23 23:53:38 +0000971 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000972
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000973 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +0000974 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000975 QualType ResultType,
976 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000977 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000978 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +0000979 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000980 const ObjCMethodDecl *Method);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000981
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000982 virtual CodeGen::RValue
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000983 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +0000984 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000985 QualType ResultType,
986 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000987 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +0000988 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000989 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000990 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +0000991 const CallArgList &CallArgs,
992 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000993
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000994 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000995 const ObjCInterfaceDecl *ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000996
Fariborz Jahanian03b29602010-06-17 19:56:20 +0000997 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
998 bool lval = false);
Fariborz Jahaniandf9ccc62009-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 McCall5a180392010-07-24 00:37:23 +00001005 virtual llvm::Constant *GetEHType(QualType T);
1006
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001007 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001008
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001009 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001010
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001011 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001012 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001013
Chris Lattner74391b42009-03-22 21:03:39 +00001014 virtual llvm::Constant *GetPropertyGetFunction();
1015 virtual llvm::Constant *GetPropertySetFunction();
David Chisnall8fac25d2010-12-26 22:13:16 +00001016 virtual llvm::Constant *GetGetStructFunction();
1017 virtual llvm::Constant *GetSetStructFunction();
Chris Lattner74391b42009-03-22 21:03:39 +00001018 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001019
John McCallf1549f62010-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 Carlsson64d5d6c2008-09-09 10:04:29 +00001025 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1026 const ObjCAtThrowStmt &S);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001027 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001028 llvm::Value *AddrWeakObj);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001029 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001030 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001031 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001032 llvm::Value *src, llvm::Value *dest,
1033 bool threadlocal = false);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00001034 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001035 llvm::Value *src, llvm::Value *dest,
1036 llvm::Value *ivarOffset);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001037 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1038 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001039 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1040 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001041 llvm::Value *size);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001042
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001043 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1044 QualType ObjectTy,
1045 llvm::Value *BaseValue,
1046 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001047 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001048 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001049 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001050 const ObjCIvarDecl *Ivar);
Fariborz Jahanian6f40e222011-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 Dunbarc17a4d32008-08-11 02:45:11 +00001058};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001059
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001060class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001061private:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001062 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001063 llvm::GlobalVariable* ObjCEmptyCacheVar;
1064 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001065
Daniel Dunbar11394522009-04-18 08:51:00 +00001066 /// SuperClassReferences - uniqued super class references.
1067 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001068
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001069 /// MetaClassReferences - uniqued meta class references.
1070 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbare588b992009-03-01 04:46:24 +00001071
1072 /// EHTypeReferences - uniqued class ehtype references.
1073 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001074
John McCall944c8432011-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 Dunbar6bff2512009-08-03 17:06:42 +00001078
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00001079 /// DefinedMetaClasses - List of defined meta-classes.
1080 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1081
John McCall944c8432011-05-14 03:10:52 +00001082 /// isVTableDispatchedSelector - Returns true if SEL is a
1083 /// vtable-based selector.
1084 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001085
Fariborz Jahanianaa23b572009-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 Dunbar8158a2f2009-04-08 04:21:03 +00001089
Daniel Dunbar463b8762009-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 Dunbar6bff2512009-08-03 17:06:42 +00001096 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1097 unsigned InstanceStart,
1098 unsigned InstanceSize,
1099 const ObjCImplementationDecl *ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001100 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001101 llvm::Constant *IsAGV,
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001102 llvm::Constant *SuperClassGV,
Fariborz Jahaniancf555162009-01-31 00:59:10 +00001103 llvm::Constant *ClassRoGV,
1104 bool HiddenVisibility);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001105
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001106 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001107
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00001108 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001109
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001110 /// EmitMethodList - Emit the method list for the given
1111 /// implementation. The return value has type MethodListnfABITy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001112 llvm::Constant *EmitMethodList(llvm::Twine Name,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001113 const char *Section,
Fariborz Jahanian98abf4b2009-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 Dunbar6bff2512009-08-03 17:06:42 +00001121
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001122 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00001123 const ObjCIvarDecl *Ivar,
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00001124 unsigned long int offset);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001125
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00001130
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00001136
Fariborz Jahanianda320092009-01-29 19:24:30 +00001137 /// EmitProtocolList - Generate the list of referenced
1138 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001139 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Fariborz Jahanianda320092009-01-29 19:24:30 +00001140 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian46551122009-02-04 00:22:57 +00001141 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001142
John McCall944c8432011-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 Jahanian6f40e222011-05-17 22:21:16 +00001152
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00001153 /// GetClassGlobal - Return the global variable for the Objective-C
1154 /// class of the given name.
Fariborz Jahanian0f902942009-04-14 18:41:56 +00001155 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Fariborz Jahanian6f40e222011-05-17 22:21:16 +00001156
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001157 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar11394522009-04-18 08:51:00 +00001158 /// for the given class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001159 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00001160 const ObjCInterfaceDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001161
Daniel Dunbar11394522009-04-18 08:51:00 +00001162 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1163 /// for the given super class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001164 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1165 const ObjCInterfaceDecl *ID);
1166
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001167 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1168 /// meta-data
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001169 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001170 const ObjCInterfaceDecl *ID);
1171
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001172 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1173 /// the given ivar.
1174 ///
Daniel Dunbar5e88bea2009-04-19 00:31:15 +00001175 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001176 const ObjCInterfaceDecl *ID,
1177 const ObjCIvarDecl *Ivar);
1178
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00001179 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1180 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001181 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1182 bool lval=false);
Daniel Dunbare588b992009-03-01 04:46:24 +00001183
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001184 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbare588b992009-03-01 04:46:24 +00001185 /// interface. The return value has type EHTypePtrTy.
John McCall5a180392010-07-24 00:37:23 +00001186 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001187 bool ForDefinition);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001188
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001189 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001190 return "OBJC_METACLASS_$_";
1191 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001192
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001193 const char *getClassSymbolPrefix() const {
1194 return "OBJC_CLASS_$_";
1195 }
1196
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00001197 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001198 uint32_t &InstanceStart,
1199 uint32_t &InstanceSize);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001200
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001201 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001202 Selector GetNullarySelector(const char* name) const {
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001203 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1204 return CGM.getContext().Selectors.getSelector(0, &II);
1205 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001206
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001207 Selector GetUnarySelector(const char* name) const {
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001208 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1209 return CGM.getContext().Selectors.getSelector(1, &II);
1210 }
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001211
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001212 /// ImplementationIsNonLazy - Check whether the given category or
1213 /// class implementation is "non-lazy".
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00001214 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001215
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001216public:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001217 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001218 // FIXME. All stubs for now!
1219 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001220
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001221 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001222 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001223 QualType ResultType,
1224 Selector Sel,
1225 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001226 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001227 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001228 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001229
1230 virtual CodeGen::RValue
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001231 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001232 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001233 QualType ResultType,
1234 Selector Sel,
1235 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001236 bool isCategoryImpl,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001237 llvm::Value *Receiver,
1238 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001239 const CallArgList &CallArgs,
1240 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001241
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001242 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001243 const ObjCInterfaceDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001244
Fariborz Jahanian03b29602010-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 Jahaniandf9ccc62009-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 Dunbar6bff2512009-08-03 17:06:42 +00001254
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00001255 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001256
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001257 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001258 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00001259 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001260
John McCall5a180392010-07-24 00:37:23 +00001261 virtual llvm::Constant *GetEHType(QualType T);
1262
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001263 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001264 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001265 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001266 virtual llvm::Constant *GetPropertySetFunction() {
1267 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001268 }
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001269
David Chisnall8fac25d2010-12-26 22:13:16 +00001270 virtual llvm::Constant *GetSetStructFunction() {
1271 return ObjCTypes.getCopyStructFn();
1272 }
1273 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001274 return ObjCTypes.getCopyStructFn();
1275 }
1276
Chris Lattner74391b42009-03-22 21:03:39 +00001277 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001278 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbar28ed0842009-02-16 18:48:45 +00001279 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001280
John McCallf1549f62010-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 Jahanianaa23b572009-01-23 23:53:38 +00001285 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlssonf57c5b22009-02-16 22:59:18 +00001286 const ObjCAtThrowStmt &S);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001287 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001288 llvm::Value *AddrWeakObj);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001289 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001290 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001291 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001292 llvm::Value *src, llvm::Value *dest,
1293 bool threadlocal = false);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001294 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001295 llvm::Value *src, llvm::Value *dest,
1296 llvm::Value *ivarOffset);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001297 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001298 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001299 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1300 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001301 llvm::Value *size);
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001302 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1303 QualType ObjectTy,
1304 llvm::Value *BaseValue,
1305 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001306 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001307 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001308 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001309 const ObjCIvarDecl *Ivar);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001310};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001311
John McCallcba681a2011-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 Dunbarc17a4d32008-08-11 02:45:11 +00001352} // end anonymous namespace
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001353
1354/* *** Helper Functions *** */
1355
1356/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Andersona1cf15f2009-07-14 23:10:40 +00001357static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001358 llvm::Constant *C,
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001359 unsigned idx0,
1360 unsigned idx1) {
1361 llvm::Value *Idxs[] = {
Owen Anderson0032b272009-08-13 21:57:51 +00001362 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1363 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001364 };
Owen Anderson3c4972d2009-07-29 18:54:39 +00001365 return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001366}
1367
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001368/// hasObjCExceptionAttribute - Return true if this class or any super
1369/// class has the __objc_exception__ attribute.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001370static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor68584ed2009-06-18 16:11:24 +00001371 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidis40b598e2009-06-30 02:34:44 +00001372 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001373 return true;
1374 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor68584ed2009-06-18 16:11:24 +00001375 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001376 return false;
1377}
1378
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001379/* *** CGObjCMac Public Interface *** */
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001380
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001381CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00001382 ObjCTypes(cgm) {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001383 ObjCABI = 1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001384 EmitImageInfo();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001385}
1386
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +00001387/// GetClass - Return a reference to the class for the given interface
1388/// decl.
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001389llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001390 const ObjCInterfaceDecl *ID) {
1391 return EmitClassRef(Builder, ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001392}
1393
1394/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001395llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1396 bool lval) {
1397 return EmitSelector(Builder, Sel, lval);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001398}
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001399llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001400 *Method) {
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001401 return EmitSelector(Builder, Method->getSelector());
1402}
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001403
John McCall5a180392010-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 Dunbarbbce49b2008-08-12 00:12:39 +00001409/// Generate a constant CFString object.
Daniel Dunbar6bff2512009-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 Dunbarbbce49b2008-08-12 00:12:39 +00001417*/
1418
Fariborz Jahanian33e982b2010-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 Jahanianaa23b572009-01-23 23:53:38 +00001428llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall0d13f6f2010-01-23 02:40:42 +00001429 const StringLiteral *SL) {
Fariborz Jahanian33e982b2010-04-22 20:26:39 +00001430 return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
1431 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian4c733072010-10-19 17:19:29 +00001432 CGM.GetAddrOfConstantString(SL));
Daniel Dunbarc17a4d32008-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 Dunbar8f2926b2008-08-23 03:46:30 +00001438CodeGen::RValue
1439CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001440 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001441 QualType ResultType,
1442 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001443 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001444 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001445 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001446 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001447 const CodeGen::CallArgList &CallArgs,
1448 const ObjCMethodDecl *Method) {
Daniel Dunbare8b470d2008-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 Dunbar6bff2512009-08-03 17:06:42 +00001451 llvm::Value *ObjCSuper =
John McCall604da292011-03-04 08:00:29 +00001452 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001453 llvm::Value *ReceiverAsObject =
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001454 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001455 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001456 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001457
Daniel Dunbarf56f1912008-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 Jahanian7ce77922009-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 Stumpb3589f42009-07-30 22:28:39 +00001471 } else {
Fariborz Jahanian7ce77922009-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 Dunbar6bff2512009-08-03 17:06:42 +00001476 }
Fariborz Jahanian182f2682009-11-14 02:18:31 +00001477 }
1478 else if (isCategoryImpl)
1479 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1480 else {
Fariborz Jahanianb0069ee2009-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 Dunbarf56f1912008-08-25 08:19:24 +00001484 }
Mike Stumpf5408fe2009-05-16 07:57:57 +00001485 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1486 // ObjCTypes types.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001487 const llvm::Type *ClassTy =
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001488 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001489 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001490 CGF.Builder.CreateStore(Target,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001491 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall944c8432011-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 Dunbarc17a4d32008-08-11 02:45:11 +00001496}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001497
1498/// Generate code for a message send expression.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001499CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001500 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001501 QualType ResultType,
1502 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001503 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001504 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001505 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001506 const ObjCMethodDecl *Method) {
John McCall944c8432011-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 Dunbar14c80b72008-08-23 09:25:55 +00001511}
1512
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001513CodeGen::RValue
John McCall944c8432011-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 Dunbar19cd87e2008-08-30 03:02:31 +00001524 CallArgList ActualArgs;
Fariborz Jahaniand019d962009-04-24 21:07:43 +00001525 if (!IsSuper)
1526 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
Eli Friedman04c9a492011-05-02 17:57:46 +00001527 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1528 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001529 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001530
Daniel Dunbar541b63b2009-02-02 23:23:47 +00001531 CodeGenTypes &Types = CGM.getTypes();
John McCall04a67a62010-02-05 21:31:56 +00001532 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindola264ba482010-03-30 20:24:48 +00001533 FunctionType::ExtInfo());
Daniel Dunbar67939662009-09-17 04:01:40 +00001534 const llvm::FunctionType *FTy =
1535 Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001536
Anders Carlsson7e70fb22010-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 McCallcba681a2011-05-14 21:12:11 +00001542 NullReturnState nullReturn;
1543
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001544 llvm::Constant *Fn = NULL;
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001545 if (CGM.ReturnTypeUsesSRet(FnInfo)) {
John McCallcba681a2011-05-14 21:12:11 +00001546 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001547 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001548 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001549 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1550 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1551 : ObjCTypes.getSendFpretFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001552 } else {
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001553 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001554 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001555 }
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001556 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
John McCallcba681a2011-05-14 21:12:11 +00001557 RValue rvalue = CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
1558 return nullReturn.complete(CGF, rvalue, ResultType);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001559}
1560
Fariborz Jahanian93ce50d2010-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 McCall6b5a61b2011-02-07 10:33:21 +00001577llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1578 const CGBlockInfo &blockInfo) {
1579 llvm::Constant *nullPtr =
Fariborz Jahanian44034db2010-08-04 18:44:59 +00001580 llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
John McCall6b5a61b2011-02-07 10:33:21 +00001581
Fariborz Jahanianfb550312010-09-13 16:09:44 +00001582 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
John McCall6b5a61b2011-02-07 10:33:21 +00001583 return nullPtr;
1584
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001585 bool hasUnion = false;
Fariborz Jahanian93ce50d2010-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 Jahanian81979822010-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 McCall6b5a61b2011-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 Jahanianc5904b42010-09-11 01:27:29 +00001620 continue;
John McCall6b5a61b2011-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 Jahaniane1a48982010-08-05 21:00:25 +00001626 continue;
1627 }
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001628
John McCall6b5a61b2011-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 Jahanian93ce50d2010-08-04 23:55:24 +00001635 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
John McCall6b5a61b2011-02-07 10:33:21 +00001636 SkipIvars.push_back(GC_IVAR(fieldOffset,
1637 fieldSize / ByteSizeInBits));
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001638 }
1639
1640 if (IvarsInfo.empty())
John McCall6b5a61b2011-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 Jahanian93ce50d2010-08-04 23:55:24 +00001647
1648 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00001649 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-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 Jahanian89ecd412010-08-04 16:57:49 +00001662}
1663
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001664llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001665 const ObjCProtocolDecl *PD) {
Daniel Dunbarc67876d2008-09-04 04:33:15 +00001666 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00001667 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc67876d2008-09-04 04:33:15 +00001668 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1669
Owen Anderson3c4972d2009-07-29 18:54:39 +00001670 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001671 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001672}
1673
Fariborz Jahanianda320092009-01-29 19:24:30 +00001674void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stumpf5408fe2009-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 Dunbar0c0e7a62008-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 Dunbar6bff2512009-08-03 17:06:42 +00001682 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001683 GetOrEmitProtocol(PD);
1684}
1685
Fariborz Jahanianda320092009-01-29 19:24:30 +00001686llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001687 if (DefinedProtocols.count(PD->getIdentifier()))
1688 return GetOrEmitProtocol(PD);
Douglas Gregorf968d832011-05-27 01:19:52 +00001689
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001690 return GetOrEmitProtocolRef(PD);
1691}
1692
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001693/*
Daniel Dunbar6bff2512009-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 Dunbar6efc0c52008-08-13 03:21:16 +00001702
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001703See EmitProtocolExtension().
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001704*/
Daniel Dunbar0c0e7a62008-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 Dunbar242d4dc2008-08-25 06:02:07 +00001712 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00001713 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00001714 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1715
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001716 // Construct method lists.
1717 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1718 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001719 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001720 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001721 ObjCMethodDecl *MD = *i;
1722 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00001723 if (!C)
1724 return GetOrEmitProtocolRef(PD);
1725
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001726 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1727 OptInstanceMethods.push_back(C);
1728 } else {
1729 InstanceMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001730 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001731 }
1732
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001733 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001734 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001735 ObjCMethodDecl *MD = *i;
1736 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00001737 if (!C)
1738 return GetOrEmitProtocolRef(PD);
1739
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001740 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1741 OptClassMethods.push_back(C);
1742 } else {
1743 ClassMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001744 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001745 }
1746
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001747 std::vector<llvm::Constant*> Values(5);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001748 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001749 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001750 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001751 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardbc933702008-08-21 21:57:41 +00001752 PD->protocol_begin(),
1753 PD->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001754 Values[3] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001755 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001756 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1757 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001758 Values[4] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001759 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001760 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1761 ClassMethods);
Owen Anderson08e25242009-07-27 22:29:56 +00001762 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001763 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001764
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001765 if (Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001766 // Already created, fix the linkage and update the initializer.
1767 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001768 Entry->setInitializer(Init);
1769 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001770 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00001771 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001772 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001773 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001774 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001775 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001776 // FIXME: Is this necessary? Why only for protocol?
1777 Entry->setAlignment(4);
1778 }
Chris Lattnerad64e022009-07-17 23:57:13 +00001779 CGM.AddUsedGlobal(Entry);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001780
1781 return Entry;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001782}
1783
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001784llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001785 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1786
1787 if (!Entry) {
Daniel Dunbar0c0e7a62008-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 Dunbar6bff2512009-08-03 17:06:42 +00001791 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00001792 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001793 llvm::GlobalValue::ExternalLinkage,
1794 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001795 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001796 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001797 // FIXME: Is this necessary? Why only for protocol?
1798 Entry->setAlignment(4);
1799 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001800
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001801 return Entry;
1802}
1803
1804/*
1805 struct _objc_protocol_extension {
Daniel Dunbar6bff2512009-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 Dunbar6efc0c52008-08-13 03:21:16 +00001810 };
1811*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001812llvm::Constant *
1813CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1814 const ConstantVector &OptInstanceMethods,
1815 const ConstantVector &OptClassMethods) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001816 uint64_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00001817 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001818 std::vector<llvm::Constant*> Values(4);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001819 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001820 Values[1] =
1821 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001822 + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001823 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1824 OptInstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001825 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001826 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001827 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1828 OptClassMethods);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001829 Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00001830 0, PD, ObjCTypes);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001831
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001832 // Return null if no extension bits are used.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001833 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001834 Values[3]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001835 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001836
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001837 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00001838 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001839
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001840 // No special section, but goes in llvm.used
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001841 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001842 Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001843 0, 0, true);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001844}
1845
1846/*
1847 struct objc_protocol_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001848 struct objc_protocol_list *next;
1849 long count;
1850 Protocol *list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001851 };
1852*/
Daniel Dunbardbc933702008-08-21 21:57:41 +00001853llvm::Constant *
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001854CGObjCMac::EmitProtocolList(llvm::Twine Name,
Daniel Dunbardbc933702008-08-21 21:57:41 +00001855 ObjCProtocolDecl::protocol_iterator begin,
1856 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001857 std::vector<llvm::Constant*> ProtocolRefs;
1858
Daniel Dunbardbc933702008-08-21 21:57:41 +00001859 for (; begin != end; ++begin)
1860 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001861
1862 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001863 if (ProtocolRefs.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001864 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001865
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001866 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00001867 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001868
1869 std::vector<llvm::Constant*> Values(3);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001870 // This field is only used by the runtime.
Owen Andersonc9c88b42009-07-31 20:28:54 +00001871 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001872 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar6bff2512009-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 Dunbar6efc0c52008-08-13 03:21:16 +00001877 ProtocolRefs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001878
Nick Lewycky0d36dd22009-09-19 20:00:52 +00001879 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001880 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001881 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00001882 4, false);
Owen Anderson3c4972d2009-07-29 18:54:39 +00001883 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001884}
1885
Fariborz Jahanian191dcd72009-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 Dunbar6efc0c52008-08-13 03:21:16 +00001906/*
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001907 struct _objc_property {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001908 const char * const name;
1909 const char * const attributes;
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001910 };
1911
1912 struct _objc_property_list {
Daniel Dunbar6bff2512009-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 Dunbarc8ef5512008-08-23 00:19:03 +00001916 };
1917*/
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001918llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001919 const Decl *Container,
1920 const ObjCContainerDecl *OCD,
1921 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001922 std::vector<llvm::Constant*> Properties, Prop(2);
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001923 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001924 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
1925 E = OCD->prop_end(); I != E; ++I) {
Steve Naroff93983f82009-01-11 12:47:58 +00001926 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001927 PropertySet.insert(PD->getIdentifier());
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001928 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00001929 Prop[1] = GetPropertyTypeString(PD, Container);
Owen Anderson08e25242009-07-27 22:29:56 +00001930 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001931 Prop));
1932 }
Fariborz Jahanian6afbdf52010-06-22 16:33:55 +00001933 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek53b94412010-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 Jahanian6afbdf52010-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 Dunbarc8ef5512008-08-23 00:19:03 +00001946
1947 // Return null for empty list.
1948 if (Properties.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001949 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001950
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001951 unsigned PropertySize =
Duncan Sands9408c452009-05-09 07:08:47 +00001952 CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001953 std::vector<llvm::Constant*> Values(3);
Owen Anderson4a28d5d2009-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 Dunbar6bff2512009-08-03 17:06:42 +00001956 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001957 Properties.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00001958 Values[2] = llvm::ConstantArray::get(AT, Properties);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00001959 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001960
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001961 llvm::GlobalVariable *GV =
1962 CreateMetadataVar(Name, Init,
1963 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbar0bf21992009-04-15 02:56:18 +00001964 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001965 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbar0bf21992009-04-15 02:56:18 +00001966 true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00001967 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001968}
1969
1970/*
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001971 struct objc_method_description_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001972 int count;
1973 struct objc_method_description list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001974 };
1975*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001976llvm::Constant *
1977CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
1978 std::vector<llvm::Constant*> Desc(2);
Owen Andersona1cf15f2009-07-14 23:10:40 +00001979 Desc[0] =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001980 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1981 ObjCTypes.SelectorPtrTy);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001982 Desc[1] = GetMethodVarType(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00001983 if (!Desc[1])
1984 return 0;
1985
Owen Anderson08e25242009-07-27 22:29:56 +00001986 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001987 Desc);
1988}
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001989
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001990llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001991 const char *Section,
1992 const ConstantVector &Methods) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001993 // Return null for empty list.
1994 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001995 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001996
1997 std::vector<llvm::Constant*> Values(2);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001998 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001999 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002000 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002001 Values[1] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002002 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002003
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002004 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002005 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002006 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002007}
2008
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002009/*
2010 struct _objc_category {
Daniel Dunbar6bff2512009-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 Dunbar86e253a2008-08-22 20:34:54 +00002018 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002019*/
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00002020void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Duncan Sands9408c452009-05-09 07:08:47 +00002021 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002022
Mike Stumpf5408fe2009-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 Dunbar86e253a2008-08-22 20:34:54 +00002027 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002028 const ObjCCategoryDecl *Category =
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002029 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002030
2031 llvm::SmallString<256> ExtName;
2032 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2033 << OCD->getName();
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002034
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002035 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002036 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002037 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002038 // Instance methods should always be defined.
2039 InstanceMethods.push_back(GetMethodConstant(*i));
2040 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002041 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002042 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002043 // Class methods should always be defined.
2044 ClassMethods.push_back(GetMethodConstant(*i));
2045 }
2046
Daniel Dunbar86e253a2008-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 Jahanian679cd7f2009-04-29 20:40:05 +00002050 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002051 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002052 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002053 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002054 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002055 Values[3] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002056 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002057 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002058 ClassMethods);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002059 if (Category) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002060 Values[4] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002061 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002062 Category->protocol_begin(),
2063 Category->protocol_end());
2064 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002065 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002066 }
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002067 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002068
2069 // If there is no category @interface then there can be no properties.
2070 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002071 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002072 OCD, Category, ObjCTypes);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002073 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002074 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002075 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002076
Owen Anderson08e25242009-07-27 22:29:56 +00002077 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002078 Values);
2079
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002080 llvm::GlobalVariable *GV =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002081 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002082 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002083 4, true);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002084 DefinedCategories.push_back(GV);
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00002085 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00002086 // method definition entries must be clear for next implementation.
2087 MethodDefinitions.clear();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002088}
2089
Daniel Dunbar27f9d772008-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 Dunbar27f9d772008-08-21 04:36:09 +00002101/*
2102 struct _objc_class {
Daniel Dunbar6bff2512009-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 Dunbar27f9d772008-08-21 04:36:09 +00002116 };
2117
2118 See EmitClassExtension();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002119*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002120void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002121 DefinedSymbols.insert(ID->getIdentifier());
2122
Chris Lattner8ec03f52008-11-24 03:54:41 +00002123 std::string ClassName = ID->getNameAsString();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002124 // FIXME: Gross
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002125 ObjCInterfaceDecl *Interface =
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002126 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002127 llvm::Constant *Protocols =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002128 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00002129 Interface->all_referenced_protocol_begin(),
2130 Interface->all_referenced_protocol_end());
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002131 unsigned Flags = eClassFlags_Factory;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00002132 if (ID->getNumIvarInitializers())
2133 Flags |= eClassFlags_HasCXXStructors;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002134 unsigned Size =
Ken Dyck5f022d82011-02-09 01:59:34 +00002135 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002136
2137 // FIXME: Set CXX-structors flag.
John McCall1fb0caa2010-10-22 21:05:15 +00002138 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002139 Flags |= eClassFlags_Hidden;
2140
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002141 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002142 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002143 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002144 // Instance methods should always be defined.
2145 InstanceMethods.push_back(GetMethodConstant(*i));
2146 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002147 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002148 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002149 // Class methods should always be defined.
2150 ClassMethods.push_back(GetMethodConstant(*i));
2151 }
2152
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002153 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002154 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-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 Dunbar27f9d772008-08-21 04:36:09 +00002169 std::vector<llvm::Constant*> Values(12);
Daniel Dunbar5384b092009-05-03 08:56:52 +00002170 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002171 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002172 // Record a reference to the super class.
2173 LazySymbols.insert(Super->getIdentifier());
2174
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002175 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002176 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002177 ObjCTypes.ClassPtrTy);
2178 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002179 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002180 }
2181 Values[ 2] = GetClassName(ID->getIdentifier());
2182 // Version is always 0.
Owen Anderson4a28d5d2009-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 Jahanian46b86c62009-01-28 19:12:34 +00002186 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002187 Values[ 7] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002188 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002189 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002190 InstanceMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002191 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002192 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002193 Values[ 9] = Protocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002194 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002195 Values[11] = EmitClassExtension(ID);
Owen Anderson08e25242009-07-27 22:29:56 +00002196 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002197 Values);
Fariborz Jahanianb0069ee2009-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 Dunbar27f9d772008-08-21 04:36:09 +00002214 DefinedClasses.push_back(GV);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00002215 // method definition entries must be clear for next implementation.
2216 MethodDefinitions.clear();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002217}
2218
2219llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2220 llvm::Constant *Protocols,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002221 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002222 unsigned Flags = eClassFlags_Meta;
Duncan Sands9408c452009-05-09 07:08:47 +00002223 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002224
John McCall1fb0caa2010-10-22 21:05:15 +00002225 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002226 Flags |= eClassFlags_Hidden;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002227
Daniel Dunbar27f9d772008-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 Dunbar6bff2512009-08-03 17:06:42 +00002233 Values[ 0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002234 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002235 ObjCTypes.ClassPtrTy);
Daniel Dunbar86e253a2008-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 Dunbar27f9d772008-08-21 04:36:09 +00002239 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002240 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002241 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002242 ObjCTypes.ClassPtrTy);
2243 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002244 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002245 }
2246 Values[ 2] = GetClassName(ID->getIdentifier());
2247 // Version is always 0.
Owen Anderson4a28d5d2009-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 Jahanian46b86c62009-01-28 19:12:34 +00002251 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002252 Values[ 7] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00002253 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002254 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002255 Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002256 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002257 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002258 Values[ 9] = Protocols;
2259 // ivar_layout for metaclass is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002260 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002261 // The class extension is always unused for metaclasses.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002262 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00002263 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002264 Values);
2265
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002266 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattner8ec03f52008-11-24 03:54:41 +00002267 Name += ID->getNameAsCString();
Daniel Dunbarf56f1912008-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 Anderson1c431b32009-07-08 19:05:04 +00002277 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002278 llvm::GlobalValue::InternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00002279 Init, Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002280 }
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002281 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbar58a29122009-03-09 22:18:41 +00002282 GV->setAlignment(4);
Chris Lattnerad64e022009-07-17 23:57:13 +00002283 CGM.AddUsedGlobal(GV);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002284
2285 return GV;
2286}
2287
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002288llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00002289 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002290
Mike Stumpf5408fe2009-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 Dunbarf56f1912008-08-25 08:19:24 +00002295
2296 // Check for an existing forward reference.
Fariborz Jahanianb0d27942009-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 Dunbar6bff2512009-08-03 17:06:42 +00002299 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2300 true)) {
Daniel Dunbarf56f1912008-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 Anderson1c431b32009-07-08 19:05:04 +00002307 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002308 llvm::GlobalValue::ExternalLinkage,
2309 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00002310 Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002311 }
2312}
2313
Fariborz Jahanianb0069ee2009-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 Dunbar27f9d772008-08-21 04:36:09 +00002330/*
2331 struct objc_class_ext {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002332 uint32_t size;
2333 const char *weak_ivar_layout;
2334 struct _objc_property_list *properties;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002335 };
2336*/
2337llvm::Constant *
2338CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002339 uint64_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00002340 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002341
2342 std::vector<llvm::Constant*> Values(3);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002343 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanianc71303d2009-04-22 23:00:43 +00002344 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002345 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002346 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002347
2348 // Return null if no extension bits are used.
2349 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002350 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002351
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002352 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00002353 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002354 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002355 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002356 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002357}
2358
2359/*
2360 struct objc_ivar {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002361 char *ivar_name;
2362 char *ivar_type;
2363 int ivar_offset;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002364 };
2365
2366 struct objc_ivar_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002367 int ivar_count;
2368 struct objc_ivar list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002369 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002370*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002371llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002372 bool ForClass) {
Daniel Dunbar27f9d772008-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 Andersonc9c88b42009-07-31 20:28:54 +00002381 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002382
2383 ObjCInterfaceDecl *OID =
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002384 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002385
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00002386 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00002387 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002388
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00002389 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2390 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00002391 // Ignore unnamed bit-fields.
2392 if (!IVD->getDeclName())
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002393 continue;
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00002394 Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2395 Ivar[1] = GetMethodVarType(IVD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002396 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
Daniel Dunbar97776872009-04-22 07:32:20 +00002397 ComputeIvarBaseOffset(CGM, OID, IVD));
Owen Anderson08e25242009-07-27 22:29:56 +00002398 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002399 }
2400
2401 // Return null for empty list.
2402 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002403 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002404
2405 std::vector<llvm::Constant*> Values(2);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002406 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00002407 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002408 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002409 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002410 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002411
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002412 llvm::GlobalVariable *GV;
2413 if (ForClass)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002414 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002415 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002416 4, true);
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002417 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002418 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002419 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002420 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002421 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002422}
2423
2424/*
2425 struct objc_method {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002426 SEL method_name;
2427 char *method_types;
2428 void *method;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002429 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002430
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002431 struct objc_method_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002432 struct objc_method_list *obsolete;
2433 int count;
2434 struct objc_method methods_list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002435 };
2436*/
Daniel Dunbarc45ef602008-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 Dunbarae226fa2008-08-27 02:31:56 +00002441llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00002442 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002443 if (!Fn)
2444 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002445
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002446 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002447 Method[0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002448 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002449 ObjCTypes.SelectorPtrTy);
2450 Method[1] = GetMethodVarType(MD);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002451 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00002452 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002453}
2454
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002455llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002456 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002457 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002458 // Return null for empty list.
2459 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002460 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002461
2462 std::vector<llvm::Constant*> Values(3);
Owen Andersonc9c88b42009-07-31 20:28:54 +00002463 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002464 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00002465 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002466 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002467 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002468 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002469
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002470 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002471 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002472 ObjCTypes.MethodListPtrTy);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002473}
2474
Fariborz Jahanian493dab72009-01-26 21:38:32 +00002475llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002476 const ObjCContainerDecl *CD) {
Daniel Dunbarc575ce72009-10-19 01:21:19 +00002477 llvm::SmallString<256> Name;
Fariborz Jahanian679a5022009-01-10 21:06:09 +00002478 GetNameForMethod(OMD, CD, Name);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002479
Daniel Dunbar541b63b2009-02-02 23:23:47 +00002480 CodeGenTypes &Types = CGM.getTypes();
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00002481 const llvm::FunctionType *MethodTy =
Daniel Dunbar541b63b2009-02-02 23:23:47 +00002482 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002483 llvm::Function *Method =
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00002484 llvm::Function::Create(MethodTy,
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002485 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarc575ce72009-10-19 01:21:19 +00002486 Name.str(),
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002487 &CGM.getModule());
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002488 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002489
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002490 return Method;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002491}
2492
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002493llvm::GlobalVariable *
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002494CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002495 llvm::Constant *Init,
2496 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +00002497 unsigned Align,
2498 bool AddToUsed) {
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002499 const llvm::Type *Ty = Init->getType();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002500 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00002501 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerad64e022009-07-17 23:57:13 +00002502 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002503 if (Section)
2504 GV->setSection(Section);
Daniel Dunbar35bd7632009-03-09 20:50:13 +00002505 if (Align)
2506 GV->setAlignment(Align);
2507 if (AddToUsed)
Chris Lattnerad64e022009-07-17 23:57:13 +00002508 CGM.AddUsedGlobal(GV);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002509 return GV;
2510}
2511
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002512llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00002513 // Abuse this interface function as a place to finalize.
2514 FinishModule();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002515 return NULL;
2516}
2517
Chris Lattner74391b42009-03-22 21:03:39 +00002518llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002519 return ObjCTypes.getGetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00002520}
2521
Chris Lattner74391b42009-03-22 21:03:39 +00002522llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002523 return ObjCTypes.getSetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00002524}
2525
David Chisnall8fac25d2010-12-26 22:13:16 +00002526llvm::Constant *CGObjCMac::GetGetStructFunction() {
2527 return ObjCTypes.getCopyStructFn();
2528}
2529llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00002530 return ObjCTypes.getCopyStructFn();
2531}
2532
Chris Lattner74391b42009-03-22 21:03:39 +00002533llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002534 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson2abd89c2008-08-31 04:05:03 +00002535}
2536
John McCallf1549f62010-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 McCallcc505292010-07-21 06:59:36 +00002546namespace {
John McCall1f0fca52010-07-21 07:22:38 +00002547 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCallcc505292010-07-21 06:59:36 +00002548 const Stmt &S;
John McCall0b251722010-08-04 05:59:32 +00002549 llvm::Value *SyncArgSlot;
John McCallcc505292010-07-21 06:59:36 +00002550 llvm::Value *CallTryExitVar;
2551 llvm::Value *ExceptionData;
2552 ObjCTypesHelper &ObjCTypes;
2553 PerformFragileFinally(const Stmt *S,
John McCall0b251722010-08-04 05:59:32 +00002554 llvm::Value *SyncArgSlot,
John McCallcc505292010-07-21 06:59:36 +00002555 llvm::Value *CallTryExitVar,
2556 llvm::Value *ExceptionData,
2557 ObjCTypesHelper *ObjCTypes)
John McCall0b251722010-08-04 05:59:32 +00002558 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCallcc505292010-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 McCalld96a8e72010-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 McCallcc505292010-07-21 06:59:36 +00002585 CGF.EmitStmt(FinallyStmt->getFinallyBody());
2586
John McCalld96a8e72010-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 McCallcc505292010-07-21 06:59:36 +00002595 } else {
2596 // Emit objc_sync_exit(expr); as finally's sole statement for
2597 // @synchronized.
John McCall0b251722010-08-04 05:59:32 +00002598 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCallcc505292010-07-21 06:59:36 +00002599 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
2600 ->setDoesNotThrow();
2601 }
2602 }
2603 };
John McCall87bb5822010-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 McCall0b251722010-08-04 05:59:32 +00002620
John McCall87bb5822010-07-31 23:20:56 +00002621 void emitWriteHazard();
John McCall0b251722010-08-04 05:59:32 +00002622 void emitHazardsInNewBlocks();
John McCall87bb5822010-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 McCall87bb5822010-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 McCall0b251722010-08-04 05:59:32 +00002689void FragileHazards::emitHazardsInNewBlocks() {
John McCall87bb5822010-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 McCall0b251722010-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 McCall87bb5822010-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 McCall0774cb82011-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 McCallcc505292010-07-21 06:59:36 +00002752}
2753
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002754/*
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002755
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002756 Objective-C setjmp-longjmp (sjlj) Exception Handling
2757 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002758
John McCallf1549f62010-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 Dunbar6bff2512009-08-03 17:06:42 +00002791 The basic framework for a @try-catch-finally is as follows:
2792 {
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002793 objc_exception_data d;
2794 id _rethrow = null;
Anders Carlsson190d00e2009-02-07 21:26:04 +00002795 bool _call_try_exit = true;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002796
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002797 objc_exception_try_enter(&d);
2798 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002799 ... try body ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002800 } else {
Daniel Dunbar6bff2512009-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 Dunbar18ccc772008-09-28 01:03:14 +00002817 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00002818 ... jump-through-finally to finally_end ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002819
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002820 finally:
Anders Carlsson190d00e2009-02-07 21:26:04 +00002821 if (_call_try_exit)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002822 objc_exception_try_exit(&d);
Anders Carlsson190d00e2009-02-07 21:26:04 +00002823
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002824 ... finally block ....
Daniel Dunbar898d5082008-09-30 01:06:03 +00002825 ... dispatch to finally destination ...
2826
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002827 finally_rethrow:
Daniel Dunbar898d5082008-09-30 01:06:03 +00002828 objc_exception_throw(_rethrow);
2829
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002830 finally_end:
2831 }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002832
Daniel Dunbar6bff2512009-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 Dunbar18ccc772008-09-28 01:03:14 +00002837
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002838 We specialize this framework for a few particular circumstances:
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002839
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002840 - If there are no catch blocks, then we avoid emitting the second
2841 exception handling context.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002842
Daniel Dunbar6bff2512009-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 Dunbar18ccc772008-09-28 01:03:14 +00002845
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002846 - FIXME: If there is no @finally block we can do a few more
2847 simplifications.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002848
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002849 Rethrows and Jumps-Through-Finally
2850 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002851
John McCallf1549f62010-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 Dunbar18ccc772008-09-28 01:03:14 +00002854
John McCallf1549f62010-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 Dunbar898d5082008-09-30 01:06:03 +00002859
John McCallf1549f62010-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 Dunbar18ccc772008-09-28 01:03:14 +00002864*/
2865
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00002866void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2867 const Stmt &S) {
2868 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallf1549f62010-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 Dunbar6bff2512009-08-03 17:06:42 +00002879
Daniel Dunbar1c566672009-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 McCall0b251722010-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 Dunbar1c566672009-02-24 01:43:46 +00002886 if (!isTry) {
John McCall0b251722010-08-04 05:59:32 +00002887 llvm::Value *SyncArg =
Daniel Dunbar1c566672009-02-24 01:43:46 +00002888 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2889 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallf1549f62010-07-06 01:34:17 +00002890 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
2891 ->setDoesNotThrow();
John McCall0b251722010-08-04 05:59:32 +00002892
2893 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
2894 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar1c566672009-02-24 01:43:46 +00002895 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00002896
John McCall0b251722010-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 McCall87bb5822010-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 McCallf1549f62010-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 McCall0b251722010-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 McCallf1549f62010-07-06 01:34:17 +00002916 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlsson190d00e2009-02-07 21:26:04 +00002917 "_call_try_exit");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002918
John McCall9e2213d2010-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 McCallf1549f62010-07-06 01:34:17 +00002923 // Push a normal cleanup to leave the try scope.
John McCall1f0fca52010-07-21 07:22:38 +00002924 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall0b251722010-08-04 05:59:32 +00002925 SyncArgSlot,
John McCall1f0fca52010-07-21 07:22:38 +00002926 CallTryExitVar,
2927 ExceptionData,
2928 &ObjCTypes);
John McCallf1549f62010-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 Dunbar55e87422008-11-11 02:29:29 +00002947 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
2948 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallf1549f62010-07-06 01:34:17 +00002949 llvm::Value *DidCatch =
John McCalld96a8e72010-08-11 00:16:14 +00002950 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
2951 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson80f25672008-09-09 17:59:25 +00002952
John McCallf1549f62010-07-06 01:34:17 +00002953 // Emit the protected block.
Anders Carlsson80f25672008-09-09 17:59:25 +00002954 CGF.EmitBlock(TryBlock);
John McCall0b251722010-08-04 05:59:32 +00002955 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002956 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallf1549f62010-07-06 01:34:17 +00002957 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall0b251722010-08-04 05:59:32 +00002958
2959 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002960
John McCallf1549f62010-07-06 01:34:17 +00002961 // Emit the exception handler block.
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00002962 CGF.EmitBlock(TryHandler);
Daniel Dunbar55e40722008-09-27 07:03:52 +00002963
John McCall87bb5822010-07-31 23:20:56 +00002964 // Don't optimize loads of the in-scope locals across this point.
2965 Hazards.emitWriteHazard();
2966
John McCallf1549f62010-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 McCall0b251722010-08-04 05:59:32 +00002971 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00002972 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallf1549f62010-07-06 01:34:17 +00002973
2974 // Otherwise, we have to match against the caught exceptions.
2975 } else {
John McCall0b251722010-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 McCallf1549f62010-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 Gregor8f5e3dd2010-04-23 22:50:49 +00002987 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002988
John McCall0b251722010-08-04 05:59:32 +00002989 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallf1549f62010-07-06 01:34:17 +00002990
John McCall0b251722010-08-04 05:59:32 +00002991 llvm::BasicBlock *CatchBlock = 0;
2992 llvm::BasicBlock *CatchHandler = 0;
2993 if (HasFinally) {
John McCall9e2213d2010-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 McCall0b251722010-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 Carlsson80f25672008-09-09 17:59:25 +00003004
John McCall0b251722010-08-04 05:59:32 +00003005 llvm::CallInst *SetJmpResult =
3006 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3007 "setjmp.result");
3008 SetJmpResult->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003009
John McCall0b251722010-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 Dunbar6bff2512009-08-03 17:06:42 +00003021
Daniel Dunbar55e40722008-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 Gregor8f5e3dd2010-04-23 22:50:49 +00003026 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3027 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson80f25672008-09-09 17:59:25 +00003028
Douglas Gregorc00d8e12010-04-26 16:46:50 +00003029 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff14108da2009-07-10 23:34:53 +00003030 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar129271a2008-09-27 07:36:24 +00003031
Anders Carlsson80f25672008-09-09 17:59:25 +00003032 // catch(...) always matches.
Daniel Dunbar55e40722008-09-27 07:03:52 +00003033 if (!CatchParam) {
3034 AllMatched = true;
3035 } else {
John McCall183700f2009-09-21 23:43:11 +00003036 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003037
John McCallf1549f62010-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 Dunbar97f61d12008-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 Friedman818e96f2009-07-11 00:57:02 +00003042 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbar55e40722008-09-27 07:03:52 +00003043 AllMatched = true;
Anders Carlsson80f25672008-09-09 17:59:25 +00003044 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003045
John McCallf1549f62010-07-06 01:34:17 +00003046 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003047 if (AllMatched) {
John McCallf1549f62010-07-06 01:34:17 +00003048 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3049
Anders Carlssondde0a942008-09-11 09:15:33 +00003050 if (CatchParam) {
John McCallb6bbcc92010-10-15 04:57:14 +00003051 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003052 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallf1549f62010-07-06 01:34:17 +00003053
3054 // These types work out because ConvertType(id) == i8*.
Steve Naroff7ba138a2009-03-03 19:52:17 +00003055 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlssondde0a942008-09-11 09:15:33 +00003056 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003057
Anders Carlssondde0a942008-09-11 09:15:33 +00003058 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003059
3060 // The scope of the catch variable ends right here.
3061 CatchVarCleanups.ForceCleanup();
3062
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003063 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson80f25672008-09-09 17:59:25 +00003064 break;
3065 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003066
Steve Naroff14108da2009-07-10 23:34:53 +00003067 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall506b57e2010-05-17 21:00:27 +00003068 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallf1549f62010-07-06 01:34:17 +00003069
3070 // FIXME: @catch (Class c) ?
John McCall506b57e2010-05-17 21:00:27 +00003071 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3072 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson80f25672008-09-09 17:59:25 +00003073
3074 // Check if the @catch block matches the exception object.
John McCall506b57e2010-05-17 21:00:27 +00003075 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003076
John McCallf1549f62010-07-06 01:34:17 +00003077 llvm::CallInst *Match =
Chris Lattner34b02a12009-04-22 02:26:14 +00003078 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3079 Class, Caught, "match");
John McCallf1549f62010-07-06 01:34:17 +00003080 Match->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003081
John McCallf1549f62010-07-06 01:34:17 +00003082 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3083 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003084
3085 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00003086 MatchedBlock, NextCatchBlock);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003087
Anders Carlsson80f25672008-09-09 17:59:25 +00003088 // Emit the @catch block.
3089 CGF.EmitBlock(MatchedBlock);
John McCallf1549f62010-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 McCall0b251722010-08-04 05:59:32 +00003093 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallf1549f62010-07-06 01:34:17 +00003094
John McCallb6bbcc92010-10-15 04:57:14 +00003095 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003096 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003097
John McCallf1549f62010-07-06 01:34:17 +00003098 // Initialize the catch variable.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003099 llvm::Value *Tmp =
3100 CGF.Builder.CreateBitCast(Caught,
3101 CGF.ConvertType(CatchParam->getType()),
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003102 "tmp");
Steve Naroff7ba138a2009-03-03 19:52:17 +00003103 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003104
Anders Carlssondde0a942008-09-11 09:15:33 +00003105 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003106
3107 // We're done with the catch variable.
3108 CatchVarCleanups.ForceCleanup();
3109
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003110 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003111
Anders Carlsson80f25672008-09-09 17:59:25 +00003112 CGF.EmitBlock(NextCatchBlock);
3113 }
3114
John McCallf1549f62010-07-06 01:34:17 +00003115 CGF.ObjCEHValueStack.pop_back();
3116
John McCall0b251722010-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 McCall9e2213d2010-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 McCall0b251722010-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 Carlssonf3a79a92009-02-09 20:38:58 +00003145 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbar55e40722008-09-27 07:03:52 +00003146 }
Anders Carlsson80f25672008-09-09 17:59:25 +00003147 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003148
John McCall87bb5822010-07-31 23:20:56 +00003149 // Insert read hazards as required in the new blocks.
John McCall0b251722010-08-04 05:59:32 +00003150 Hazards.emitHazardsInNewBlocks();
John McCall87bb5822010-07-31 23:20:56 +00003151
John McCallf1549f62010-07-06 01:34:17 +00003152 // Pop the cleanup.
John McCall0b251722010-08-04 05:59:32 +00003153 CGF.Builder.restoreIP(TryFallthroughIP);
3154 if (CGF.HaveInsertPoint())
3155 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallf1549f62010-07-06 01:34:17 +00003156 CGF.PopCleanupBlock();
John McCall0b251722010-08-04 05:59:32 +00003157 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003158
John McCallf1549f62010-07-06 01:34:17 +00003159 // Emit the rethrow block.
John McCall87bb5822010-07-31 23:20:56 +00003160 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallff8e1152010-07-23 21:56:41 +00003161 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallf1549f62010-07-06 01:34:17 +00003162 if (CGF.HaveInsertPoint()) {
John McCall9e2213d2010-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 McCall0b251722010-08-04 05:59:32 +00003167
John McCall9e2213d2010-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 McCallf1549f62010-07-06 01:34:17 +00003178 ->setDoesNotThrow();
3179 CGF.Builder.CreateUnreachable();
Fariborz Jahanianf2878e52008-11-21 19:21:53 +00003180 }
Anders Carlsson80f25672008-09-09 17:59:25 +00003181
John McCall87bb5822010-07-31 23:20:56 +00003182 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00003183}
3184
3185void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar898d5082008-09-30 01:06:03 +00003186 const ObjCAtThrowStmt &S) {
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003187 llvm::Value *ExceptionAsObject;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003188
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003189 if (const Expr *ThrowExpr = S.getThrowExpr()) {
3190 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003191 ExceptionAsObject =
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003192 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
3193 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003194 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003195 "Unexpected rethrow outside @catch block.");
Anders Carlsson273558f2009-02-07 21:37:21 +00003196 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003197 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003198
John McCallf1549f62010-07-06 01:34:17 +00003199 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3200 ->setDoesNotReturn();
Anders Carlsson80f25672008-09-09 17:59:25 +00003201 CGF.Builder.CreateUnreachable();
Daniel Dunbara448fb22008-11-11 23:11:34 +00003202
3203 // Clear the insertion point to indicate we are in unreachable code.
3204 CGF.Builder.ClearInsertionPoint();
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00003205}
3206
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003207/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00003208/// object: objc_read_weak (id *src)
3209///
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003210llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00003211 llvm::Value *AddrWeakObj) {
Eli Friedman8339b352009-03-07 03:57:15 +00003212 const llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003213 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3214 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3215 ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00003216 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003217 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00003218 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00003219 return read_weak;
3220}
3221
Fariborz Jahanian3e283e32008-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 Stump1eb44332009-09-09 15:08:12 +00003226 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003227 const llvm::Type * SrcTy = src->getType();
3228 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003229 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00003232 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003233 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3234 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003235 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3236 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00003237 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003238 src, dst, "weakassign");
3239 return;
3240}
3241
Fariborz Jahanian58626502008-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 Jahanian021a7a62010-07-20 20:30:03 +00003246 llvm::Value *src, llvm::Value *dst,
3247 bool threadlocal) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003248 const llvm::Type * SrcTy = src->getType();
3249 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003250 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00003253 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003254 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3255 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003256 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3257 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-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 Jahanian58626502008-11-19 00:59:10 +00003264 return;
3265}
3266
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003267/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003268/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003269///
3270void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003271 llvm::Value *src, llvm::Value *dst,
3272 llvm::Value *ivarOffset) {
3273 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003274 const llvm::Type * SrcTy = src->getType();
3275 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003276 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00003279 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003280 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3281 }
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003282 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3283 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003284 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3285 src, dst, ivarOffset);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003286 return;
3287}
3288
Fariborz Jahanian58626502008-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 Stump1eb44332009-09-09 15:08:12 +00003293 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003294 const llvm::Type * SrcTy = src->getType();
3295 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003296 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00003299 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003300 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3301 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003302 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3303 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00003304 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian58626502008-11-19 00:59:10 +00003305 src, dst, "weakassign");
3306 return;
3307}
3308
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003309void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003310 llvm::Value *DestPtr,
3311 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00003312 llvm::Value *size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003313 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3314 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003315 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00003316 DestPtr, SrcPtr, size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003317 return;
3318}
3319
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00003320/// EmitObjCValueForIvar - Code Gen for ivar reference.
3321///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00003322LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3323 QualType ObjectTy,
3324 llvm::Value *BaseValue,
3325 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00003326 unsigned CVRQualifiers) {
John McCallc12c5bb2010-05-15 11:32:37 +00003327 const ObjCInterfaceDecl *ID =
3328 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar97776872009-04-22 07:32:20 +00003329 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3330 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00003331}
3332
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003333llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00003334 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003335 const ObjCIvarDecl *Ivar) {
Daniel Dunbar97776872009-04-22 07:32:20 +00003336 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003337 return llvm::ConstantInt::get(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003338 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3339 Offset);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003340}
3341
Daniel Dunbarf77ac862008-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 Dunbarfce176b2010-04-25 20:39:01 +00003353 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003354 eImageInfo_GarbageCollected = (1 << 1),
3355 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003356 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
3357
Daniel Dunbarfce176b2010-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 Dunbarc7c6dc02009-04-20 07:11:47 +00003360 eImageInfo_CorrectedSynthesize = (1 << 4)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003361};
3362
Daniel Dunbarfce176b2010-04-25 20:39:01 +00003363void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbarf77ac862008-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 Dunbar6bff2512009-08-03 17:06:42 +00003372
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003373 // We never allow @synthesize of a superclass property.
3374 flags |= eImageInfo_CorrectedSynthesize;
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003375
Chris Lattner77b89b82010-06-27 07:15:29 +00003376 const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
3377
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003378 // Emitted as int[2];
3379 llvm::Constant *values[2] = {
Chris Lattner77b89b82010-06-27 07:15:29 +00003380 llvm::ConstantInt::get(Int32Ty, version),
3381 llvm::ConstantInt::get(Int32Ty, flags)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003382 };
Chris Lattner77b89b82010-06-27 07:15:29 +00003383 llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
Daniel Dunbar63c5b502009-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 Dunbar6bff2512009-08-03 17:06:42 +00003390 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003391 CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
Owen Anderson7db6d832009-07-28 18:33:04 +00003392 llvm::ConstantArray::get(AT, values, 2),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003393 Section,
3394 0,
3395 true);
3396 GV->setConstant(true);
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003397}
3398
Daniel Dunbar4e2d7d02008-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 Sands9408c452009-05-09 07:08:47 +00003411 uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003412
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003413 std::vector<llvm::Constant*> Values(4);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003414 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
3415 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00003416 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003417 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003418 Values[3] = EmitModuleSymbols();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003419 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson08e25242009-07-27 22:29:56 +00003420 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003421 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00003422 4, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003423}
3424
3425llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003426 unsigned NumClasses = DefinedClasses.size();
3427 unsigned NumCategories = DefinedCategories.size();
3428
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003429 // Return null if no symbols were defined.
3430 if (!NumClasses && !NumCategories)
Owen Andersonc9c88b42009-07-31 20:28:54 +00003431 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003432
3433 std::vector<llvm::Constant*> Values(5);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003434 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Andersonc9c88b42009-07-31 20:28:54 +00003435 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003436 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3437 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003438
Daniel Dunbar86e253a2008-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 Dunbar27f9d772008-08-21 04:36:09 +00003441 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003442 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00003443 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003444 ObjCTypes.Int8PtrTy);
3445 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003446 Symbols[NumClasses + i] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003447 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003448 ObjCTypes.Int8PtrTy);
3449
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003450 Values[4] =
Owen Anderson96e0fc72009-07-29 22:16:19 +00003451 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003452 NumClasses + NumCategories),
3453 Symbols);
3454
Nick Lewycky0d36dd22009-09-19 20:00:52 +00003455 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003456
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003457 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003458 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3459 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003460 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00003461 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003462}
3463
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003464llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003465 const ObjCInterfaceDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003466 LazySymbols.insert(ID->getIdentifier());
3467
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003468 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003469
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003470 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003471 llvm::Constant *Casted =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003472 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003473 ObjCTypes.ClassPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003474 Entry =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003475 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3476 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003477 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003478 }
3479
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00003480 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003481}
3482
Fariborz Jahanian03b29602010-06-17 19:56:20 +00003483llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
3484 bool lvalue) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003485 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003486
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003487 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003488 llvm::Constant *Casted =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003489 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003490 ObjCTypes.SelectorPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003491 Entry =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003492 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3493 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003494 4, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003495 }
3496
Fariborz Jahanian03b29602010-06-17 19:56:20 +00003497 if (lvalue)
3498 return Entry;
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00003499 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003500}
3501
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00003502llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003503 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003504
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003505 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003506 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003507 llvm::ConstantArray::get(VMContext,
3508 Ident->getNameStart()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003509 ((ObjCABI == 2) ?
3510 "__TEXT,__objc_classname,cstring_literals" :
3511 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003512 1, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003513
Owen Andersona1cf15f2009-07-14 23:10:40 +00003514 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003515}
3516
Argyrios Kyrtzidis9d50c062010-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 Jahaniand80d81b2009-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 Dunbar6bff2512009-08-03 17:06:42 +00003536 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Andersonc9c88b42009-07-31 20:28:54 +00003537 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +00003538}
3539
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003540void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003541 unsigned int BytePos,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003542 bool ForStrongLayout,
3543 bool &HasUnion) {
3544 const RecordDecl *RD = RT->getDecl();
3545 // FIXME - Use iterator.
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00003546 llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003547 const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003548 const llvm::StructLayout *RecLayout =
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003549 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003550
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003551 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3552 ForStrongLayout, HasUnion);
3553}
3554
Daniel Dunbar5a5a8032009-05-03 21:05:10 +00003555void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003556 const llvm::StructLayout *Layout,
3557 const RecordDecl *RD,
Chris Lattnerf1690852009-03-31 08:48:01 +00003558 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003559 unsigned int BytePos, bool ForStrongLayout,
3560 bool &HasUnion) {
Fariborz Jahanian820e0202009-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 Kyrtzidis0dc75092010-09-06 12:00:10 +00003566 FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003567 uint64_t MaxFieldOffset = 0;
3568 uint64_t MaxSkippedFieldOffset = 0;
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003569 uint64_t LastBitfieldOrUnnamedOffset = 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003570
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003571 if (RecFields.empty())
3572 return;
Chris Lattnerf1690852009-03-31 08:48:01 +00003573 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3574 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3575
Chris Lattnerf1690852009-03-31 08:48:01 +00003576 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003577 FieldDecl *Field = RecFields[i];
Daniel Dunbare05cc982009-05-03 23:35:23 +00003578 uint64_t FieldOffset;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00003579 if (RD) {
Daniel Dunbarf8f8eba2010-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 Dyckfb67ccd2011-04-14 00:43:09 +00003583 FieldOffset = RL.getFieldOffset(i) / ByteSizeInBits;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00003584 } else
Daniel Dunbare05cc982009-05-03 23:35:23 +00003585 FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003586
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003587 // Skip over unnamed or bitfields
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003588 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003589 LastFieldBitfieldOrUnnamed = Field;
3590 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003591 continue;
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003592 }
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003593
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003594 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003595 QualType FQT = Field->getType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003596 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003597 if (FQT->isUnionType())
3598 HasUnion = true;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003599
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003600 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003601 BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003602 ForStrongLayout, HasUnion);
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003603 continue;
3604 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003605
Chris Lattnerf1690852009-03-31 08:48:01 +00003606 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003607 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003608 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003609 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003610 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003611 FQT = CArray->getElementType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003612 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3613 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003614 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003615 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003616 FQT = CArray->getElementType();
3617 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003618
3619 assert(!FQT->isUnionType() &&
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003620 "layout for array of unions not supported");
Fariborz Jahanianf96bdf42011-01-03 19:23:18 +00003621 if (FQT->isRecordType() && ElCount) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003622 int OldIndex = IvarsInfo.size() - 1;
3623 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003624
Ted Kremenek6217b802009-07-29 21:53:49 +00003625 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003626 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003627 ForStrongLayout, HasUnion);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003628
Fariborz Jahanian820e0202009-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 Dunbar6bff2512009-08-03 17:06:42 +00003632 for (int FirstIndex = IvarsInfo.size() - 1,
3633 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003634 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar8b2926c2009-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 Jahanian820e0202009-03-11 00:07:04 +00003641 }
3642 continue;
3643 }
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003644 }
Fariborz Jahanian820e0202009-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 McCall0953e762009-09-24 19:53:00 +00003647 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003648
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003649 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall0953e762009-09-24 19:53:00 +00003650 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3651 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00003652 if (IsUnion) {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003653 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar487993b2009-05-03 13:32:01 +00003654 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003655 MaxUnionIvarSize = UnionIvarSize;
3656 MaxField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003657 MaxFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003658 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00003659 } else {
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003660 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003661 FieldSize / WordSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003662 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003663 } else if ((ForStrongLayout &&
John McCall0953e762009-09-24 19:53:00 +00003664 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3665 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00003666 if (IsUnion) {
Mike Stumpf5408fe2009-05-16 07:57:57 +00003667 // FIXME: Why the asymmetry? We divide by word size in bits on other
3668 // side.
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003669 uint64_t UnionIvarSize = FieldSize;
Daniel Dunbar487993b2009-05-03 13:32:01 +00003670 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003671 MaxSkippedUnionIvarSize = UnionIvarSize;
3672 MaxSkippedField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003673 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003674 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00003675 } else {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003676 // FIXME: Why the asymmetry, we divide by byte size in bits here?
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003677 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003678 FieldSize / ByteSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003679 }
3680 }
3681 }
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003682
Argyrios Kyrtzidis0dc75092010-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 Jahanian7fb16272009-04-21 18:33:06 +00003702 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003703
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003704 if (MaxField)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003705 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003706 MaxUnionIvarSize));
3707 if (MaxSkippedField)
Daniel Dunbar900c1982009-05-03 23:31:46 +00003708 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003709 MaxSkippedUnionIvarSize));
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00003710}
3711
Fariborz Jahanianb8fd2eb2010-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 Jahanian9397e1d2009-03-11 20:59:05 +00003718 unsigned int WordsToScan, WordsToSkip;
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00003719 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003720
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003721 // Build the string of skip/scan nibbles
Fariborz Jahanian8c2f2d12009-04-24 17:15:27 +00003722 llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003723 unsigned int WordSize =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003724 CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003725 if (IvarsInfo[0].ivar_bytepos == 0) {
3726 WordsToSkip = 0;
3727 WordsToScan = IvarsInfo[0].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003728 } else {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003729 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3730 WordsToScan = IvarsInfo[0].ivar_size;
3731 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003732 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003733 unsigned int TailPrevGCObjC =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003734 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003735 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003736 // consecutive 'scanned' object pointers.
3737 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003738 } else {
Fariborz Jahanian9397e1d2009-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 Jahanianc8ce9c82009-03-12 22:50:49 +00003744 SKIP_SCAN SkScan;
3745 SkScan.skip = WordsToSkip;
3746 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003747 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003748
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003749 // Skip the hole.
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003750 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3751 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003752 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003753 WordsToSkip = 0;
3754 WordsToScan = IvarsInfo[i].ivar_size;
3755 }
3756 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003757 if (WordsToScan > 0) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003758 SKIP_SCAN SkScan;
3759 SkScan.skip = WordsToSkip;
3760 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003761 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003762 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003763
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003764 if (!SkipIvars.empty()) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003765 unsigned int LastIndex = SkipIvars.size()-1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003766 int LastByteSkipped =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003767 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003768 LastIndex = IvarsInfo.size()-1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003769 int LastByteScanned =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003770 IvarsInfo[LastIndex].ivar_bytepos +
3771 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003772 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramer54d76db2009-12-25 15:43:36 +00003773 if (LastByteSkipped > LastByteScanned) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003774 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003775 SKIP_SCAN SkScan;
3776 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3777 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003778 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-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 Jahanian81adc052009-04-24 16:17:09 +00003783 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003784 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-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 Jahanian93ce50d2010-08-04 23:55:24 +00003794
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003795 // Generate the string.
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003796 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-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 Jahanian93ce50d2010-08-04 23:55:24 +00003802
Fariborz Jahanian9397e1d2009-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 Jahanian93ce50d2010-08-04 23:55:24 +00003806
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003807 // next (skip small, scan)
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003808 if (skip_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003809 byte = skip_small << 4;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003810 if (scan_big > 0) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003811 byte |= 0xf;
3812 --scan_big;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003813 } else if (scan_small) {
Fariborz Jahanian9397e1d2009-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 Dunbar31682fd2009-05-03 23:21:22 +00003823 if (scan_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003824 byte = scan_small;
3825 BitMap += byte;
3826 }
3827 }
3828 // null terminate string.
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003829 unsigned char zero = 0;
3830 BitMap += zero;
Fariborz Jahanian93ce50d2010-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 Dunbaraf19ac42011-03-25 20:09:09 +00003835 ((ObjCABI == 2) ?
3836 "__TEXT,__objc_classname,cstring_literals" :
3837 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003838 1, true);
3839 return getConstantGEP(VMContext, Entry, 0, 0);
3840}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003841
Fariborz Jahanian93ce50d2010-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 Jahanian2c18bb72010-08-20 21:21:08 +00003867 llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003868 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
Fariborz Jahanian2c18bb72010-08-20 21:21:08 +00003869 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003870
Fariborz Jahanian2c18bb72010-08-20 21:21:08 +00003871 llvm::SmallVector<FieldDecl*, 32> RecFields;
Fariborz Jahanian93ce50d2010-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 Jahanianb8fd2eb2010-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 Jahanian93ce50d2010-08-04 23:55:24 +00003891 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00003892 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003893
3894 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003895 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian3d2ad662009-04-20 22:03:45 +00003896 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar4087f272010-08-17 22:39:59 +00003897 OMD->getClassInterface()->getName().data());
Fariborz Jahanian3d2ad662009-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 Jahanian93ce50d2010-08-04 23:55:24 +00003906 return C;
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00003907}
3908
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003909llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003910 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3911
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003912 // FIXME: Avoid std::string copying.
3913 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003914 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Owen Anderson0032b272009-08-13 21:57:51 +00003915 llvm::ConstantArray::get(VMContext, Sel.getAsString()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003916 ((ObjCABI == 2) ?
3917 "__TEXT,__objc_methname,cstring_literals" :
3918 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003919 1, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003920
Owen Andersona1cf15f2009-07-14 23:10:40 +00003921 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003922}
3923
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003924// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003925llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003926 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
3927}
3928
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00003929llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel7794bb82009-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 Dunbar6efc0c52008-08-13 03:21:16 +00003934
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003935 if (!Entry)
3936 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson0032b272009-08-13 21:57:51 +00003937 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003938 ((ObjCABI == 2) ?
3939 "__TEXT,__objc_methtype,cstring_literals" :
3940 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003941 1, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003942
Owen Andersona1cf15f2009-07-14 23:10:40 +00003943 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003944}
3945
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003946llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003947 std::string TypeStr;
Douglas Gregorf968d832011-05-27 01:19:52 +00003948 if (CGM.getContext().getObjCEncodingForMethodDecl(
3949 const_cast<ObjCMethodDecl*>(D),
3950 TypeStr))
3951 return 0;
Devang Patel7794bb82009-03-04 18:21:39 +00003952
3953 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3954
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003955 if (!Entry)
3956 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson0032b272009-08-13 21:57:51 +00003957 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003958 ((ObjCABI == 2) ?
3959 "__TEXT,__objc_methtype,cstring_literals" :
3960 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003961 1, true);
Devang Patel7794bb82009-03-04 18:21:39 +00003962
Owen Andersona1cf15f2009-07-14 23:10:40 +00003963 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003964}
3965
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003966// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003967llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003968 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003969
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003970 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003971 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003972 llvm::ConstantArray::get(VMContext,
3973 Ident->getNameStart()),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003974 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003975 1, true);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003976
Owen Andersona1cf15f2009-07-14 23:10:40 +00003977 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003978}
3979
3980// FIXME: Merge into a single cstring creation function.
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00003981// FIXME: This Decl should be more precise.
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003982llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003983CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
3984 const Decl *Container) {
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00003985 std::string TypeStr;
3986 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003987 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
3988}
3989
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003990void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003991 const ObjCContainerDecl *CD,
Daniel Dunbarc575ce72009-10-19 01:21:19 +00003992 llvm::SmallVectorImpl<char> &Name) {
3993 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian679a5022009-01-10 21:06:09 +00003994 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbarc575ce72009-10-19 01:21:19 +00003995 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
3996 << '[' << CD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003997 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbarc575ce72009-10-19 01:21:19 +00003998 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer900fc632010-04-17 09:33:03 +00003999 OS << '(' << CID << ')';
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004000 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00004001}
4002
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004003void CGObjCMac::FinishModule() {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004004 EmitModuleInfo();
4005
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004006 // Emit the dummy bodies for any protocols which were referenced but
4007 // never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004008 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerad64e022009-07-17 23:57:13 +00004009 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4010 if (I->second->hasInitializer())
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004011 continue;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004012
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004013 std::vector<llvm::Constant*> Values(5);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004014 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004015 Values[1] = GetClassName(I->first);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004016 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004017 Values[3] = Values[4] =
Owen Andersonc9c88b42009-07-31 20:28:54 +00004018 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004019 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson08e25242009-07-27 22:29:56 +00004020 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004021 Values));
Chris Lattnerad64e022009-07-17 23:57:13 +00004022 CGM.AddUsedGlobal(I->second);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004023 }
4024
Daniel Dunbar242d4dc2008-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 Dunbar33063492009-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 Dunbar242d4dc2008-08-25 06:02:07 +00004035
Daniel Dunbar33063492009-09-07 00:20:42 +00004036 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbar33063492009-09-07 00:20:42 +00004037 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4038 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar01eb9b92009-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 Lattnerafd5eda2010-04-17 18:26:20 +00004041 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004042 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004043 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanianb9c5b3d2010-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 Lattnerafd5eda2010-04-17 18:26:20 +00004050
Daniel Dunbar33063492009-09-07 00:20:42 +00004051 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004052 }
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004053}
4054
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004055CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004056 : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00004057 ObjCTypes(cgm) {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004058 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004059 ObjCABI = 2;
4060}
4061
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004062/* *** */
4063
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004064ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004065 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004066 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4067 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004068
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004069 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004070 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004071 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004072 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00004073 Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004074
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004075 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00004076 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004077 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004078
Mike Stumpf5408fe2009-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 Dunbar6efc0c52008-08-13 03:21:16 +00004081 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00004082 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004083
Fariborz Jahanianee0af742009-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 Dunbar6bff2512009-08-03 17:06:42 +00004088
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004089 // FIXME: This is leaked.
4090 // FIXME: Merge with rewriter code?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004091
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004092 // struct _objc_super {
4093 // id self;
4094 // Class cls;
4095 // }
Abramo Bagnara465d41b2010-05-11 21:36:43 +00004096 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00004097 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00004098 SourceLocation(), SourceLocation(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004099 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004100 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith7a614d82011-06-11 17:19:42 +00004101 Ctx.getObjCIdType(), 0, 0, false, false));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004102 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith7a614d82011-06-11 17:19:42 +00004103 Ctx.getObjCClassType(), 0, 0, false, false));
Douglas Gregor838db382010-02-11 01:19:42 +00004104 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004105
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004106 SuperCTy = Ctx.getTagDeclType(RD);
4107 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004108
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004109 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004110 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4111
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004112 // struct _prop_t {
4113 // char *name;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004114 // char *attributes;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004115 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004116 PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004117 CGM.getModule().addTypeName("struct._prop_t",
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004118 PropertyTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004119
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004120 // struct _prop_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004121 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004122 // uint32_t count_of_properties;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004123 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004124 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004125 PropertyListTy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004126 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004127 llvm::ArrayType::get(PropertyTy, 0),
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004128 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004129 CGM.getModule().addTypeName("struct._prop_list_t",
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004130 PropertyListTy);
4131 // struct _prop_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004132 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004133
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004134 // struct _objc_method {
4135 // SEL _cmd;
4136 // char *method_type;
4137 // char *_imp;
4138 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004139 MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004140 Int8PtrTy,
4141 Int8PtrTy,
4142 NULL);
4143 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004144
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004145 // struct _objc_cache *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004146 CacheTy = llvm::OpaqueType::get(VMContext);
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004147 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004148 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004149}
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004150
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004151ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004152 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004153 // struct _objc_method_description {
4154 // SEL name;
4155 // char *types;
4156 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004157 MethodDescriptionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004158 llvm::StructType::get(VMContext, SelectorPtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004159 Int8PtrTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004160 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004161 CGM.getModule().addTypeName("struct._objc_method_description",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004162 MethodDescriptionTy);
4163
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004164 // struct _objc_method_description_list {
4165 // int count;
4166 // struct _objc_method_description[1];
4167 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004168 MethodDescriptionListTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004169 llvm::StructType::get(VMContext, IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004170 llvm::ArrayType::get(MethodDescriptionTy, 0),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004171 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004172 CGM.getModule().addTypeName("struct._objc_method_description_list",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004173 MethodDescriptionListTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004174
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004175 // struct _objc_method_description_list *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004176 MethodDescriptionListPtrTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004177 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004178
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004179 // Protocol description structures
4180
Fariborz Jahanian10a42312009-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 Dunbar6bff2512009-08-03 17:06:42 +00004187 ProtocolExtensionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004188 llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004189 MethodDescriptionListPtrTy,
4190 MethodDescriptionListPtrTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004191 PropertyListPtrTy,
4192 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004193 CGM.getModule().addTypeName("struct._objc_protocol_extension",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004194 ProtocolExtensionTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004195
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004196 // struct _objc_protocol_extension *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004197 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004198
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004199 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004200
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004201 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
4202 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004203
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004204 const llvm::Type *T =
Mike Stump1eb44332009-09-09 15:08:12 +00004205 llvm::StructType::get(VMContext,
Owen Anderson47a434f2009-08-05 23:18:46 +00004206 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004207 LongTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004208 llvm::ArrayType::get(ProtocolTyHolder, 0),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004209 NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004210 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
4211
Fariborz Jahanian10a42312009-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 Anderson47a434f2009-08-05 23:18:46 +00004219 T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004220 Int8PtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004221 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Daniel Dunbar6efc0c52008-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 Dunbar6bff2512009-08-03 17:06:42 +00004228 CGM.getModule().addTypeName("struct._objc_protocol_list",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004229 ProtocolListTy);
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004230 // struct _objc_protocol_list *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004231 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004232
4233 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004234 CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004235 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004236
4237 // Class description structures
4238
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004239 // struct _objc_ivar {
4240 // char *ivar_name;
4241 // char *ivar_type;
4242 // int ivar_offset;
4243 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004244 IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004245 Int8PtrTy,
4246 IntTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004247 NULL);
4248 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
4249
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004250 // struct _objc_ivar_list *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004251 IvarListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004252 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004253 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004254
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004255 // struct _objc_method_list *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004256 MethodListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004257 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004258 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004259
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004260 // struct _objc_class_extension *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004261 ClassExtensionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004262 llvm::StructType::get(VMContext, IntTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004263 Int8PtrTy,
4264 PropertyListPtrTy,
4265 NULL);
4266 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004267 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004268
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004269 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004270
Fariborz Jahanian10a42312009-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 Anderson47a434f2009-08-05 23:18:46 +00004285 T = llvm::StructType::get(VMContext,
4286 llvm::PointerType::getUnqual(ClassTyHolder),
Owen Anderson96e0fc72009-07-29 22:16:19 +00004287 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar27f9d772008-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 Dunbar6bff2512009-08-03 17:06:42 +00004300
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004301 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
4302 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004303 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004304
Fariborz Jahanian10a42312009-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 Anderson47a434f2009-08-05 23:18:46 +00004313 CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar86e253a2008-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 Dunbar27f9d772008-08-21 04:36:09 +00004323 // Global metadata structures
4324
Fariborz Jahanian10a42312009-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 Anderson47a434f2009-08-05 23:18:46 +00004332 SymtabTy = llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004333 SelectorPtrTy,
4334 ShortTy,
4335 ShortTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004336 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004337 NULL);
4338 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004339 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004340
Fariborz Jahaniandb286862009-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 Dunbar6bff2512009-08-03 17:06:42 +00004347 ModuleTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004348 llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004349 LongTy,
4350 Int8PtrTy,
4351 SymtabPtrTy,
4352 NULL);
4353 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00004354
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004355
Mike Stumpf5408fe2009-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 Carlsson124526b2008-09-09 10:10:21 +00004358 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004359
Anders Carlsson124526b2008-09-09 10:10:21 +00004360 // Exceptions
Owen Anderson96e0fc72009-07-29 22:16:19 +00004361 const llvm::Type *StackPtrTy = llvm::ArrayType::get(
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00004362 llvm::Type::getInt8PtrTy(VMContext), 4);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004363
4364 ExceptionDataTy =
Chris Lattner77b89b82010-06-27 07:15:29 +00004365 llvm::StructType::get(VMContext,
4366 llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
4367 SetJmpBufferSize),
Anders Carlsson124526b2008-09-09 10:10:21 +00004368 StackPtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004369 CGM.getModule().addTypeName("struct._objc_exception_data",
Anders Carlsson124526b2008-09-09 10:10:21 +00004370 ExceptionDataTy);
4371
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00004372}
4373
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004374ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004375 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian30bc5712009-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 Anderson47a434f2009-08-05 23:18:46 +00004381 MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004382 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004383 llvm::ArrayType::get(MethodTy, 0),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004384 NULL);
4385 CGM.getModule().addTypeName("struct.__method_list_t",
4386 MethodListnfABITy);
4387 // struct method_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004388 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004389
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004390 // struct _protocol_t {
4391 // id isa; // NULL
4392 // const char * const protocol_name;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004393 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanian30bc5712009-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 Jahaniand55b6fc2009-01-23 01:46:23 +00004398 // const struct _prop_list_t * properties;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004399 // const uint32_t size; // sizeof(struct _protocol_t)
4400 // const uint32_t flags; // = 0
4401 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004402
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004403 // Holder for struct _protocol_list_t *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004404 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004405
Owen Anderson47a434f2009-08-05 23:18:46 +00004406 ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004407 Int8PtrTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004408 llvm::PointerType::getUnqual(
Fariborz Jahaniand55b6fc2009-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 Dunbar948e2582009-02-15 07:36:20 +00004420
4421 // struct _protocol_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004422 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004423
Fariborz Jahanianda320092009-01-29 19:24:30 +00004424 // struct _protocol_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004425 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar948e2582009-02-15 07:36:20 +00004426 // struct _protocol_t *[protocol_count];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004427 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004428 ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004429 llvm::ArrayType::get(
Daniel Dunbar948e2582009-02-15 07:36:20 +00004430 ProtocolnfABIPtrTy, 0),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004431 NULL);
4432 CGM.getModule().addTypeName("struct._objc_protocol_list",
4433 ProtocolListnfABITy);
Daniel Dunbar948e2582009-02-15 07:36:20 +00004434 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004435 ProtocolListnfABITy);
4436
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004437 // struct _objc_protocol_list*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004438 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004439
Fariborz Jahanian30bc5712009-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 Stump1eb44332009-09-09 15:08:12 +00004447 IvarnfABITy = llvm::StructType::get(VMContext,
Owen Anderson47a434f2009-08-05 23:18:46 +00004448 llvm::PointerType::getUnqual(LongTy),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004449 Int8PtrTy,
4450 Int8PtrTy,
4451 IntTy,
4452 IntTy,
4453 NULL);
4454 CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004455
Fariborz Jahanian30bc5712009-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 Anderson47a434f2009-08-05 23:18:46 +00004461 IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004462 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004463 llvm::ArrayType::get(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004464 IvarnfABITy, 0),
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004465 NULL);
4466 CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004467
Owen Anderson96e0fc72009-07-29 22:16:19 +00004468 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004469
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004470 // struct _class_ro_t {
Fariborz Jahanian30bc5712009-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 Dunbar6bff2512009-08-03 17:06:42 +00004483
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004484 // FIXME. Add 'reserved' field in 64bit abi mode!
Owen Anderson47a434f2009-08-05 23:18:46 +00004485 ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahaniand55b6fc2009-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 Dunbar6bff2512009-08-03 17:06:42 +00004498
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004499 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
John McCall0774cb82011-05-15 01:53:33 +00004500 const llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
4501 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
4502 ->getPointerTo();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004503
Fariborz Jahaniand55b6fc2009-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 Dunbar6bff2512009-08-03 17:06:42 +00004511
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004512 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Owen Andersona1cf15f2009-07-14 23:10:40 +00004513 ClassnfABITy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004514 llvm::StructType::get(VMContext,
4515 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar6bff2512009-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 Jahaniand55b6fc2009-01-23 01:46:23 +00004521 CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
4522
4523 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004524 ClassnfABITy);
4525
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004526 // LLVM for struct _class_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004527 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004528
Fariborz Jahaniand55b6fc2009-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 Jahanian45c2ba02009-01-23 17:41:22 +00004536 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004537 CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004538 ClassnfABIPtrTy,
Fariborz Jahanian45c2ba02009-01-23 17:41:22 +00004539 MethodListnfABIPtrTy,
4540 MethodListnfABIPtrTy,
4541 ProtocolListnfABIPtrTy,
4542 PropertyListPtrTy,
4543 NULL);
4544 CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004545
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004546 // New types for nonfragile abi messaging.
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004547 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4548 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004549
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004550 // MessageRefTy - LLVM for:
4551 // struct _message_ref_t {
4552 // IMP messenger;
4553 // SEL name;
4554 // };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004555
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004556 // First the clang type for struct _message_ref_t
Abramo Bagnara465d41b2010-05-11 21:36:43 +00004557 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00004558 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00004559 SourceLocation(), SourceLocation(),
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004560 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004561 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith7a614d82011-06-11 17:19:42 +00004562 Ctx.VoidPtrTy, 0, 0, false, false));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004563 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith7a614d82011-06-11 17:19:42 +00004564 Ctx.getObjCSelType(), 0, 0, false, false));
Douglas Gregor838db382010-02-11 01:19:42 +00004565 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004566
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004567 MessageRefCTy = Ctx.getTagDeclType(RD);
4568 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4569 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004570
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004571 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004572 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004573
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004574 // SuperMessageRefTy - LLVM for:
4575 // struct _super_message_ref_t {
4576 // SUPER_IMP messenger;
4577 // SEL name;
4578 // };
Owen Anderson47a434f2009-08-05 23:18:46 +00004579 SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004580 SelectorPtrTy,
4581 NULL);
4582 CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004583
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004584 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004585 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
4586
Daniel Dunbare588b992009-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 Anderson47a434f2009-08-05 23:18:46 +00004593 EHTypeTy = llvm::StructType::get(VMContext,
4594 llvm::PointerType::getUnqual(Int8PtrTy),
Daniel Dunbare588b992009-03-01 04:46:24 +00004595 Int8PtrTy,
4596 ClassnfABIPtrTy,
4597 NULL);
Daniel Dunbar4ff36842009-03-02 06:08:11 +00004598 CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004599 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00004600}
4601
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004602llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004603 FinishNonFragileABIModule();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004604
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004605 return NULL;
4606}
4607
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004608void CGObjCNonFragileABIMac::AddModuleClassList(const
4609 std::vector<llvm::GlobalValue*>
4610 &Container,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004611 const char *SymbolName,
4612 const char *SectionName) {
4613 unsigned NumClasses = Container.size();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004614
Daniel Dunbar463b8762009-05-15 21:48:48 +00004615 if (!NumClasses)
4616 return;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004617
Daniel Dunbar463b8762009-05-15 21:48:48 +00004618 std::vector<llvm::Constant*> Symbols(NumClasses);
4619 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00004620 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar463b8762009-05-15 21:48:48 +00004621 ObjCTypes.Int8PtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004622 llvm::Constant* Init =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004623 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004624 NumClasses),
4625 Symbols);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004626
Daniel Dunbar463b8762009-05-15 21:48:48 +00004627 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00004628 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004629 llvm::GlobalValue::InternalLinkage,
4630 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00004631 SymbolName);
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004632 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Daniel Dunbar463b8762009-05-15 21:48:48 +00004633 GV->setSection(SectionName);
Chris Lattnerad64e022009-07-17 23:57:13 +00004634 CGM.AddUsedGlobal(GV);
Daniel Dunbar463b8762009-05-15 21:48:48 +00004635}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004636
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004637void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4638 // nonfragile abi has no module definition.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004639
Daniel Dunbar463b8762009-05-15 21:48:48 +00004640 // Build list of all implemented class addresses in array
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00004641 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004642 AddModuleClassList(DefinedClasses,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004643 "\01L_OBJC_LABEL_CLASS_$",
4644 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004645
Fariborz Jahaniana03d0dd2009-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 Jahaniana03d0dd2009-11-17 21:37:35 +00004651 }
4652
Fariborz Jahanian0e93d252009-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 Jahaniana03d0dd2009-11-17 21:37:35 +00004659
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004660 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004661 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4662 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004663
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00004664 // Build list of all implemented category addresses in array
4665 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004666 AddModuleClassList(DefinedCategories,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004667 "\01L_OBJC_LABEL_CATEGORY_$",
4668 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004669 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004670 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4671 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004672
Daniel Dunbarfce176b2010-04-25 20:39:01 +00004673 EmitImageInfo();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004674}
4675
John McCall944c8432011-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 Dunbar6bff2512009-08-03 17:06:42 +00004678/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004679/// message dispatch call for all the rest.
John McCall944c8432011-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 Dunbarf643b9b2010-04-24 17:56:46 +00004683 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
4684 default:
John McCall944c8432011-05-14 03:10:52 +00004685 llvm_unreachable("Invalid dispatch method!");
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004686 case CodeGenOptions::Legacy:
Fariborz Jahanian776dbf92010-04-19 17:53:30 +00004687 return false;
John McCall944c8432011-05-14 03:10:52 +00004688 case CodeGenOptions::NonLegacy:
4689 return true;
Daniel Dunbarf643b9b2010-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 McCall944c8432011-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 Dunbar6bff2512009-08-03 17:06:42 +00004703
John McCall944c8432011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +00004735 }
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004736
John McCall944c8432011-05-14 03:10:52 +00004737 return VTableDispatchMethods.count(Sel);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004738}
4739
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004740// Metadata flags
4741enum MetaDataDlags {
4742 CLS = 0x0,
4743 CLS_META = 0x1,
4744 CLS_ROOT = 0x2,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004745 OBJC2_CLS_HIDDEN = 0x10,
Fariborz Jahanian058a1b72009-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 Jahanianda320092009-01-29 19:24:30 +00004757/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian058a1b72009-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 Dunbar6bff2512009-08-03 17:06:42 +00004764 unsigned flags,
4765 unsigned InstanceStart,
4766 unsigned InstanceSize,
4767 const ObjCImplementationDecl *ID) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004768 std::string ClassName = ID->getNameAsString();
4769 std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
Owen Anderson4a28d5d2009-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 Jahanian058a1b72009-01-24 20:21:50 +00004773 // FIXME. For 64bit targets add 0 here.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004774 Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4775 : BuildIvarLayout(ID, true);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004776 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian493dab72009-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 Dunbar6bff2512009-08-03 17:06:42 +00004782 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004783 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-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 Dunbar6bff2512009-08-03 17:06:42 +00004789 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004790 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004791 // Instance methods should always be defined.
4792 Methods.push_back(GetMethodConstant(*i));
4793 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004794 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004795 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004796 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004797
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004798 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4799 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004800
Fariborz Jahanian939abce2009-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 Jahanian493dab72009-01-26 21:38:32 +00004809 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004810 Values[ 5] = EmitMethodList(MethodListName,
4811 "__DATA, __objc_const", Methods);
4812
Fariborz Jahanianda320092009-01-29 19:24:30 +00004813 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4814 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004815 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004816 + OID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00004817 OID->all_referenced_protocol_begin(),
4818 OID->all_referenced_protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004819
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00004820 if (flags & CLS_META)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004821 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00004822 else
4823 Values[ 7] = EmitIvarList(ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004824 Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4825 : BuildIvarLayout(ID, false);
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00004826 if (flags & CLS_META)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004827 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00004828 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004829 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4830 ID, ID->getClassInterface(), ObjCTypes);
Owen Anderson08e25242009-07-27 22:29:56 +00004831 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004832 Values);
4833 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar6bff2512009-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 Jahanian09796d62009-01-31 02:43:27 +00004840 CLASS_RO_GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004841 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00004842 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004843 return CLASS_RO_GV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00004844
Fariborz Jahanian058a1b72009-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 Jahanian84394a52009-01-24 21:21:53 +00004857llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar6bff2512009-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 Jahanian058a1b72009-01-24 20:21:50 +00004863 std::vector<llvm::Constant*> Values(5);
4864 Values[0] = IsAGV;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004865 Values[1] = SuperClassGV;
4866 if (!Values[1])
4867 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004868 Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
4869 Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4870 Values[4] = ClassRoGV; // &CLASS_RO_GV
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004871 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004872 Values);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004873 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4874 GV->setInitializer(Init);
Fariborz Jahaniandd0db2a2009-01-31 01:07:39 +00004875 GV->setSection("__DATA, __objc_data");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00004876 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004877 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004878 if (HiddenVisibility)
4879 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004880 return GV;
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004881}
4882
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004883bool
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00004884CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004885 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004886}
4887
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00004888void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00004889 uint32_t &InstanceStart,
4890 uint32_t &InstanceSize) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004891 const ASTRecordLayout &RL =
Daniel Dunbarb4c79e02009-05-04 21:26:30 +00004892 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004893
Daniel Dunbar6e8575b2009-05-04 23:23:09 +00004894 // InstanceSize is really instance end.
Ken Dyckec299032011-02-11 02:20:09 +00004895 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar6e8575b2009-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 Dyckfb67ccd2011-04-14 00:43:09 +00004901 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbarb02532a2009-04-19 23:41:48 +00004902}
4903
Fariborz Jahanianaa23b572009-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 Dunbar6bff2512009-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 Jahanianaa23b572009-01-23 23:53:38 +00004915 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004916 CGM.getModule(),
4917 ObjCTypes.ImpnfABITy,
4918 false,
4919 llvm::GlobalValue::ExternalLinkage,
4920 0,
4921 "_objc_empty_vtable");
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004922 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004923 assert(ID->getClassInterface() &&
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004924 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbar6c1aac82009-04-20 20:18:54 +00004925 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004926 uint32_t InstanceStart =
Duncan Sands9408c452009-05-09 07:08:47 +00004927 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004928 uint32_t InstanceSize = InstanceStart;
4929 uint32_t flags = CLS_META;
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00004930 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4931 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004932
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004933 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004934
4935 bool classIsHidden =
John McCall1fb0caa2010-10-22 21:05:15 +00004936 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004937 if (classIsHidden)
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004938 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00004939 if (ID->getNumIvarInitializers())
4940 flags |= eClassFlags_ABI2_HasCXXStructors;
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004941 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004942 // class is root
4943 flags |= CLS_ROOT;
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004944 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004945 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004946 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004947 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004948 const ObjCInterfaceDecl *Root = ID->getClassInterface();
4949 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4950 Root = Super;
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004951 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004952 if (Root->isWeakImported())
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004953 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004954 // work on super class metadata symbol.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004955 std::string SuperClassName =
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004956 ObjCMetaClassName +
4957 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004958 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004959 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004960 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004961 }
4962 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4963 InstanceStart,
4964 InstanceSize,ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004965 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004966 llvm::GlobalVariable *MetaTClass =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004967 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4968 classIsHidden);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004969 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00004970
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004971 // Metadata for the class
4972 flags = CLS;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004973 if (classIsHidden)
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004974 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00004975 if (ID->getNumIvarInitializers())
4976 flags |= eClassFlags_ABI2_HasCXXStructors;
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004977
Douglas Gregor68584ed2009-06-18 16:11:24 +00004978 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004979 flags |= CLS_EXCEPTION;
4980
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004981 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004982 flags |= CLS_ROOT;
4983 SuperClassGV = 0;
Chris Lattnerb7b58b12009-04-19 06:02:28 +00004984 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004985 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004986 std::string RootClassName =
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004987 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004988 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004989 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004990 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004991 }
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00004992 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004993 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00004994 InstanceStart,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004995 InstanceSize,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00004996 ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004997
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004998 TClassName = ObjCClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004999 llvm::GlobalVariable *ClassMD =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005000 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5001 classIsHidden);
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00005002 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005003
Daniel Dunbar74d4b122009-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 Dunbar8158a2f2009-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 Jahanian64089ce2011-04-22 22:02:28 +00005011 // Make sure method definition entries are all clear for next implementation.
5012 MethodDefinitions.clear();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005013}
5014
Fariborz Jahanian8cfd3972009-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 Dunbar6bff2512009-08-03 17:06:42 +00005024 const ObjCProtocolDecl *PD) {
5025
Fariborz Jahanian960cd062009-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 Dunbar6bff2512009-08-03 17:06:42 +00005029 llvm::Constant *Init =
5030 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
5031 ObjCTypes.ExternalProtocolPtrTy);
5032
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005033 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar4087f272010-08-17 22:39:59 +00005034 ProtocolName += PD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005035
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005036 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5037 if (PTGV)
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005038 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005039 PTGV = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005040 CGM.getModule(),
5041 Init->getType(), false,
5042 llvm::GlobalValue::WeakAnyLinkage,
5043 Init,
5044 ProtocolName);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005045 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5046 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005047 CGM.AddUsedGlobal(PTGV);
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005048 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005049}
5050
Fariborz Jahanianeb062d92009-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 Dunbar74d4b122009-05-15 22:33:15 +00005061void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005062 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005063 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005064 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5065 "_$_" + OCD->getNameAsString());
5066 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005067 Interface->getNameAsString());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005068
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005069 std::vector<llvm::Constant*> Values(6);
5070 Values[0] = GetClassName(OCD->getIdentifier());
5071 // meta-class entry symbol
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005072 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005073 if (Interface->isWeakImported())
Fariborz Jahanian2cdcc4c2009-11-17 22:02:21 +00005074 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5075
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005076 Values[1] = ClassGV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005077 std::vector<llvm::Constant*> Methods;
5078 std::string MethodListName(Prefix);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005079 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005080 "_$_" + OCD->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005081
5082 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005083 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005084 // Instance methods should always be defined.
5085 Methods.push_back(GetMethodConstant(*i));
5086 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005087
5088 Values[2] = EmitMethodList(MethodListName,
5089 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005090 Methods);
5091
5092 MethodListName = Prefix;
5093 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5094 OCD->getNameAsString();
5095 Methods.clear();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005096 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005097 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005098 // Class methods should always be defined.
5099 Methods.push_back(GetMethodConstant(*i));
5100 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005101
5102 Values[3] = EmitMethodList(MethodListName,
5103 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005104 Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005105 const ObjCCategoryDecl *Category =
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00005106 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005107 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005108 llvm::SmallString<256> ExtName;
5109 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5110 << OCD->getName();
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005111 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005112 + Interface->getName() + "_$_"
5113 + Category->getName(),
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005114 Category->protocol_begin(),
5115 Category->protocol_end());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005116 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5117 OCD, Category, ObjCTypes);
Mike Stumpb3589f42009-07-30 22:28:39 +00005118 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00005119 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5120 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005121 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005122
5123 llvm::Constant *Init =
5124 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005125 Values);
5126 llvm::GlobalVariable *GCATV
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005127 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005128 false,
5129 llvm::GlobalValue::InternalLinkage,
5130 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005131 ExtCatName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005132 GCATV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005133 CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005134 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerad64e022009-07-17 23:57:13 +00005135 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005136 DefinedCategories.push_back(GCATV);
Daniel Dunbar74d4b122009-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 Jahanian64089ce2011-04-22 22:02:28 +00005141 // method definition entries must be clear for next implementation.
5142 MethodDefinitions.clear();
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005143}
Fariborz Jahanian493dab72009-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 Dunbar6bff2512009-08-03 17:06:42 +00005149 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00005150 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005151 if (!Fn)
5152 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005153
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005154 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005155 Method[0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00005156 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005157 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005158 Method[1] = GetMethodVarType(MD);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005159 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005160 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian493dab72009-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 Dunbar9c29bf52009-10-18 20:48:59 +00005170llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
5171 const char *Section,
5172 const ConstantVector &Methods) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005173 // Return null for empty list.
5174 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00005175 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005176
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005177 std::vector<llvm::Constant*> Values(3);
5178 // sizeof(struct _objc_method)
Duncan Sands9408c452009-05-09 07:08:47 +00005179 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005180 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005181 // method_count
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005182 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00005183 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005184 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00005185 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005186 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005187
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005188 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005189 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005190 llvm::GlobalValue::InternalLinkage,
5191 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005192 Name);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005193 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005194 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005195 GV->setSection(Section);
Chris Lattnerad64e022009-07-17 23:57:13 +00005196 CGM.AddUsedGlobal(GV);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005197 return llvm::ConstantExpr::getBitCast(GV,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005198 ObjCTypes.MethodListnfABIPtrTy);
5199}
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005200
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005201/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5202/// the given ivar.
Daniel Dunbare83be122010-04-02 21:14:02 +00005203llvm::GlobalVariable *
5204CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5205 const ObjCIvarDecl *Ivar) {
5206 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbara81419d2009-05-05 00:36:57 +00005207 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregor6ab35242009-04-09 21:40:53 +00005208 '.' + Ivar->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005209 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005210 CGM.getModule().getGlobalVariable(Name);
5211 if (!IvarOffsetGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005212 IvarOffsetGV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005213 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005214 false,
5215 llvm::GlobalValue::ExternalLinkage,
5216 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00005217 Name);
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005218 return IvarOffsetGV;
5219}
5220
Daniel Dunbare83be122010-04-02 21:14:02 +00005221llvm::Constant *
5222CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5223 const ObjCIvarDecl *Ivar,
5224 unsigned long int Offset) {
Daniel Dunbar737c5022009-04-19 00:44:02 +00005225 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005226 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar737c5022009-04-19 00:44:02 +00005227 Offset));
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005228 IvarOffsetGV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005229 CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbar737c5022009-04-19 00:44:02 +00005230
Mike Stumpf5408fe2009-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 Dunbar737c5022009-04-19 00:44:02 +00005233 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5234 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall1fb0caa2010-10-22 21:05:15 +00005235 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00005236 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar04d40782009-04-14 06:00:08 +00005237 else
Fariborz Jahanian77c9fd22009-04-06 18:30:00 +00005238 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendling1f382512011-05-04 21:37:25 +00005239 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005240 return IvarOffsetGV;
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005241}
5242
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005243/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar11394522009-04-18 08:51:00 +00005244/// implementation. The return value has type
Fariborz Jahanian98abf4b2009-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 Dunbar3e5f0d82009-04-20 06:54:31 +00005259
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005260llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005261 const ObjCImplementationDecl *ID) {
5262
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005263 std::vector<llvm::Constant*> Ivars, Ivar(5);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005264
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005265 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5266 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005267
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005268 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005269
Daniel Dunbar91636d62009-04-20 00:33:43 +00005270 // Collect declared and synthesized ivars in a small vector.
Fariborz Jahanian18191882009-03-31 18:11:23 +00005271 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00005272 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005273
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00005274 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
5275 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00005276 // Ignore unnamed bit-fields.
5277 if (!IVD->getDeclName())
5278 continue;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005279 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00005280 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00005281 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5282 Ivar[2] = GetMethodVarType(IVD);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005283 const llvm::Type *FieldTy =
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00005284 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Duncan Sands9408c452009-05-09 07:08:47 +00005285 unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005286 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005287 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005288 Align = llvm::Log2_32(Align);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005289 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbar91636d62009-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 Anderson4a28d5d2009-07-24 23:12:58 +00005295 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson08e25242009-07-27 22:29:56 +00005296 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005297 }
5298 // Return null for empty list.
5299 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00005300 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005301 std::vector<llvm::Constant*> Values(3);
Duncan Sands9408c452009-05-09 07:08:47 +00005302 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Anderson4a28d5d2009-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 Anderson96e0fc72009-07-29 22:16:19 +00005305 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005306 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00005307 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005308 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005309 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5310 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005311 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005312 llvm::GlobalValue::InternalLinkage,
5313 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005314 Prefix + OID->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005315 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005316 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005317 GV->setSection("__DATA, __objc_const");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005318
Chris Lattnerad64e022009-07-17 23:57:13 +00005319 CGM.AddUsedGlobal(GV);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005320 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005321}
5322
5323llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005324 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005325 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005326
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00005331 Entry =
5332 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5333 llvm::GlobalValue::ExternalLinkage,
5334 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005335 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianda320092009-01-29 19:24:30 +00005336 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00005337 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005338
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00005360 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005361 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005362
Fariborz Jahanianda320092009-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 Jahanianda320092009-01-29 19:24:30 +00005367 // Construct method lists.
5368 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5369 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005370 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005371 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005372 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005373 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00005374 if (!C)
5375 return GetOrEmitProtocolRef(PD);
5376
Fariborz Jahanianda320092009-01-29 19:24:30 +00005377 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5378 OptInstanceMethods.push_back(C);
5379 } else {
5380 InstanceMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005381 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00005382 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005383
5384 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005385 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005386 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005387 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00005388 if (!C)
5389 return GetOrEmitProtocolRef(PD);
5390
Fariborz Jahanianda320092009-01-29 19:24:30 +00005391 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5392 OptClassMethods.push_back(C);
5393 } else {
5394 ClassMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005395 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00005396 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005397
Fariborz Jahanianda320092009-01-29 19:24:30 +00005398 std::vector<llvm::Constant*> Values(10);
5399 // isa is NULL
Owen Andersonc9c88b42009-07-31 20:28:54 +00005400 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005401 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005402 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5403 PD->protocol_begin(),
5404 PD->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005405
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005406 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005407 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005408 "__DATA, __objc_const",
5409 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005410 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005411 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005412 "__DATA, __objc_const",
5413 ClassMethods);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005414 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005415 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005416 "__DATA, __objc_const",
5417 OptInstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005418 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005419 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005420 "__DATA, __objc_const",
5421 OptClassMethods);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005422 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005423 0, PD, ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005424 uint32_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00005425 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005426 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Andersonc9c88b42009-07-31 20:28:54 +00005427 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005428 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanianda320092009-01-29 19:24:30 +00005429 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005430
Fariborz Jahanianda320092009-01-29 19:24:30 +00005431 if (Entry) {
5432 // Already created, fix the linkage and update the initializer.
Mike Stump286acbd2009-03-07 16:33:28 +00005433 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005434 Entry->setInitializer(Init);
5435 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005436 Entry =
Daniel Dunbar9c29bf52009-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 Jahanian09796d62009-01-31 02:43:27 +00005440 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005441 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanianda320092009-01-29 19:24:30 +00005442 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00005443 }
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005444 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005445 CGM.AddUsedGlobal(Entry);
5446
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005447 // Use this protocol meta-data to build protocol list table in section
5448 // __DATA, __objc_protolist
Daniel Dunbar9c29bf52009-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 Jahanian09796d62009-01-31 02:43:27 +00005453 PTGV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005454 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbar0bf21992009-04-15 02:56:18 +00005455 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005456 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005457 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanianda320092009-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 Dunbar9c29bf52009-10-18 20:48:59 +00005470CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
5471 ObjCProtocolDecl::protocol_iterator begin,
5472 ObjCProtocolDecl::protocol_iterator end) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005473 std::vector<llvm::Constant*> ProtocolRefs;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005474
Fariborz Jahanianda320092009-01-29 19:24:30 +00005475 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005476 if (begin == end)
Owen Andersonc9c88b42009-07-31 20:28:54 +00005477 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005478
Daniel Dunbar948e2582009-02-15 07:36:20 +00005479 // FIXME: We shouldn't need to do this lookup here, should we?
Daniel Dunbar9c29bf52009-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 Jahanianda320092009-01-29 19:24:30 +00005484 if (GV)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005485 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005486
Daniel Dunbar948e2582009-02-15 07:36:20 +00005487 for (; begin != end; ++begin)
5488 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
5489
Fariborz Jahanianda320092009-01-29 19:24:30 +00005490 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00005491 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005492 ObjCTypes.ProtocolnfABIPtrTy));
5493
Fariborz Jahanianda320092009-01-29 19:24:30 +00005494 std::vector<llvm::Constant*> Values(2);
Owen Andersona1cf15f2009-07-14 23:10:40 +00005495 Values[0] =
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005496 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005497 Values[1] =
Owen Anderson7db6d832009-07-28 18:33:04 +00005498 llvm::ConstantArray::get(
Owen Anderson96e0fc72009-07-29 22:16:19 +00005499 llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005500 ProtocolRefs.size()),
5501 ProtocolRefs);
5502
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005503 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Owen Anderson1c431b32009-07-08 19:05:04 +00005504 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanianda320092009-01-29 19:24:30 +00005505 llvm::GlobalValue::InternalLinkage,
5506 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005507 Name);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005508 GV->setSection("__DATA, __objc_const");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005509 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005510 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Chris Lattnerad64e022009-07-17 23:57:13 +00005511 CGM.AddUsedGlobal(GV);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005512 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar948e2582009-02-15 07:36:20 +00005513 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005514}
5515
Fariborz Jahanian3819a0b2009-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 Andersona1cf15f2009-07-14 23:10:40 +00005526 Desc[0] =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005527 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5528 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005529 Desc[1] = GetMethodVarType(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00005530 if (!Desc[1])
5531 return 0;
5532
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005533 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00005534 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005535 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005536}
Fariborz Jahanian45012a72009-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 Dunbar6bff2512009-08-03 17:06:42 +00005543///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00005544LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall506b57e2010-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 Dunbar97776872009-04-22 07:32:20 +00005551 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5552 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005553}
5554
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00005555llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005556 CodeGen::CodeGenFunction &CGF,
5557 const ObjCInterfaceDecl *Interface,
5558 const ObjCIvarDecl *Ivar) {
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005559 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00005560}
5561
John McCallb1e81442011-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 Dunbar6bff2512009-08-03 17:06:42 +00005568
John McCallb1e81442011-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 McCall944c8432011-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 McCallb1e81442011-05-13 23:16:18 +00005595 // Compute the actual arguments.
5596 CallArgList args;
5597
John McCall944c8432011-05-14 03:10:52 +00005598 // First argument: the receiver / super-call structure.
John McCallb1e81442011-05-13 23:16:18 +00005599 if (!isSuper)
John McCall944c8432011-05-14 03:10:52 +00005600 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
5601 args.add(RValue::get(arg0), arg0Type);
John McCallb1e81442011-05-13 23:16:18 +00005602
John McCall944c8432011-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 McCallb1e81442011-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 McCallcba681a2011-05-14 21:12:11 +00005613 NullReturnState nullReturn;
5614
John McCall944c8432011-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 McCallb1e81442011-05-13 23:16:18 +00005622 llvm::Constant *fn = 0;
5623 std::string messageRefName("\01l_");
5624 if (CGM.ReturnTypeUsesSRet(fnInfo)) {
John McCallb1e81442011-05-13 23:16:18 +00005625 if (isSuper) {
5626 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
5627 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005628 } else {
John McCallcba681a2011-05-14 21:12:11 +00005629 nullReturn.init(CGF, arg0);
John McCallb1e81442011-05-13 23:16:18 +00005630 fn = ObjCTypes.getMessageSendStretFixupFn();
5631 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005632 }
John McCallb1e81442011-05-13 23:16:18 +00005633 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
5634 fn = ObjCTypes.getMessageSendFpretFixupFn();
5635 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stumpb3589f42009-07-30 22:28:39 +00005636 } else {
John McCallb1e81442011-05-13 23:16:18 +00005637 if (isSuper) {
5638 fn = ObjCTypes.getMessageSendSuper2FixupFn();
5639 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005640 } else {
John McCallb1e81442011-05-13 23:16:18 +00005641 fn = ObjCTypes.getMessageSendFixupFn();
5642 messageRefName += "objc_msgSend_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005643 }
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005644 }
John McCallb1e81442011-05-13 23:16:18 +00005645 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
5646 messageRefName += '_';
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005647
John McCallb1e81442011-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 McCall944c8432011-05-14 03:10:52 +00005655 // Build the message ref structure.
John McCallb1e81442011-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 McCall944c8432011-05-14 03:10:52 +00005672 // Update the message ref argument.
John McCallb1e81442011-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 McCallcba681a2011-05-14 21:12:11 +00005685 RValue result = CGF.EmitCall(fnInfo, callee, returnSlot, args);
5686 return nullReturn.complete(CGF, result, resultType);
Fariborz Jahanian46551122009-02-04 00:22:57 +00005687}
5688
5689/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005690CodeGen::RValue
5691CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00005692 ReturnValueSlot Return,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005693 QualType ResultType,
5694 Selector Sel,
5695 llvm::Value *Receiver,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005696 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00005697 const ObjCInterfaceDecl *Class,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005698 const ObjCMethodDecl *Method) {
John McCall944c8432011-05-14 03:10:52 +00005699 return isVTableDispatchedSelector(Sel)
5700 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005701 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00005702 false, CallArgs, Method)
5703 : EmitMessageSend(CGF, Return, ResultType,
5704 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005705 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00005706 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian46551122009-02-04 00:22:57 +00005707}
5708
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005709llvm::GlobalVariable *
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005710CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005711 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5712
Daniel Dunbardfff2302009-03-02 05:18:14 +00005713 if (!GV) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005714 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005715 false, llvm::GlobalValue::ExternalLinkage,
5716 0, Name);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005717 }
5718
5719 return GV;
5720}
5721
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005722llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5723 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005724 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005725
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005726 if (!Entry) {
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005727 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005728 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005729 Entry =
5730 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005731 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005732 ClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005733 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005734 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005735 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005736 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00005737 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005738 CGM.AddUsedGlobal(Entry);
Daniel Dunbar11394522009-04-18 08:51:00 +00005739 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005740
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005741 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar11394522009-04-18 08:51:00 +00005742}
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005743
Daniel Dunbar11394522009-04-18 08:51:00 +00005744llvm::Value *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005745CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00005746 const ObjCInterfaceDecl *ID) {
5747 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005748
Daniel Dunbar11394522009-04-18 08:51:00 +00005749 if (!Entry) {
5750 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5751 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005752 Entry =
5753 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005754 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005755 ClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005756 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar11394522009-04-18 08:51:00 +00005757 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005758 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005759 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00005760 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005761 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005762 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005763
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005764 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005765}
5766
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005767/// EmitMetaClassRef - Return a Value * of the address of _class_t
5768/// meta-data
5769///
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005770llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5771 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005772 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5773 if (Entry)
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005774 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005775
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005776 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005777 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005778 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00005779 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005780 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005781 MetaClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005782 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005783 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005784 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005785 ObjCTypes.ClassnfABIPtrTy));
5786
Daniel Dunbar33af70f2009-04-15 19:03:14 +00005787 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005788 CGM.AddUsedGlobal(Entry);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005789
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005790 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005791}
5792
Fariborz Jahanian0e81f4b2009-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 Gregor0a0d2b12011-03-23 00:50:03 +00005797 if (ID->isWeakImported()) {
Fariborz Jahanian269f8bc2009-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 Jahanian0e81f4b2009-02-05 20:41:40 +00005803 return EmitClassRef(Builder, ID);
5804}
5805
Fariborz Jahanian7a06aae2009-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 McCallef072fd2010-05-22 01:48:05 +00005811 ReturnValueSlot Return,
Daniel Dunbar6bff2512009-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 Dunbard6c93d72009-09-17 04:01:22 +00005818 const CodeGen::CallArgList &CallArgs,
5819 const ObjCMethodDecl *Method) {
Fariborz Jahanian7a06aae2009-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 McCall604da292011-03-04 08:00:29 +00005824 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005825
Fariborz Jahanian7a06aae2009-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 Dunbar6bff2512009-08-03 17:06:42 +00005830
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005831 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanian7ce77922009-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 Dunbar11394522009-04-18 08:51:00 +00005837 Target = EmitClassRef(CGF.Builder, Class);
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005838 Target = CGF.Builder.CreateStructGEP(Target, 0);
5839 Target = CGF.Builder.CreateLoad(Target);
Mike Stumpb3589f42009-07-30 22:28:39 +00005840 } else
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005841 Target = EmitMetaClassRef(CGF.Builder, Class);
Mike Stumpb3589f42009-07-30 22:28:39 +00005842 } else
Daniel Dunbar11394522009-04-18 08:51:00 +00005843 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005844
Mike Stumpf5408fe2009-05-16 07:57:57 +00005845 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5846 // ObjCTypes types.
Fariborz Jahanian7a06aae2009-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 Dunbar6bff2512009-08-03 17:06:42 +00005852
John McCall944c8432011-05-14 03:10:52 +00005853 return (isVTableDispatchedSelector(Sel))
5854 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005855 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00005856 true, CallArgs, Method)
5857 : EmitMessageSend(CGF, Return, ResultType,
5858 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005859 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00005860 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005861}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005862
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005863llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian03b29602010-06-17 19:56:20 +00005864 Selector Sel, bool lval) {
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005865 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005866
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005867 if (!Entry) {
Daniel Dunbar6bff2512009-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 Jahaniand0f8a8d2009-05-11 19:25:47 +00005875 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005876 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005877 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005878
Fariborz Jahanian03b29602010-06-17 19:56:20 +00005879 if (lval)
5880 return Entry;
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005881 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005882}
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005883/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005884/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005885///
5886void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005887 llvm::Value *src,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005888 llvm::Value *dst,
5889 llvm::Value *ivarOffset) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005890 const llvm::Type * SrcTy = src->getType();
5891 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005892 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Jahanian3b8a6522009-03-13 00:42:52 +00005896 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5897 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005898 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5899 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005900 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5901 src, dst, ivarOffset);
Fariborz Jahanian6948aea2009-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 Dunbar6bff2512009-08-03 17:06:42 +00005909 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005910 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005911 const llvm::Type * SrcTy = src->getType();
5912 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005913 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00005916 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005917 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5918 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005919 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5920 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00005921 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005922 src, dst, "weakassign");
5923 return;
5924}
5925
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005926void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005927 CodeGen::CodeGenFunction &CGF,
5928 llvm::Value *DestPtr,
5929 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00005930 llvm::Value *Size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005931 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5932 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005933 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00005934 DestPtr, SrcPtr, Size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005935 return;
5936}
5937
Fariborz Jahanian6948aea2009-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 Dunbar6bff2512009-08-03 17:06:42 +00005942 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005943 llvm::Value *AddrWeakObj) {
Eli Friedman8339b352009-03-07 03:57:15 +00005944 const llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005945 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5946 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00005947 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005948 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00005949 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6948aea2009-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 Stump1eb44332009-09-09 15:08:12 +00005957 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005958 const llvm::Type * SrcTy = src->getType();
5959 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005960 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Jahanian3b8a6522009-03-13 00:42:52 +00005964 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5965 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005966 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5967 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00005968 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian6948aea2009-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 Jahanian021a7a62010-07-20 20:30:03 +00005977 llvm::Value *src, llvm::Value *dst,
5978 bool threadlocal) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005979 const llvm::Type * SrcTy = src->getType();
5980 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005981 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Jahanian3b8a6522009-03-13 00:42:52 +00005985 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5986 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005987 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5988 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-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 Jahanian6948aea2009-02-16 22:52:32 +00005995 return;
5996}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005997
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005998void
John McCallf1549f62010-07-06 01:34:17 +00005999CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6000 const ObjCAtSynchronizedStmt &S) {
David Chisnall05dc91b2011-03-25 17:46:35 +00006001 EmitAtSynchronizedStmt(CGF, S,
6002 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6003 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallf1549f62010-07-06 01:34:17 +00006004}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006005
John McCall5a180392010-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 McCallf1549f62010-07-06 01:34:17 +00006031void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6032 const ObjCAtTryStmt &S) {
David Chisnall05dc91b2011-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 Dunbar8ecbaf22009-02-24 07:47:38 +00006037}
6038
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006039/// EmitThrowStmt - Generate code for a throw statement.
6040void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6041 const ObjCAtThrowStmt &S) {
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006042 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall7ec404c2010-10-16 08:21:07 +00006043 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
John McCallfd186ac2010-10-16 16:34:08 +00006044 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy,
6045 "tmp");
John McCall7ec404c2010-10-16 08:21:07 +00006046 llvm::Value *Args[] = { Exception };
6047 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(),
6048 Args, Args+1)
6049 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006050 } else {
John McCall7ec404c2010-10-16 08:21:07 +00006051 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn(), 0, 0)
6052 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006053 }
6054
John McCall7ec404c2010-10-16 08:21:07 +00006055 CGF.Builder.CreateUnreachable();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006056 CGF.Builder.ClearInsertionPoint();
6057}
Daniel Dunbare588b992009-03-01 04:46:24 +00006058
John McCall5a180392010-07-24 00:37:23 +00006059llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006060CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006061 bool ForDefinition) {
Daniel Dunbare588b992009-03-01 04:46:24 +00006062 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbare588b992009-03-01 04:46:24 +00006063
Daniel Dunbar8158a2f2009-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 Dunbar7e075cb2009-04-07 06:43:45 +00006069
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006070 // If this type (or a super class) has the __objc_exception__
6071 // attribute, emit an external reference.
Douglas Gregor68584ed2009-06-18 16:11:24 +00006072 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006073 return Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00006074 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006075 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006076 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006077 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006078 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006079 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006080
Daniel Dunbar8158a2f2009-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 Dunbar6ab187a2009-04-07 05:48:37 +00006084 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbare588b992009-03-01 04:46:24 +00006085 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006086 llvm::GlobalVariable *VTableGV =
Daniel Dunbare588b992009-03-01 04:46:24 +00006087 CGM.getModule().getGlobalVariable(VTableName);
6088 if (!VTableGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006089 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6090 false,
Daniel Dunbare588b992009-03-01 04:46:24 +00006091 llvm::GlobalValue::ExternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00006092 0, VTableName);
Daniel Dunbare588b992009-03-01 04:46:24 +00006093
Chris Lattner77b89b82010-06-27 07:15:29 +00006094 llvm::Value *VTableIdx =
6095 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
Daniel Dunbare588b992009-03-01 04:46:24 +00006096
6097 std::vector<llvm::Constant*> Values(3);
Owen Anderson3c4972d2009-07-29 18:54:39 +00006098 Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
Daniel Dunbare588b992009-03-01 04:46:24 +00006099 Values[1] = GetClassName(ID->getIdentifier());
Fariborz Jahanian0f902942009-04-14 18:41:56 +00006100 Values[2] = GetClassGlobal(ClassName);
Owen Andersona1cf15f2009-07-14 23:10:40 +00006101 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00006102 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbare588b992009-03-01 04:46:24 +00006103
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006104 if (Entry) {
6105 Entry->setInitializer(Init);
6106 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00006107 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006108 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006109 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006110 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006111 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006112 }
6113
John McCall1fb0caa2010-10-22 21:05:15 +00006114 if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006115 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00006116 Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
6117 ObjCTypes.EHTypeTy));
Daniel Dunbar8158a2f2009-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 Dunbare588b992009-03-01 04:46:24 +00006125
6126 return Entry;
6127}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006128
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00006129/* *** */
6130
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00006131CodeGen::CGObjCRuntime *
6132CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
David Chisnall60be6072011-03-22 21:21:24 +00006133 if (CGM.getLangOptions().ObjCNonFragileABI)
6134 return new CGObjCNonFragileABIMac(CGM);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00006135 return new CGObjCMac(CGM);
6136}