blob: d0419ec1632a36c1c5764fc501aa721b1a59a007 [file] [log] [blame]
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattner57540c52011-04-15 05:22:18 +000010// This provides Objective-C code generation targeting the Apple runtime.
Daniel Dunbar303e2c22008-08-11 02:45:11 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
John McCallad7c5c12011-02-08 08:22:06 +000015#include "CGBlocks.h"
John McCalled1ae862011-01-28 11:13:47 +000016#include "CGCleanup.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000017#include "CGRecordLayout.h"
18#include "CodeGenFunction.h"
19#include "CodeGenModule.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000020#include "clang/AST/ASTContext.h"
Daniel Dunbar221fa942008-08-11 04:54:23 +000021#include "clang/AST/Decl.h"
Daniel Dunbarb036db82008-08-13 03:21:16 +000022#include "clang/AST/DeclObjC.h"
Anders Carlsson15b73de2009-07-18 19:43:29 +000023#include "clang/AST/RecordLayout.h"
Chris Lattnerf0b64d72009-04-26 01:32:48 +000024#include "clang/AST/StmtObjC.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000025#include "clang/Basic/LangOptions.h"
Mark Laceya8e7df32013-10-30 21:53:58 +000026#include "clang/CodeGen/CGFunctionInfo.h"
Chandler Carruth85098242010-06-15 23:19:56 +000027#include "clang/Frontend/CodeGenOptions.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000028#include "llvm/ADT/DenseSet.h"
29#include "llvm/ADT/SetVector.h"
30#include "llvm/ADT/SmallPtrSet.h"
31#include "llvm/ADT/SmallString.h"
Chandler Carruthc80ceea2014-03-04 11:02:08 +000032#include "llvm/IR/CallSite.h"
Chandler Carruthffd55512013-01-02 11:45:17 +000033#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/InlineAsm.h"
35#include "llvm/IR/IntrinsicInst.h"
36#include "llvm/IR/LLVMContext.h"
37#include "llvm/IR/Module.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000038#include "llvm/Support/raw_ostream.h"
Torok Edwindb714922009-08-24 13:25:12 +000039#include <cstdio>
Daniel Dunbar303e2c22008-08-11 02:45:11 +000040
41using namespace clang;
Daniel Dunbar41cf9de2008-09-09 01:06:48 +000042using namespace CodeGen;
Daniel Dunbar303e2c22008-08-11 02:45:11 +000043
44namespace {
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000045
Daniel Dunbar59e476b2009-08-03 17:06:42 +000046// FIXME: We should find a nicer way to make the labels for metadata, string
47// concatenation is lame.
Daniel Dunbarb036db82008-08-13 03:21:16 +000048
Fariborz Jahanian279eda62009-01-21 22:04:16 +000049class ObjCCommonTypesHelper {
Owen Anderson170229f2009-07-14 23:10:40 +000050protected:
51 llvm::LLVMContext &VMContext;
Daniel Dunbar59e476b2009-08-03 17:06:42 +000052
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000053private:
John McCall9dc0db22011-05-15 01:53:33 +000054 // The types of these functions don't really matter because we
55 // should always bitcast before calling them.
56
57 /// id objc_msgSend (id, SEL, ...)
58 ///
59 /// The default messenger, used for sends whose ABI is unchanged from
60 /// the all-integer/pointer case.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000061 llvm::Constant *getMessageSendFn() const {
John McCall31168b02011-06-15 23:02:42 +000062 // Add the non-lazy-bind attribute, since objc_msgSend is likely to
63 // be called a lot.
Chris Lattnera5f58b02011-07-09 17:41:47 +000064 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Bill Wendling8594fcb2013-01-31 00:30:05 +000065 return
66 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
67 params, true),
68 "objc_msgSend",
69 llvm::AttributeSet::get(CGM.getLLVMContext(),
70 llvm::AttributeSet::FunctionIndex,
71 llvm::Attribute::NonLazyBind));
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000072 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000073
John McCall9dc0db22011-05-15 01:53:33 +000074 /// void objc_msgSend_stret (id, SEL, ...)
75 ///
76 /// The messenger used when the return value is an aggregate returned
77 /// by indirect reference in the first argument, and therefore the
78 /// self and selector parameters are shifted over by one.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000079 llvm::Constant *getMessageSendStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000080 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +000081 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
82 params, true),
83 "objc_msgSend_stret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000084
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000085 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000086
John McCall9dc0db22011-05-15 01:53:33 +000087 /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
88 ///
89 /// The messenger used when the return value is returned on the x87
90 /// floating-point stack; without a special entrypoint, the nil case
91 /// would be unbalanced.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000092 llvm::Constant *getMessageSendFpretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000093 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Chris Lattnerece04092012-02-07 00:39:47 +000094 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
95 params, true),
John McCall9dc0db22011-05-15 01:53:33 +000096 "objc_msgSend_fpret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000097
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000098 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000099
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000100 /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
101 ///
102 /// The messenger used when the return value is returned in two values on the
103 /// x87 floating point stack; without a special entrypoint, the nil case
104 /// would be unbalanced. Only used on 64-bit X86.
105 llvm::Constant *getMessageSendFp2retFn() const {
106 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
107 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
108 llvm::Type *resultType =
109 llvm::StructType::get(longDoubleType, longDoubleType, NULL);
110
111 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
112 params, true),
113 "objc_msgSend_fp2ret");
114 }
115
John McCall9dc0db22011-05-15 01:53:33 +0000116 /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
117 ///
118 /// The messenger used for super calls, which have different dispatch
119 /// semantics. The class passed is the superclass of the current
120 /// class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000121 llvm::Constant *getMessageSendSuperFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000122 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000123 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000124 params, true),
125 "objc_msgSendSuper");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000126 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000127
John McCall9dc0db22011-05-15 01:53:33 +0000128 /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
129 ///
130 /// A slightly different messenger used for super calls. The class
131 /// passed is the current class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000132 llvm::Constant *getMessageSendSuperFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000133 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000134 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000135 params, true),
136 "objc_msgSendSuper2");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000137 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000138
John McCall9dc0db22011-05-15 01:53:33 +0000139 /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
140 /// SEL op, ...)
141 ///
142 /// The messenger used for super calls which return an aggregate indirectly.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000143 llvm::Constant *getMessageSendSuperStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000144 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000145 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000146 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000147 "objc_msgSendSuper_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000148 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000149
John McCall9dc0db22011-05-15 01:53:33 +0000150 /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
151 /// SEL op, ...)
152 ///
153 /// objc_msgSendSuper_stret with the super2 semantics.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000154 llvm::Constant *getMessageSendSuperStretFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000155 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000156 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000157 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000158 "objc_msgSendSuper2_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000159 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000160
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000161 llvm::Constant *getMessageSendSuperFpretFn() const {
162 // There is no objc_msgSendSuper_fpret? How can that work?
163 return getMessageSendSuperFn();
164 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000165
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000166 llvm::Constant *getMessageSendSuperFpretFn2() const {
167 // There is no objc_msgSendSuper_fpret? How can that work?
168 return getMessageSendSuperFn2();
169 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000170
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000171protected:
172 CodeGen::CodeGenModule &CGM;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000173
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000174public:
Chris Lattnera5f58b02011-07-09 17:41:47 +0000175 llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000176 llvm::Type *Int8PtrTy, *Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000177
Daniel Dunbar5d715592008-08-12 05:28:47 +0000178 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000179 llvm::Type *ObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000180
Fariborz Jahanian406b1172008-11-18 20:18:11 +0000181 /// PtrObjectPtrTy - LLVM type for id *
Chris Lattnera5f58b02011-07-09 17:41:47 +0000182 llvm::Type *PtrObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000183
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000184 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000185 llvm::Type *SelectorPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000186
187private:
Daniel Dunbarb036db82008-08-13 03:21:16 +0000188 /// ProtocolPtrTy - LLVM type for external protocol handles
189 /// (typeof(Protocol))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000190 llvm::Type *ExternalProtocolPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000191
192public:
193 llvm::Type *getExternalProtocolPtrTy() {
194 if (!ExternalProtocolPtrTy) {
195 // FIXME: It would be nice to unify this with the opaque type, so that the
196 // IR comes out a bit cleaner.
197 CodeGen::CodeGenTypes &Types = CGM.getTypes();
198 ASTContext &Ctx = CGM.getContext();
199 llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
200 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
201 }
202
203 return ExternalProtocolPtrTy;
204 }
205
Daniel Dunbarc722b852008-08-30 03:02:31 +0000206 // SuperCTy - clang type for struct objc_super.
207 QualType SuperCTy;
208 // SuperPtrCTy - clang type for struct objc_super *.
209 QualType SuperPtrCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000210
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000211 /// SuperTy - LLVM type for struct objc_super.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000212 llvm::StructType *SuperTy;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +0000213 /// SuperPtrTy - LLVM type for struct objc_super *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000214 llvm::Type *SuperPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000215
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000216 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
217 /// in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000218 llvm::StructType *PropertyTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000219
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000220 /// PropertyListTy - LLVM type for struct objc_property_list
221 /// (_prop_list_t in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000222 llvm::StructType *PropertyListTy;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000223 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000224 llvm::Type *PropertyListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000225
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000226 // MethodTy - LLVM type for struct objc_method.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000227 llvm::StructType *MethodTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000228
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000229 /// CacheTy - LLVM type for struct objc_cache.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000230 llvm::Type *CacheTy;
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000231 /// CachePtrTy - LLVM type for struct objc_cache *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000232 llvm::Type *CachePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000233
Chris Lattnerce8754e2009-04-22 02:44:54 +0000234 llvm::Constant *getGetPropertyFn() {
235 CodeGen::CodeGenTypes &Types = CGM.getTypes();
236 ASTContext &Ctx = CGM.getContext();
237 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000238 SmallVector<CanQualType,4> Params;
John McCall2da83a32010-02-26 00:48:12 +0000239 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
240 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000241 Params.push_back(IdType);
242 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000243 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000244 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000245 llvm::FunctionType *FTy =
Reid Kleckner4982b822014-01-31 22:54:50 +0000246 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(IdType, false, Params,
247 FunctionType::ExtInfo(),
John McCall8dda7b22012-07-07 06:41:13 +0000248 RequiredArgs::All));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000249 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
250 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000251
Chris Lattnerce8754e2009-04-22 02:44:54 +0000252 llvm::Constant *getSetPropertyFn() {
253 CodeGen::CodeGenTypes &Types = CGM.getTypes();
254 ASTContext &Ctx = CGM.getContext();
255 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000256 SmallVector<CanQualType,6> Params;
John McCall2da83a32010-02-26 00:48:12 +0000257 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
258 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000259 Params.push_back(IdType);
260 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000261 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000262 Params.push_back(IdType);
263 Params.push_back(Ctx.BoolTy);
264 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000265 llvm::FunctionType *FTy =
Reid Kleckner4982b822014-01-31 22:54:50 +0000266 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
267 Params,
268 FunctionType::ExtInfo(),
John McCall8dda7b22012-07-07 06:41:13 +0000269 RequiredArgs::All));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000270 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
271 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000272
Ted Kremeneke65b0862012-03-06 20:05:56 +0000273 llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) {
274 CodeGen::CodeGenTypes &Types = CGM.getTypes();
275 ASTContext &Ctx = CGM.getContext();
276 // void objc_setProperty_atomic(id self, SEL _cmd,
277 // id newValue, ptrdiff_t offset);
278 // void objc_setProperty_nonatomic(id self, SEL _cmd,
279 // id newValue, ptrdiff_t offset);
280 // void objc_setProperty_atomic_copy(id self, SEL _cmd,
281 // id newValue, ptrdiff_t offset);
282 // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
283 // id newValue, ptrdiff_t offset);
284
285 SmallVector<CanQualType,4> Params;
286 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
287 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
288 Params.push_back(IdType);
289 Params.push_back(SelType);
290 Params.push_back(IdType);
291 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
292 llvm::FunctionType *FTy =
Reid Kleckner4982b822014-01-31 22:54:50 +0000293 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
294 Params,
John McCall8dda7b22012-07-07 06:41:13 +0000295 FunctionType::ExtInfo(),
296 RequiredArgs::All));
Ted Kremeneke65b0862012-03-06 20:05:56 +0000297 const char *name;
298 if (atomic && copy)
299 name = "objc_setProperty_atomic_copy";
300 else if (atomic && !copy)
301 name = "objc_setProperty_atomic";
302 else if (!atomic && copy)
303 name = "objc_setProperty_nonatomic_copy";
304 else
305 name = "objc_setProperty_nonatomic";
306
307 return CGM.CreateRuntimeFunction(FTy, name);
308 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000309
310 llvm::Constant *getCopyStructFn() {
311 CodeGen::CodeGenTypes &Types = CGM.getTypes();
312 ASTContext &Ctx = CGM.getContext();
313 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000314 SmallVector<CanQualType,5> Params;
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000315 Params.push_back(Ctx.VoidPtrTy);
316 Params.push_back(Ctx.VoidPtrTy);
317 Params.push_back(Ctx.LongTy);
318 Params.push_back(Ctx.BoolTy);
319 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000320 llvm::FunctionType *FTy =
Reid Kleckner4982b822014-01-31 22:54:50 +0000321 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
322 Params,
323 FunctionType::ExtInfo(),
John McCall8dda7b22012-07-07 06:41:13 +0000324 RequiredArgs::All));
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000325 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
326 }
327
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000328 /// This routine declares and returns address of:
329 /// void objc_copyCppObjectAtomic(
330 /// void *dest, const void *src,
331 /// void (*copyHelper) (void *dest, const void *source));
332 llvm::Constant *getCppAtomicObjectFunction() {
333 CodeGen::CodeGenTypes &Types = CGM.getTypes();
334 ASTContext &Ctx = CGM.getContext();
335 /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
336 SmallVector<CanQualType,3> Params;
337 Params.push_back(Ctx.VoidPtrTy);
338 Params.push_back(Ctx.VoidPtrTy);
339 Params.push_back(Ctx.VoidPtrTy);
340 llvm::FunctionType *FTy =
Reid Kleckner4982b822014-01-31 22:54:50 +0000341 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
342 Params,
343 FunctionType::ExtInfo(),
John McCall8dda7b22012-07-07 06:41:13 +0000344 RequiredArgs::All));
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000345 return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
346 }
347
Chris Lattnerce8754e2009-04-22 02:44:54 +0000348 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000349 CodeGen::CodeGenTypes &Types = CGM.getTypes();
350 ASTContext &Ctx = CGM.getContext();
Chris Lattnerce8754e2009-04-22 02:44:54 +0000351 // void objc_enumerationMutation (id)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000352 SmallVector<CanQualType,1> Params;
John McCall2da83a32010-02-26 00:48:12 +0000353 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Chris Lattner2192fe52011-07-18 04:24:23 +0000354 llvm::FunctionType *FTy =
Reid Kleckner4982b822014-01-31 22:54:50 +0000355 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, false,
356 Params,
357 FunctionType::ExtInfo(),
John McCalla729c622012-02-17 03:33:10 +0000358 RequiredArgs::All));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000359 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
360 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000361
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000362 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattnerce8754e2009-04-22 02:44:54 +0000363 llvm::Constant *getGcReadWeakFn() {
364 // id objc_read_weak (id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000365 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000366 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000367 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000368 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000369 }
370
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000371 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000372 llvm::Constant *getGcAssignWeakFn() {
373 // id objc_assign_weak (id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000374 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000375 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000376 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000377 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
378 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000379
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000380 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000381 llvm::Constant *getGcAssignGlobalFn() {
382 // id objc_assign_global(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000383 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000384 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000385 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000386 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
387 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000388
Fariborz Jahanian217af242010-07-20 20:30:03 +0000389 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
390 llvm::Constant *getGcAssignThreadLocalFn() {
391 // id objc_assign_threadlocal(id src, id * dest)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000392 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian217af242010-07-20 20:30:03 +0000393 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000394 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian217af242010-07-20 20:30:03 +0000395 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
396 }
397
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000398 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000399 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000400 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000401 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
402 CGM.PtrDiffTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000403 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000404 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000405 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
406 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000407
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000408 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
409 llvm::Constant *GcMemmoveCollectableFn() {
410 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000411 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
John McCall9dc0db22011-05-15 01:53:33 +0000412 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000413 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
414 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000415
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000416 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000417 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000418 // id objc_assign_strongCast(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000419 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000420 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000421 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000422 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
423 }
Anders Carlsson9ab53d12009-02-16 22:59:18 +0000424
425 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000426 llvm::Constant *getExceptionThrowFn() {
427 // void objc_exception_throw(id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000428 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000429 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000430 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000431 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
432 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000433
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000434 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
435 llvm::Constant *getExceptionRethrowFn() {
436 // void objc_exception_rethrow(void)
John McCall9dc0db22011-05-15 01:53:33 +0000437 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000438 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
439 }
440
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000441 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerdcceee72009-04-06 16:53:45 +0000442 llvm::Constant *getSyncEnterFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000443 // int objc_sync_enter (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000444 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerdcceee72009-04-06 16:53:45 +0000445 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000446 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000447 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
448 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000449
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000450 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000451 llvm::Constant *getSyncExitFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000452 // int objc_sync_exit (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000453 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000454 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000455 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000456 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
457 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000458
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000459 llvm::Constant *getSendFn(bool IsSuper) const {
460 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
461 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000462
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000463 llvm::Constant *getSendFn2(bool IsSuper) const {
464 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
465 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000466
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000467 llvm::Constant *getSendStretFn(bool IsSuper) const {
468 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
469 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000470
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000471 llvm::Constant *getSendStretFn2(bool IsSuper) const {
472 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
473 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000474
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000475 llvm::Constant *getSendFpretFn(bool IsSuper) const {
476 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
477 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000478
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000479 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
480 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
481 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000482
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000483 llvm::Constant *getSendFp2retFn(bool IsSuper) const {
484 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
485 }
486
487 llvm::Constant *getSendFp2RetFn2(bool IsSuper) const {
488 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
489 }
490
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000491 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
492 ~ObjCCommonTypesHelper(){}
493};
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000494
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000495/// ObjCTypesHelper - Helper class that encapsulates lazy
496/// construction of varies types used during ObjC generation.
497class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000498public:
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000499 /// SymtabTy - LLVM type for struct objc_symtab.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000500 llvm::StructType *SymtabTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000501 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000502 llvm::Type *SymtabPtrTy;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000503 /// ModuleTy - LLVM type for struct objc_module.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000504 llvm::StructType *ModuleTy;
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000505
Daniel Dunbarb036db82008-08-13 03:21:16 +0000506 /// ProtocolTy - LLVM type for struct objc_protocol.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000507 llvm::StructType *ProtocolTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000508 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000509 llvm::Type *ProtocolPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000510 /// ProtocolExtensionTy - LLVM type for struct
511 /// objc_protocol_extension.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000512 llvm::StructType *ProtocolExtensionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000513 /// ProtocolExtensionTy - LLVM type for struct
514 /// objc_protocol_extension *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000515 llvm::Type *ProtocolExtensionPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000516 /// MethodDescriptionTy - LLVM type for struct
517 /// objc_method_description.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000518 llvm::StructType *MethodDescriptionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000519 /// MethodDescriptionListTy - LLVM type for struct
520 /// objc_method_description_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000521 llvm::StructType *MethodDescriptionListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000522 /// MethodDescriptionListPtrTy - LLVM type for struct
523 /// objc_method_description_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000524 llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000525 /// ProtocolListTy - LLVM type for struct objc_property_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000526 llvm::StructType *ProtocolListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000527 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000528 llvm::Type *ProtocolListPtrTy;
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000529 /// CategoryTy - LLVM type for struct objc_category.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000530 llvm::StructType *CategoryTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000531 /// ClassTy - LLVM type for struct objc_class.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000532 llvm::StructType *ClassTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000533 /// ClassPtrTy - LLVM type for struct objc_class *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000534 llvm::Type *ClassPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000535 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000536 llvm::StructType *ClassExtensionTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000537 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000538 llvm::Type *ClassExtensionPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000539 // IvarTy - LLVM type for struct objc_ivar.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000540 llvm::StructType *IvarTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000541 /// IvarListTy - LLVM type for struct objc_ivar_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000542 llvm::Type *IvarListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000543 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000544 llvm::Type *IvarListPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000545 /// MethodListTy - LLVM type for struct objc_method_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000546 llvm::Type *MethodListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000547 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000548 llvm::Type *MethodListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000549
Anders Carlsson9ff22482008-09-09 10:10:21 +0000550 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000551 llvm::Type *ExceptionDataTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000552
Anders Carlsson9ff22482008-09-09 10:10:21 +0000553 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000554 llvm::Constant *getExceptionTryEnterFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000555 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000556 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000557 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000558 "objc_exception_try_enter");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000559 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000560
561 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000562 llvm::Constant *getExceptionTryExitFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000563 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000564 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000565 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000566 "objc_exception_try_exit");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000567 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000568
569 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000570 llvm::Constant *getExceptionExtractFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000571 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000572 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000573 params, false),
Chris Lattnerc6406db2009-04-22 02:26:14 +0000574 "objc_exception_extract");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000575 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000576
Anders Carlsson9ff22482008-09-09 10:10:21 +0000577 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000578 llvm::Constant *getExceptionMatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000579 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000580 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000581 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000582 "objc_exception_match");
583
Chris Lattnerc6406db2009-04-22 02:26:14 +0000584 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000585
Anders Carlsson9ff22482008-09-09 10:10:21 +0000586 /// SetJmpFn - LLVM _setjmp function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000587 llvm::Constant *getSetJmpFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000588 // This is specifically the prototype for x86.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000589 llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
Bill Wendling8594fcb2013-01-31 00:30:05 +0000590 return
591 CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty,
592 params, false),
593 "_setjmp",
594 llvm::AttributeSet::get(CGM.getLLVMContext(),
595 llvm::AttributeSet::FunctionIndex,
596 llvm::Attribute::NonLazyBind));
Chris Lattnerc6406db2009-04-22 02:26:14 +0000597 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000598
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000599public:
600 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000601 ~ObjCTypesHelper() {}
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000602};
603
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000604/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000605/// modern abi
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000606class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000607public:
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000608
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000609 // MethodListnfABITy - LLVM for struct _method_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000610 llvm::StructType *MethodListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000611
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000612 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000613 llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000614
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000615 // ProtocolnfABITy = LLVM for struct _protocol_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000616 llvm::StructType *ProtocolnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000617
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000618 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000619 llvm::Type *ProtocolnfABIPtrTy;
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000620
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000621 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
Chris Lattnera5f58b02011-07-09 17:41:47 +0000622 llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000623
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000624 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000625 llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000626
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000627 // ClassnfABITy - LLVM for struct _class_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000628 llvm::StructType *ClassnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000629
Fariborz Jahanian71394042009-01-23 23:53:38 +0000630 // ClassnfABIPtrTy - LLVM for struct _class_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000631 llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000632
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000633 // IvarnfABITy - LLVM for struct _ivar_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000634 llvm::StructType *IvarnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000635
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000636 // IvarListnfABITy - LLVM for struct _ivar_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000637 llvm::StructType *IvarListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000638
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000639 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000640 llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000641
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000642 // ClassRonfABITy - LLVM for struct _class_ro_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000643 llvm::StructType *ClassRonfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000644
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000645 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000646 llvm::Type *ImpnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000647
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000648 // CategorynfABITy - LLVM for struct _category_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000649 llvm::StructType *CategorynfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000650
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000651 // New types for nonfragile abi messaging.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000652
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000653 // MessageRefTy - LLVM for:
654 // struct _message_ref_t {
655 // IMP messenger;
656 // SEL name;
657 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000658 llvm::StructType *MessageRefTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000659 // MessageRefCTy - clang type for struct _message_ref_t
660 QualType MessageRefCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000661
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000662 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000663 llvm::Type *MessageRefPtrTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000664 // MessageRefCPtrTy - clang type for struct _message_ref_t*
665 QualType MessageRefCPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000666
Fariborz Jahanian4e87c832009-02-05 01:13:09 +0000667 // MessengerTy - Type of the messenger (shown as IMP above)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000668 llvm::FunctionType *MessengerTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000669
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000670 // SuperMessageRefTy - LLVM for:
671 // struct _super_message_ref_t {
672 // SUPER_IMP messenger;
673 // SEL name;
674 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000675 llvm::StructType *SuperMessageRefTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000676
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000677 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000678 llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000679
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000680 llvm::Constant *getMessageSendFixupFn() {
681 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000682 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000683 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000684 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000685 "objc_msgSend_fixup");
686 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000687
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000688 llvm::Constant *getMessageSendFpretFixupFn() {
689 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000690 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000691 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000692 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000693 "objc_msgSend_fpret_fixup");
694 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000695
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000696 llvm::Constant *getMessageSendStretFixupFn() {
697 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000698 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000699 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000700 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000701 "objc_msgSend_stret_fixup");
702 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000703
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000704 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000705 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000706 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000707 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000708 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000709 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000710 "objc_msgSendSuper2_fixup");
711 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000712
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000713 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000714 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000715 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000716 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000717 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000718 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000719 "objc_msgSendSuper2_stret_fixup");
720 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000721
Chris Lattnera7c00b42009-04-22 02:15:23 +0000722 llvm::Constant *getObjCEndCatchFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000723 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000724 "objc_end_catch");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000725
Chris Lattnera7c00b42009-04-22 02:15:23 +0000726 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000727
Chris Lattnera7c00b42009-04-22 02:15:23 +0000728 llvm::Constant *getObjCBeginCatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000729 llvm::Type *params[] = { Int8PtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000730 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000731 params, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000732 "objc_begin_catch");
733 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +0000734
Chris Lattnera5f58b02011-07-09 17:41:47 +0000735 llvm::StructType *EHTypeTy;
736 llvm::Type *EHTypePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000737
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000738 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
739 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000740};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000741
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000742class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000743public:
744 // FIXME - accessibility
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000745 class GC_IVAR {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +0000746 public:
Eli Friedman8cbca202012-11-06 22:15:52 +0000747 unsigned ivar_bytepos;
748 unsigned ivar_size;
749 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000750 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar22b0ada2009-04-23 01:29:05 +0000751
752 // Allow sorting based on byte pos.
753 bool operator<(const GC_IVAR &b) const {
754 return ivar_bytepos < b.ivar_bytepos;
755 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000756 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000757
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000758 class SKIP_SCAN {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000759 public:
760 unsigned skip;
761 unsigned scan;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000762 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000763 : skip(_skip), scan(_scan) {}
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000764 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000765
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000766 /// opcode for captured block variables layout 'instructions'.
767 /// In the following descriptions, 'I' is the value of the immediate field.
768 /// (field following the opcode).
769 ///
770 enum BLOCK_LAYOUT_OPCODE {
771 /// An operator which affects how the following layout should be
772 /// interpreted.
773 /// I == 0: Halt interpretation and treat everything else as
774 /// a non-pointer. Note that this instruction is equal
775 /// to '\0'.
776 /// I != 0: Currently unused.
777 BLOCK_LAYOUT_OPERATOR = 0,
778
779 /// The next I+1 bytes do not contain a value of object pointer type.
780 /// Note that this can leave the stream unaligned, meaning that
781 /// subsequent word-size instructions do not begin at a multiple of
782 /// the pointer size.
783 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
784
785 /// The next I+1 words do not contain a value of object pointer type.
786 /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
787 /// when the required skip quantity is a multiple of the pointer size.
788 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
789
790 /// The next I+1 words are __strong pointers to Objective-C
791 /// objects or blocks.
792 BLOCK_LAYOUT_STRONG = 3,
793
794 /// The next I+1 words are pointers to __block variables.
795 BLOCK_LAYOUT_BYREF = 4,
796
797 /// The next I+1 words are __weak pointers to Objective-C
798 /// objects or blocks.
799 BLOCK_LAYOUT_WEAK = 5,
800
801 /// The next I+1 words are __unsafe_unretained pointers to
802 /// Objective-C objects or blocks.
803 BLOCK_LAYOUT_UNRETAINED = 6
804
805 /// The next I+1 words are block or object pointers with some
806 /// as-yet-unspecified ownership semantics. If we add more
807 /// flavors of ownership semantics, values will be taken from
808 /// this range.
809 ///
810 /// This is included so that older tools can at least continue
811 /// processing the layout past such things.
812 //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
813
814 /// All other opcodes are reserved. Halt interpretation and
815 /// treat everything else as opaque.
816 };
817
818 class RUN_SKIP {
819 public:
820 enum BLOCK_LAYOUT_OPCODE opcode;
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000821 CharUnits block_var_bytepos;
822 CharUnits block_var_size;
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000823 RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000824 CharUnits BytePos = CharUnits::Zero(),
825 CharUnits Size = CharUnits::Zero())
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +0000826 : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000827
828 // Allow sorting based on byte pos.
829 bool operator<(const RUN_SKIP &b) const {
830 return block_var_bytepos < b.block_var_bytepos;
831 }
832 };
833
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000834protected:
Owen Andersonae86c192009-07-13 04:10:07 +0000835 llvm::LLVMContext &VMContext;
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000836 // FIXME! May not be needing this after all.
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000837 unsigned ObjCABI;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000838
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000839 // gc ivar layout bitmap calculation helper caches.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000840 SmallVector<GC_IVAR, 16> SkipIvars;
841 SmallVector<GC_IVAR, 16> IvarsInfo;
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000842
843 // arc/mrr layout of captured block literal variables.
844 SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000845
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000846 /// LazySymbols - Symbols to generate a lazy reference for. See
847 /// DefinedSymbols and FinishModule().
Daniel Dunbard027a922009-09-07 00:20:42 +0000848 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000849
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000850 /// DefinedSymbols - External symbols which are defined by this
851 /// module. The symbols in this list and LazySymbols are used to add
852 /// special linker symbols which ensure that Objective-C modules are
853 /// linked properly.
Daniel Dunbard027a922009-09-07 00:20:42 +0000854 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000855
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000856 /// ClassNames - uniqued class names.
Daniel Dunbarb036db82008-08-13 03:21:16 +0000857 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000858
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000859 /// MethodVarNames - uniqued method variable names.
860 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000861
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000862 /// DefinedCategoryNames - list of category names in form Class_Category.
863 llvm::SetVector<std::string> DefinedCategoryNames;
864
Daniel Dunbarb036db82008-08-13 03:21:16 +0000865 /// MethodVarTypes - uniqued method type signatures. We have to use
866 /// a StringMap here because have no other unique reference.
867 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000868
Daniel Dunbar3c76cb52008-08-26 21:51:14 +0000869 /// MethodDefinitions - map of methods which have been defined in
870 /// this translation unit.
871 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000872
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000873 /// PropertyNames - uniqued method variable names.
874 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000875
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000876 /// ClassReferences - uniqued class references.
877 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000878
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000879 /// SelectorReferences - uniqued selector references.
880 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000881
Daniel Dunbarb036db82008-08-13 03:21:16 +0000882 /// Protocols - Protocols for which an objc_protocol structure has
883 /// been emitted. Forward declarations are handled by creating an
884 /// empty structure whose initializer is filled in when/if defined.
885 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000886
Daniel Dunbarc475d422008-10-29 22:36:39 +0000887 /// DefinedProtocols - Protocols which have actually been
888 /// defined. We should not need this, see FIXME in GenerateProtocol.
889 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000890
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000891 /// DefinedClasses - List of defined classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000892 SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000893
894 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000895 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000896
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000897 /// DefinedCategories - List of defined categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000898 SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000899
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000900 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000901 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000902
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000903 /// GetNameForMethod - Return a name for the given method.
904 /// \param[out] NameOut - The return value.
905 void GetNameForMethod(const ObjCMethodDecl *OMD,
906 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000907 SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000908
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000909 /// GetMethodVarName - Return a unique constant for the given
910 /// selector's name. The return value has type char *.
911 llvm::Constant *GetMethodVarName(Selector Sel);
912 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000913
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000914 /// GetMethodVarType - Return a unique constant for the given
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000915 /// method's type encoding string. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000916
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000917 // FIXME: This is a horrible name.
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000918 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
919 bool Extended = false);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000920 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000921
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000922 /// GetPropertyName - Return a unique constant for the given
923 /// name. The return value has type char *.
924 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000925
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000926 // FIXME: This can be dropped once string functions are unified.
927 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
928 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000929
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000930 /// GetClassName - Return a unique constant for the given selector's
931 /// name. The return value has type char *.
932 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000933
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000934 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
935
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000936 /// BuildIvarLayout - Builds ivar layout bitmap for the class
937 /// implementation for the __strong or __weak case.
938 ///
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000939 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
940 bool ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +0000941
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +0000942 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000943
Daniel Dunbar15bd8882009-05-03 14:10:34 +0000944 void BuildAggrIvarRecordLayout(const RecordType *RT,
Eli Friedman8cbca202012-11-06 22:15:52 +0000945 unsigned int BytePos, bool ForStrongLayout,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000946 bool &HasUnion);
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +0000947 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000948 const llvm::StructLayout *Layout,
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000949 const RecordDecl *RD,
Bill Wendlingf1a3fca2012-02-22 09:30:11 +0000950 ArrayRef<const FieldDecl*> RecFields,
Eli Friedman8cbca202012-11-06 22:15:52 +0000951 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahaniana123b642009-04-24 16:17:09 +0000952 bool &HasUnion);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000953
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000954 Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
Fariborz Jahanian2dd78192012-11-02 22:51:18 +0000955
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000956 void UpdateRunSkipBlockVars(bool IsByref,
957 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000958 CharUnits FieldOffset,
959 CharUnits FieldSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000960
961 void BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000962 CharUnits BytePos, bool &HasUnion,
963 bool ByrefLayout=false);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000964
965 void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
966 const RecordDecl *RD,
967 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000968 CharUnits BytePos, bool &HasUnion,
969 bool ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000970
Fariborz Jahanian23290b02012-11-01 18:32:55 +0000971 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
972
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000973 llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
974
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000975
Fariborz Jahanian01dff422009-03-05 19:17:31 +0000976 /// GetIvarLayoutName - Returns a unique constant for the given
977 /// ivar layout bitmap.
978 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
979 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000980
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000981 /// EmitPropertyList - Emit the given property list. The return
982 /// value has type PropertyListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000983 llvm::Constant *EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000984 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000985 const ObjCContainerDecl *OCD,
986 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000987
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000988 /// EmitProtocolMethodTypes - Generate the array of extended method type
989 /// strings. The return value has type Int8PtrPtrTy.
990 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +0000991 ArrayRef<llvm::Constant*> MethodTypes,
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000992 const ObjCCommonTypesHelper &ObjCTypes);
993
Fariborz Jahanian751c1e72009-12-12 21:26:21 +0000994 /// PushProtocolProperties - Push protocol's property on the input stack.
Bill Wendlinga515b582012-02-09 22:16:49 +0000995 void PushProtocolProperties(
996 llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000997 SmallVectorImpl<llvm::Constant*> &Properties,
Bill Wendlinga515b582012-02-09 22:16:49 +0000998 const Decl *Container,
999 const ObjCProtocolDecl *PROTO,
1000 const ObjCCommonTypesHelper &ObjCTypes);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00001001
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001002 /// GetProtocolRef - Return a reference to the internal protocol
1003 /// description, creating an empty one if it has not been
1004 /// defined. The return value has type ProtocolPtrTy.
1005 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +00001006
Daniel Dunbar30c65362009-03-09 20:09:19 +00001007 /// CreateMetadataVar - Create a global variable with internal
1008 /// linkage for use by the Objective-C runtime.
1009 ///
1010 /// This is a convenience wrapper which not only creates the
1011 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +00001012 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001013 ///
1014 /// \param Name - The variable name.
1015 /// \param Init - The variable initializer; this is also used to
1016 /// define the type of the variable.
1017 /// \param Section - The section the variable should go into, or 0.
1018 /// \param Align - The alignment for the variable, or 0.
1019 /// \param AddToUsed - Whether the variable should be added to
Daniel Dunbar4527d302009-04-14 17:42:51 +00001020 /// "llvm.used".
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001021 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00001022 llvm::Constant *Init,
1023 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001024 unsigned Align,
1025 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +00001026
John McCall9e8bb002011-05-14 03:10:52 +00001027 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1028 ReturnValueSlot Return,
1029 QualType ResultType,
1030 llvm::Value *Sel,
1031 llvm::Value *Arg0,
1032 QualType Arg0Ty,
1033 bool IsSuper,
1034 const CallArgList &CallArgs,
1035 const ObjCMethodDecl *OMD,
1036 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +00001037
Daniel Dunbar5e639272010-04-25 20:39:01 +00001038 /// EmitImageInfo - Emit the image info marker used to encode some module
1039 /// level information.
1040 void EmitImageInfo();
1041
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001042public:
Owen Andersonae86c192009-07-13 04:10:07 +00001043 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
John McCalla729c622012-02-17 03:33:10 +00001044 CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001045
David Chisnall481e3a82010-01-23 02:40:42 +00001046 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Ted Kremeneke65b0862012-03-06 20:05:56 +00001047
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001048 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
1049 const ObjCContainerDecl *CD=0);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001050
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001051 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001052
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001053 /// GetOrEmitProtocol - Get the protocol object for the given
1054 /// declaration, emitting it if necessary. The return value has type
1055 /// ProtocolPtrTy.
1056 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001057
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001058 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1059 /// object for the given declaration, emitting it if needed. These
1060 /// forward references will be filled in with empty bodies if no
1061 /// definition is seen. The return value has type ProtocolPtrTy.
1062 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCall351762c2011-02-07 10:33:21 +00001063 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1064 const CGBlockInfo &blockInfo);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00001065 virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1066 const CGBlockInfo &blockInfo);
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00001067
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00001068 virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1069 QualType T);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001070};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001071
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001072class CGObjCMac : public CGObjCCommonMac {
1073private:
1074 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001075
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001076 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001077 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001078 void EmitModuleInfo();
1079
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001080 /// EmitModuleSymols - Emit module symbols, the list of defined
1081 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001082 llvm::Constant *EmitModuleSymbols();
1083
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001084 /// FinishModule - Write out global data structures at the end of
1085 /// processing a translation unit.
1086 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +00001087
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001088 /// EmitClassExtension - Generate the class extension structure used
1089 /// to store the weak ivar layout and properties. The return value
1090 /// has type ClassExtensionPtrTy.
1091 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
1092
1093 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1094 /// for the given class.
John McCall882987f2013-02-28 19:01:20 +00001095 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001096 const ObjCInterfaceDecl *ID);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001097
John McCall882987f2013-02-28 19:01:20 +00001098 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00001099 IdentifierInfo *II);
1100
John McCall882987f2013-02-28 19:01:20 +00001101 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF);
John McCall31168b02011-06-15 23:02:42 +00001102
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001103 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1104 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001105
1106 /// EmitIvarList - Emit the ivar list for the given
1107 /// implementation. If ForClass is true the list of class ivars
1108 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1109 /// interface ivars will be emitted. The return value has type
1110 /// IvarListPtrTy.
1111 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00001112 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001113
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001114 /// EmitMetaClass - Emit a forward reference to the class structure
1115 /// for the metaclass of the given interface. The return value has
1116 /// type ClassPtrTy.
1117 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1118
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001119 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001120 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001121 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1122 llvm::Constant *Protocols,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001123 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001124
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001125 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001126
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001127 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001128
1129 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +00001130 /// implementation. The return value has type MethodListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001131 llvm::Constant *EmitMethodList(Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00001132 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001133 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001134
1135 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001136 /// method declarations.
Daniel Dunbarb036db82008-08-13 03:21:16 +00001137 /// - TypeName: The name for the type containing the methods.
Sylvestre Ledru33b5baf2012-09-27 10:16:10 +00001138 /// - IsProtocol: True iff these methods are for a protocol.
1139 /// - ClassMethds: True iff these are class methods.
Daniel Dunbarb036db82008-08-13 03:21:16 +00001140 /// - Required: When true, only "required" methods are
1141 /// listed. Similarly, when false only "optional" methods are
1142 /// listed. For classes this should always be true.
1143 /// - begin, end: The method list to output.
1144 ///
1145 /// The return value has type MethodDescriptionListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001146 llvm::Constant *EmitMethodDescList(Twine Name,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001147 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001148 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001149
Daniel Dunbarc475d422008-10-29 22:36:39 +00001150 /// GetOrEmitProtocol - Get the protocol object for the given
1151 /// declaration, emitting it if necessary. The return value has type
1152 /// ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001153 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001154
1155 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1156 /// object for the given declaration, emitting it if needed. These
1157 /// forward references will be filled in with empty bodies if no
1158 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001159 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001160
Daniel Dunbarb036db82008-08-13 03:21:16 +00001161 /// EmitProtocolExtension - Generate the protocol extension
1162 /// structure used to store optional instance and class methods, and
1163 /// protocol properties. The return value has type
1164 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001165 llvm::Constant *
1166 EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001167 ArrayRef<llvm::Constant*> OptInstanceMethods,
1168 ArrayRef<llvm::Constant*> OptClassMethods,
1169 ArrayRef<llvm::Constant*> MethodTypesExt);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001170
1171 /// EmitProtocolList - Generate the list of referenced
1172 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001173 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001174 ObjCProtocolDecl::protocol_iterator begin,
1175 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001176
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001177 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1178 /// for the given selector.
John McCall882987f2013-02-28 19:01:20 +00001179 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001180 bool lval=false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001181
1182public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001183 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001184
Fariborz Jahanian71394042009-01-23 23:53:38 +00001185 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001186
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001187 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001188 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001189 QualType ResultType,
1190 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001191 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001192 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001193 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001194 const ObjCMethodDecl *Method);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001195
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001196 virtual CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001197 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001198 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001199 QualType ResultType,
1200 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001201 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001202 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001203 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001204 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001205 const CallArgList &CallArgs,
1206 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001207
John McCall882987f2013-02-28 19:01:20 +00001208 virtual llvm::Value *GetClass(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001209 const ObjCInterfaceDecl *ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001210
John McCall882987f2013-02-28 19:01:20 +00001211 virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001212 bool lval = false);
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001213
1214 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1215 /// untyped one.
John McCall882987f2013-02-28 19:01:20 +00001216 virtual llvm::Value *GetSelector(CodeGenFunction &CGF,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001217 const ObjCMethodDecl *Method);
1218
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001219 virtual llvm::Constant *GetEHType(QualType T);
John McCall2ca705e2010-07-24 00:37:23 +00001220
Daniel Dunbar92992502008-08-15 22:20:32 +00001221 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001222
Daniel Dunbar92992502008-08-15 22:20:32 +00001223 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001224
Daniel Dunbarf3d3b012012-02-28 15:36:15 +00001225 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {}
David Chisnall92d436b2012-01-31 18:59:20 +00001226
John McCall882987f2013-02-28 19:01:20 +00001227 virtual llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00001228 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001229
Chris Lattnerd4808922009-03-22 21:03:39 +00001230 virtual llvm::Constant *GetPropertyGetFunction();
1231 virtual llvm::Constant *GetPropertySetFunction();
Ted Kremeneke65b0862012-03-06 20:05:56 +00001232 virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1233 bool copy);
David Chisnall168b80f2010-12-26 22:13:16 +00001234 virtual llvm::Constant *GetGetStructFunction();
1235 virtual llvm::Constant *GetSetStructFunction();
David Chisnall0d75e062012-12-17 18:54:24 +00001236 virtual llvm::Constant *GetCppAtomicObjectGetFunction();
1237 virtual llvm::Constant *GetCppAtomicObjectSetFunction();
Chris Lattnerd4808922009-03-22 21:03:39 +00001238 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001239
John McCallbd309292010-07-06 01:34:17 +00001240 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1241 const ObjCAtTryStmt &S);
1242 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1243 const ObjCAtSynchronizedStmt &S);
1244 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00001245 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00001246 const ObjCAtThrowStmt &S,
1247 bool ClearInsertionPoint=true);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001248 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001249 llvm::Value *AddrWeakObj);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001250 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001251 llvm::Value *src, llvm::Value *dst);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001252 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001253 llvm::Value *src, llvm::Value *dest,
1254 bool threadlocal = false);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00001255 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001256 llvm::Value *src, llvm::Value *dest,
1257 llvm::Value *ivarOffset);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001258 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1259 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001260 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1261 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001262 llvm::Value *size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001263
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001264 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1265 QualType ObjectTy,
1266 llvm::Value *BaseValue,
1267 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001268 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001269 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001270 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001271 const ObjCIvarDecl *Ivar);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001272
1273 /// GetClassGlobal - Return the global variable for the Objective-C
1274 /// class of the given name.
Rafael Espindola554256c2014-02-26 22:25:45 +00001275 llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
Craig Toppera798a9d2014-03-02 09:32:10 +00001276 bool Weak = false) override {
David Blaikie83d382b2011-09-23 05:06:16 +00001277 llvm_unreachable("CGObjCMac::GetClassGlobal");
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001278 }
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001279};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001280
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001281class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001282private:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001283 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001284 llvm::GlobalVariable* ObjCEmptyCacheVar;
1285 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001286
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001287 /// SuperClassReferences - uniqued super class references.
1288 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001289
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001290 /// MetaClassReferences - uniqued meta class references.
1291 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001292
1293 /// EHTypeReferences - uniqued class ehtype references.
1294 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001295
John McCall9e8bb002011-05-14 03:10:52 +00001296 /// VTableDispatchMethods - List of methods for which we generate
1297 /// vtable-based message dispatch.
1298 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001299
Fariborz Jahanian67260552009-11-17 21:37:35 +00001300 /// DefinedMetaClasses - List of defined meta-classes.
1301 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1302
John McCall9e8bb002011-05-14 03:10:52 +00001303 /// isVTableDispatchedSelector - Returns true if SEL is a
1304 /// vtable-based selector.
1305 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001306
Fariborz Jahanian71394042009-01-23 23:53:38 +00001307 /// FinishNonFragileABIModule - Write out global data structures at the end of
1308 /// processing a translation unit.
1309 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001310
Daniel Dunbar19573e72009-05-15 21:48:48 +00001311 /// AddModuleClassList - Add the given list of class pointers to the
1312 /// module with the provided symbol and section names.
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001313 void AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
Daniel Dunbar19573e72009-05-15 21:48:48 +00001314 const char *SymbolName,
1315 const char *SectionName);
1316
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001317 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1318 unsigned InstanceStart,
1319 unsigned InstanceSize,
1320 const ObjCImplementationDecl *ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001321 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001322 llvm::Constant *IsAGV,
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001323 llvm::Constant *SuperClassGV,
Fariborz Jahanian82208252009-01-31 00:59:10 +00001324 llvm::Constant *ClassRoGV,
Rafael Espindola554256c2014-02-26 22:25:45 +00001325 bool HiddenVisibility,
1326 bool Weak = false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001327
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001328 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001329
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00001330 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001331
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001332 /// EmitMethodList - Emit the method list for the given
1333 /// implementation. The return value has type MethodListnfABITy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001334 llvm::Constant *EmitMethodList(Twine Name,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001335 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001336 ArrayRef<llvm::Constant*> Methods);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001337 /// EmitIvarList - Emit the ivar list for the given
1338 /// implementation. If ForClass is true the list of class ivars
1339 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1340 /// interface ivars will be emitted. The return value has type
1341 /// IvarListnfABIPtrTy.
1342 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001343
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001344 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001345 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00001346 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001347
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001348 /// GetOrEmitProtocol - Get the protocol object for the given
1349 /// declaration, emitting it if necessary. The return value has type
1350 /// ProtocolPtrTy.
1351 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001352
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001353 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1354 /// object for the given declaration, emitting it if needed. These
1355 /// forward references will be filled in with empty bodies if no
1356 /// definition is seen. The return value has type ProtocolPtrTy.
1357 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001358
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001359 /// EmitProtocolList - Generate the list of referenced
1360 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001361 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001362 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001363 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001364
John McCall9e8bb002011-05-14 03:10:52 +00001365 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1366 ReturnValueSlot Return,
1367 QualType ResultType,
1368 Selector Sel,
1369 llvm::Value *Receiver,
1370 QualType Arg0Ty,
1371 bool IsSuper,
1372 const CallArgList &CallArgs,
1373 const ObjCMethodDecl *Method);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001374
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001375 /// GetClassGlobal - Return the global variable for the Objective-C
1376 /// class of the given name.
Rafael Espindola554256c2014-02-26 22:25:45 +00001377 llvm::GlobalVariable *GetClassGlobal(const std::string &Name,
Craig Toppera798a9d2014-03-02 09:32:10 +00001378 bool Weak = false) override;
Rafael Espindola554256c2014-02-26 22:25:45 +00001379
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001380 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001381 /// for the given class reference.
John McCall882987f2013-02-28 19:01:20 +00001382 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001383 const ObjCInterfaceDecl *ID);
John McCall31168b02011-06-15 23:02:42 +00001384
John McCall882987f2013-02-28 19:01:20 +00001385 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
Rafael Espindola554256c2014-02-26 22:25:45 +00001386 IdentifierInfo *II, bool Weak);
John McCall31168b02011-06-15 23:02:42 +00001387
John McCall882987f2013-02-28 19:01:20 +00001388 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001389
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001390 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1391 /// for the given super class reference.
John McCall882987f2013-02-28 19:01:20 +00001392 llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001393 const ObjCInterfaceDecl *ID);
1394
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001395 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1396 /// meta-data
John McCall882987f2013-02-28 19:01:20 +00001397 llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001398 const ObjCInterfaceDecl *ID);
1399
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001400 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1401 /// the given ivar.
1402 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001403 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001404 const ObjCInterfaceDecl *ID,
1405 const ObjCIvarDecl *Ivar);
1406
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001407 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1408 /// for the given selector.
John McCall882987f2013-02-28 19:01:20 +00001409 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001410 bool lval=false);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001411
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001412 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001413 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001414 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001415 bool ForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001416
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001417 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar15894b72009-04-07 05:48:37 +00001418 return "OBJC_METACLASS_$_";
1419 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001420
Daniel Dunbar15894b72009-04-07 05:48:37 +00001421 const char *getClassSymbolPrefix() const {
1422 return "OBJC_CLASS_$_";
1423 }
1424
Daniel Dunbar961202372009-05-03 12:57:56 +00001425 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001426 uint32_t &InstanceStart,
1427 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001428
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001429 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001430 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001431 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1432 return CGM.getContext().Selectors.getSelector(0, &II);
1433 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001434
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001435 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001436 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1437 return CGM.getContext().Selectors.getSelector(1, &II);
1438 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001439
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001440 /// ImplementationIsNonLazy - Check whether the given category or
1441 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001442 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001443
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001444 bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001445 const ObjCIvarDecl *IV) {
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001446 // Annotate the load as an invariant load iff inside an instance method
1447 // and ivar belongs to instance method's class and one of its super class.
1448 // This check is needed because the ivar offset is a lazily
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001449 // initialised value that may depend on objc_msgSend to perform a fixup on
1450 // the first message dispatch.
1451 //
1452 // An additional opportunity to mark the load as invariant arises when the
1453 // base of the ivar access is a parameter to an Objective C method.
1454 // However, because the parameters are not available in the current
1455 // interface, we cannot perform this check.
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001456 if (const ObjCMethodDecl *MD =
1457 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
Fariborz Jahanian7a583022014-03-04 22:57:32 +00001458 if (MD->isInstanceMethod())
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001459 if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
1460 return IV->getContainingInterface()->isSuperClassOf(ID);
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001461 return false;
1462 }
1463
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001464public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001465 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001466 // FIXME. All stubs for now!
1467 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001468
Fariborz Jahanian71394042009-01-23 23:53:38 +00001469 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001470 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001471 QualType ResultType,
1472 Selector Sel,
1473 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001474 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001475 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001476 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001477
1478 virtual CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001479 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001480 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001481 QualType ResultType,
1482 Selector Sel,
1483 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001484 bool isCategoryImpl,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001485 llvm::Value *Receiver,
1486 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001487 const CallArgList &CallArgs,
1488 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001489
John McCall882987f2013-02-28 19:01:20 +00001490 virtual llvm::Value *GetClass(CodeGenFunction &CGF,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001491 const ObjCInterfaceDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001492
John McCall882987f2013-02-28 19:01:20 +00001493 virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001494 bool lvalue = false)
John McCall882987f2013-02-28 19:01:20 +00001495 { return EmitSelector(CGF, Sel, lvalue); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001496
1497 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1498 /// untyped one.
John McCall882987f2013-02-28 19:01:20 +00001499 virtual llvm::Value *GetSelector(CodeGenFunction &CGF,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001500 const ObjCMethodDecl *Method)
John McCall882987f2013-02-28 19:01:20 +00001501 { return EmitSelector(CGF, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001502
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00001503 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001504
Fariborz Jahanian71394042009-01-23 23:53:38 +00001505 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
David Chisnall92d436b2012-01-31 18:59:20 +00001506
Daniel Dunbarf3d3b012012-02-28 15:36:15 +00001507 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {}
David Chisnall92d436b2012-01-31 18:59:20 +00001508
John McCall882987f2013-02-28 19:01:20 +00001509 virtual llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
Fariborz Jahanian097feda2009-01-30 18:58:59 +00001510 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001511
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001512 virtual llvm::Constant *GetEHType(QualType T);
John McCall2ca705e2010-07-24 00:37:23 +00001513
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001514 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001515 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001516 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001517 virtual llvm::Constant *GetPropertySetFunction() {
1518 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001519 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001520
Ted Kremeneke65b0862012-03-06 20:05:56 +00001521 virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1522 bool copy) {
1523 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1524 }
1525
David Chisnall168b80f2010-12-26 22:13:16 +00001526 virtual llvm::Constant *GetSetStructFunction() {
1527 return ObjCTypes.getCopyStructFn();
1528 }
1529 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001530 return ObjCTypes.getCopyStructFn();
1531 }
David Chisnall0d75e062012-12-17 18:54:24 +00001532 virtual llvm::Constant *GetCppAtomicObjectSetFunction() {
1533 return ObjCTypes.getCppAtomicObjectFunction();
1534 }
1535 virtual llvm::Constant *GetCppAtomicObjectGetFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001536 return ObjCTypes.getCppAtomicObjectFunction();
1537 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001538
Chris Lattnerd4808922009-03-22 21:03:39 +00001539 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001540 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001541 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001542
John McCallbd309292010-07-06 01:34:17 +00001543 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1544 const ObjCAtTryStmt &S);
1545 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1546 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001547 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00001548 const ObjCAtThrowStmt &S,
1549 bool ClearInsertionPoint=true);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001550 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001551 llvm::Value *AddrWeakObj);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001552 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001553 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001554 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001555 llvm::Value *src, llvm::Value *dest,
1556 bool threadlocal = false);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001557 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001558 llvm::Value *src, llvm::Value *dest,
1559 llvm::Value *ivarOffset);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001560 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001561 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001562 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1563 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001564 llvm::Value *size);
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001565 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1566 QualType ObjectTy,
1567 llvm::Value *BaseValue,
1568 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001569 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001570 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001571 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001572 const ObjCIvarDecl *Ivar);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001573};
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001574
1575/// A helper class for performing the null-initialization of a return
1576/// value.
1577struct NullReturnState {
1578 llvm::BasicBlock *NullBB;
John McCall3d1e2c92013-02-12 05:53:35 +00001579 NullReturnState() : NullBB(0) {}
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001580
John McCall3d1e2c92013-02-12 05:53:35 +00001581 /// Perform a null-check of the given receiver.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001582 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
John McCall3d1e2c92013-02-12 05:53:35 +00001583 // Make blocks for the null-receiver and call edges.
1584 NullBB = CGF.createBasicBlock("msgSend.null-receiver");
1585 llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001586
1587 // Check for a null receiver and, if there is one, jump to the
John McCall3d1e2c92013-02-12 05:53:35 +00001588 // null-receiver block. There's no point in trying to avoid it:
1589 // we're always going to put *something* there, because otherwise
1590 // we shouldn't have done this null-check in the first place.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001591 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1592 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1593
1594 // Otherwise, start performing the call.
1595 CGF.EmitBlock(callBB);
1596 }
1597
John McCall3d1e2c92013-02-12 05:53:35 +00001598 /// Complete the null-return operation. It is valid to call this
1599 /// regardless of whether 'init' has been called.
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001600 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
1601 const CallArgList &CallArgs,
1602 const ObjCMethodDecl *Method) {
John McCall3d1e2c92013-02-12 05:53:35 +00001603 // If we never had to do a null-check, just use the raw result.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001604 if (!NullBB) return result;
John McCall3d1e2c92013-02-12 05:53:35 +00001605
1606 // The continuation block. This will be left null if we don't have an
1607 // IP, which can happen if the method we're calling is marked noreturn.
1608 llvm::BasicBlock *contBB = 0;
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001609
John McCall3d1e2c92013-02-12 05:53:35 +00001610 // Finish the call path.
1611 llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
1612 if (callBB) {
1613 contBB = CGF.createBasicBlock("msgSend.cont");
1614 CGF.Builder.CreateBr(contBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001615 }
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001616
John McCall3d1e2c92013-02-12 05:53:35 +00001617 // Okay, start emitting the null-receiver block.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001618 CGF.EmitBlock(NullBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001619
John McCall3d1e2c92013-02-12 05:53:35 +00001620 // Release any consumed arguments we've got.
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001621 if (Method) {
1622 CallArgList::const_iterator I = CallArgs.begin();
1623 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1624 e = Method->param_end(); i != e; ++i, ++I) {
1625 const ParmVarDecl *ParamDecl = (*i);
1626 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1627 RValue RV = I->RV;
1628 assert(RV.isScalar() &&
1629 "NullReturnState::complete - arg not on object");
John McCallcdda29c2013-03-13 03:10:54 +00001630 CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001631 }
1632 }
1633 }
John McCall3d1e2c92013-02-12 05:53:35 +00001634
1635 // The phi code below assumes that we haven't needed any control flow yet.
1636 assert(CGF.Builder.GetInsertBlock() == NullBB);
1637
1638 // If we've got a void return, just jump to the continuation block.
1639 if (result.isScalar() && resultType->isVoidType()) {
1640 // No jumps required if the message-send was noreturn.
1641 if (contBB) CGF.EmitBlock(contBB);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001642 return result;
1643 }
1644
John McCall3d1e2c92013-02-12 05:53:35 +00001645 // If we've got a scalar return, build a phi.
1646 if (result.isScalar()) {
1647 // Derive the null-initialization value.
1648 llvm::Constant *null = CGF.CGM.EmitNullConstant(resultType);
1649
1650 // If no join is necessary, just flow out.
1651 if (!contBB) return RValue::get(null);
1652
1653 // Otherwise, build a phi.
1654 CGF.EmitBlock(contBB);
1655 llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2);
1656 phi->addIncoming(result.getScalarVal(), callBB);
1657 phi->addIncoming(null, NullBB);
1658 return RValue::get(phi);
1659 }
1660
1661 // If we've got an aggregate return, null the buffer out.
1662 // FIXME: maybe we should be doing things differently for all the
1663 // cases where the ABI has us returning (1) non-agg values in
1664 // memory or (2) agg values in registers.
1665 if (result.isAggregate()) {
1666 assert(result.isAggregate() && "null init of non-aggregate result?");
1667 CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
1668 if (contBB) CGF.EmitBlock(contBB);
1669 return result;
1670 }
1671
1672 // Complex types.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001673 CGF.EmitBlock(contBB);
John McCall3d1e2c92013-02-12 05:53:35 +00001674 CodeGenFunction::ComplexPairTy callResult = result.getComplexVal();
1675
1676 // Find the scalar type and its zero value.
1677 llvm::Type *scalarTy = callResult.first->getType();
1678 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1679
1680 // Build phis for both coordinates.
1681 llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2);
1682 real->addIncoming(callResult.first, callBB);
1683 real->addIncoming(scalarZero, NullBB);
1684 llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2);
1685 imag->addIncoming(callResult.second, callBB);
1686 imag->addIncoming(scalarZero, NullBB);
1687 return RValue::getComplex(real, imag);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001688 }
1689};
1690
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001691} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001692
1693/* *** Helper Functions *** */
1694
1695/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001696static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001697 llvm::Constant *C,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001698 unsigned idx0,
1699 unsigned idx1) {
1700 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001701 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1702 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001703 };
Jay Foaded8db7d2011-07-21 14:31:17 +00001704 return llvm::ConstantExpr::getGetElementPtr(C, Idxs);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001705}
1706
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001707/// hasObjCExceptionAttribute - Return true if this class or any super
1708/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001709static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001710 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001711 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001712 return true;
1713 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001714 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001715 return false;
1716}
1717
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001718/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001719
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001720CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001721 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001722 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001723 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001724}
1725
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001726/// GetClass - Return a reference to the class for the given interface
1727/// decl.
John McCall882987f2013-02-28 19:01:20 +00001728llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001729 const ObjCInterfaceDecl *ID) {
John McCall882987f2013-02-28 19:01:20 +00001730 return EmitClassRef(CGF, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001731}
1732
1733/// GetSelector - Return the pointer to the unique'd string for this selector.
John McCall882987f2013-02-28 19:01:20 +00001734llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001735 bool lval) {
John McCall882987f2013-02-28 19:01:20 +00001736 return EmitSelector(CGF, Sel, lval);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001737}
John McCall882987f2013-02-28 19:01:20 +00001738llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001739 *Method) {
John McCall882987f2013-02-28 19:01:20 +00001740 return EmitSelector(CGF, Method->getSelector());
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001741}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001742
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001743llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001744 if (T->isObjCIdType() ||
1745 T->isObjCQualifiedIdType()) {
1746 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001747 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001748 }
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001749 if (T->isObjCClassType() ||
1750 T->isObjCQualifiedClassType()) {
1751 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001752 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001753 }
1754 if (T->isObjCObjectPointerType())
1755 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
1756
John McCall2ca705e2010-07-24 00:37:23 +00001757 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall2ca705e2010-07-24 00:37:23 +00001758}
1759
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001760/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001761/*
1762 struct __builtin_CFString {
1763 const int *isa; // point to __CFConstantStringClassReference
1764 int flags;
1765 const char *str;
1766 long length;
1767 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001768*/
1769
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001770/// or Generate a constant NSString object.
1771/*
1772 struct __builtin_NSString {
1773 const int *isa; // point to __NSConstantStringClassReference
1774 const char *str;
1775 unsigned int length;
1776 };
1777*/
1778
Fariborz Jahanian71394042009-01-23 23:53:38 +00001779llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall481e3a82010-01-23 02:40:42 +00001780 const StringLiteral *SL) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001781 return (CGM.getLangOpts().NoConstantCFStrings == 0 ?
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001782 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian50c925f2010-10-19 17:19:29 +00001783 CGM.GetAddrOfConstantString(SL));
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001784}
1785
Ted Kremeneke65b0862012-03-06 20:05:56 +00001786enum {
1787 kCFTaggedObjectID_Integer = (1 << 1) + 1
1788};
1789
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001790/// Generates a message send where the super is the receiver. This is
1791/// a message send to self with special delivery semantics indicating
1792/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001793CodeGen::RValue
1794CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001795 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001796 QualType ResultType,
1797 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001798 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001799 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001800 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001801 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001802 const CodeGen::CallArgList &CallArgs,
1803 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001804 // Create and init a super structure; this is a (receiver, class)
1805 // pair we will pass to objc_msgSendSuper.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001806 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00001807 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001808 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001809 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001810 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001811 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001812
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001813 // If this is a class message the metaclass is passed as the target.
1814 llvm::Value *Target;
1815 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001816 if (isCategoryImpl) {
1817 // Message sent to 'super' in a class method defined in a category
1818 // implementation requires an odd treatment.
1819 // If we are in a class method, we must retrieve the
1820 // _metaclass_ for the current class, pointed at by
1821 // the class's "isa" pointer. The following assumes that
1822 // isa" is the first ivar in a class (which it must be).
John McCall882987f2013-02-28 19:01:20 +00001823 Target = EmitClassRef(CGF, Class->getSuperClass());
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001824 Target = CGF.Builder.CreateStructGEP(Target, 0);
1825 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00001826 } else {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001827 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1828 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1829 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1830 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001831 }
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00001832 }
1833 else if (isCategoryImpl)
John McCall882987f2013-02-28 19:01:20 +00001834 Target = EmitClassRef(CGF, Class->getSuperClass());
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00001835 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001836 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1837 ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1838 Target = CGF.Builder.CreateLoad(ClassPtr);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001839 }
Mike Stump18bb9282009-05-16 07:57:57 +00001840 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1841 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00001842 llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00001843 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00001844 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001845 CGF.Builder.CreateStore(Target,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001846 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall9e8bb002011-05-14 03:10:52 +00001847 return EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00001848 EmitSelector(CGF, Sel),
John McCall9e8bb002011-05-14 03:10:52 +00001849 ObjCSuper, ObjCTypes.SuperPtrCTy,
1850 true, CallArgs, Method, ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001851}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001852
1853/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001854CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001855 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001856 QualType ResultType,
1857 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001858 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001859 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001860 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001861 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00001862 return EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00001863 EmitSelector(CGF, Sel),
John McCall9e8bb002011-05-14 03:10:52 +00001864 Receiver, CGF.getContext().getObjCIdType(),
1865 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00001866}
1867
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001868CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00001869CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1870 ReturnValueSlot Return,
1871 QualType ResultType,
1872 llvm::Value *Sel,
1873 llvm::Value *Arg0,
1874 QualType Arg0Ty,
1875 bool IsSuper,
1876 const CallArgList &CallArgs,
1877 const ObjCMethodDecl *Method,
1878 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc722b852008-08-30 03:02:31 +00001879 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00001880 if (!IsSuper)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00001881 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman43dca6a2011-05-02 17:57:46 +00001882 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1883 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCall31168b02011-06-15 23:02:42 +00001884 ActualArgs.addFrom(CallArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001885
John McCalla729c622012-02-17 03:33:10 +00001886 // If we're calling a method, use the formal signature.
1887 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001888
Anders Carlsson280e61f12010-06-21 20:59:55 +00001889 if (Method)
Alp Toker314cc812014-01-25 16:55:45 +00001890 assert(CGM.getContext().getCanonicalType(Method->getReturnType()) ==
1891 CGM.getContext().getCanonicalType(ResultType) &&
Anders Carlsson280e61f12010-06-21 20:59:55 +00001892 "Result type mismatch!");
1893
John McCall5880fb82011-05-14 21:12:11 +00001894 NullReturnState nullReturn;
1895
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001896 llvm::Constant *Fn = NULL;
John McCalla729c622012-02-17 03:33:10 +00001897 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001898 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001899 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001900 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001901 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1902 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1903 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +00001904 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
1905 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
1906 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001907 } else {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001908 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001909 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001910 }
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001911
1912 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001913 if (CGM.getLangOpts().ObjCAutoRefCount && Method)
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001914 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1915 e = Method->param_end(); i != e; ++i) {
1916 const ParmVarDecl *ParamDecl = (*i);
1917 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1918 if (!nullReturn.NullBB)
1919 nullReturn.init(CGF, Arg0);
1920 requiresnullCheck = true;
1921 break;
1922 }
1923 }
1924
John McCalla729c622012-02-17 03:33:10 +00001925 Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
1926 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001927 return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
1928 requiresnullCheck ? Method : 0);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001929}
1930
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001931static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1932 if (FQT.isObjCGCStrong())
1933 return Qualifiers::Strong;
1934
John McCall31168b02011-06-15 23:02:42 +00001935 if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001936 return Qualifiers::Weak;
1937
Fariborz Jahanian430b35e2012-02-16 00:15:02 +00001938 // check for __unsafe_unretained
1939 if (FQT.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
1940 return Qualifiers::GCNone;
1941
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001942 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1943 return Qualifiers::Strong;
1944
1945 if (const PointerType *PT = FQT->getAs<PointerType>())
1946 return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1947
1948 return Qualifiers::GCNone;
1949}
1950
John McCall351762c2011-02-07 10:33:21 +00001951llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1952 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00001953
Chris Lattnerece04092012-02-07 00:39:47 +00001954 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001955 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
1956 !CGM.getLangOpts().ObjCAutoRefCount)
John McCall351762c2011-02-07 10:33:21 +00001957 return nullPtr;
1958
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001959 bool hasUnion = false;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001960 SkipIvars.clear();
1961 IvarsInfo.clear();
John McCallc8e01702013-04-16 22:48:15 +00001962 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
1963 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001964
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00001965 // __isa is the first field in block descriptor and must assume by runtime's
1966 // convention that it is GC'able.
Eli Friedman8cbca202012-11-06 22:15:52 +00001967 IvarsInfo.push_back(GC_IVAR(0, 1));
John McCall351762c2011-02-07 10:33:21 +00001968
1969 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1970
1971 // Calculate the basic layout of the block structure.
1972 const llvm::StructLayout *layout =
Micah Villmowdd31ca12012-10-08 16:25:52 +00001973 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
John McCall351762c2011-02-07 10:33:21 +00001974
1975 // Ignore the optional 'this' capture: C++ objects are not assumed
1976 // to be GC'ed.
1977
1978 // Walk the captured variables.
1979 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1980 ce = blockDecl->capture_end(); ci != ce; ++ci) {
1981 const VarDecl *variable = ci->getVariable();
1982 QualType type = variable->getType();
1983
1984 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1985
1986 // Ignore constant captures.
1987 if (capture.isConstant()) continue;
1988
Eli Friedman8cbca202012-11-06 22:15:52 +00001989 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
John McCall351762c2011-02-07 10:33:21 +00001990
1991 // __block variables are passed by their descriptor address.
1992 if (ci->isByRef()) {
Eli Friedman8cbca202012-11-06 22:15:52 +00001993 IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00001994 continue;
John McCall351762c2011-02-07 10:33:21 +00001995 }
1996
1997 assert(!type->isArrayType() && "array variable should not be caught");
1998 if (const RecordType *record = type->getAs<RecordType>()) {
1999 BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00002000 continue;
2001 }
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00002002
John McCall351762c2011-02-07 10:33:21 +00002003 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
Eli Friedman8cbca202012-11-06 22:15:52 +00002004 unsigned fieldSize = CGM.getContext().getTypeSize(type);
John McCall351762c2011-02-07 10:33:21 +00002005
2006 if (GCAttr == Qualifiers::Strong)
Eli Friedman8cbca202012-11-06 22:15:52 +00002007 IvarsInfo.push_back(GC_IVAR(fieldOffset,
2008 fieldSize / WordSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002009 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
Eli Friedman8cbca202012-11-06 22:15:52 +00002010 SkipIvars.push_back(GC_IVAR(fieldOffset,
2011 fieldSize / ByteSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002012 }
2013
2014 if (IvarsInfo.empty())
John McCall351762c2011-02-07 10:33:21 +00002015 return nullPtr;
2016
2017 // Sort on byte position; captures might not be allocated in order,
2018 // and unions can do funny things.
2019 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
2020 llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002021
2022 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00002023 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
David Blaikiebbafb8a2012-03-11 07:00:24 +00002024 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002025 printf("\n block variable layout for block: ");
Roman Divackye6377112012-09-06 15:59:27 +00002026 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling53136852012-02-07 09:06:01 +00002027 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002028 if (!(s[i] & 0xf0))
2029 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
2030 else
2031 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
2032 printf("\n");
2033 }
2034
2035 return C;
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00002036}
2037
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00002038/// getBlockCaptureLifetime - This routine returns life time of the captured
2039/// block variable for the purpose of block layout meta-data generation. FQT is
2040/// the type of the variable captured in the block.
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002041Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
2042 bool ByrefLayout) {
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002043 if (CGM.getLangOpts().ObjCAutoRefCount)
2044 return FQT.getObjCLifetime();
2045
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00002046 // MRR.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002047 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002048 return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002049
2050 return Qualifiers::OCL_None;
2051}
2052
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002053void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
2054 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002055 CharUnits FieldOffset,
2056 CharUnits FieldSize) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002057 // __block variables are passed by their descriptor address.
2058 if (IsByref)
2059 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002060 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002061 else if (LifeTime == Qualifiers::OCL_Strong)
2062 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002063 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002064 else if (LifeTime == Qualifiers::OCL_Weak)
2065 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002066 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002067 else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2068 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002069 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002070 else
2071 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2072 FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002073 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002074}
2075
2076void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2077 const RecordDecl *RD,
2078 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002079 CharUnits BytePos, bool &HasUnion,
2080 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002081 bool IsUnion = (RD && RD->isUnion());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002082 CharUnits MaxUnionSize = CharUnits::Zero();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002083 const FieldDecl *MaxField = 0;
2084 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002085 CharUnits MaxFieldOffset = CharUnits::Zero();
2086 CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002087
2088 if (RecFields.empty())
2089 return;
John McCallc8e01702013-04-16 22:48:15 +00002090 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002091
2092 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2093 const FieldDecl *Field = RecFields[i];
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002094 // Note that 'i' here is actually the field index inside RD of Field,
2095 // although this dependency is hidden.
2096 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002097 CharUnits FieldOffset =
2098 CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002099
2100 // Skip over unnamed or bitfields
2101 if (!Field->getIdentifier() || Field->isBitField()) {
2102 LastFieldBitfieldOrUnnamed = Field;
2103 LastBitfieldOrUnnamedOffset = FieldOffset;
2104 continue;
2105 }
2106
2107 LastFieldBitfieldOrUnnamed = 0;
2108 QualType FQT = Field->getType();
2109 if (FQT->isRecordType() || FQT->isUnionType()) {
2110 if (FQT->isUnionType())
2111 HasUnion = true;
2112
2113 BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
2114 BytePos + FieldOffset, HasUnion);
2115 continue;
2116 }
2117
2118 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2119 const ConstantArrayType *CArray =
2120 dyn_cast_or_null<ConstantArrayType>(Array);
2121 uint64_t ElCount = CArray->getSize().getZExtValue();
2122 assert(CArray && "only array with known element size is supported");
2123 FQT = CArray->getElementType();
2124 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2125 const ConstantArrayType *CArray =
2126 dyn_cast_or_null<ConstantArrayType>(Array);
2127 ElCount *= CArray->getSize().getZExtValue();
2128 FQT = CArray->getElementType();
2129 }
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002130 if (FQT->isRecordType() && ElCount) {
2131 int OldIndex = RunSkipBlockVars.size() - 1;
2132 const RecordType *RT = FQT->getAs<RecordType>();
2133 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
2134 HasUnion);
2135
2136 // Replicate layout information for each array element. Note that
2137 // one element is already done.
2138 uint64_t ElIx = 1;
2139 for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002140 CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002141 for (int i = OldIndex+1; i <= FirstIndex; ++i)
2142 RunSkipBlockVars.push_back(
2143 RUN_SKIP(RunSkipBlockVars[i].opcode,
2144 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2145 RunSkipBlockVars[i].block_var_size));
2146 }
2147 continue;
2148 }
2149 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002150 CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002151 if (IsUnion) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002152 CharUnits UnionIvarSize = FieldSize;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002153 if (UnionIvarSize > MaxUnionSize) {
2154 MaxUnionSize = UnionIvarSize;
2155 MaxField = Field;
2156 MaxFieldOffset = FieldOffset;
2157 }
2158 } else {
2159 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002160 getBlockCaptureLifetime(FQT, ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002161 BytePos + FieldOffset,
2162 FieldSize);
2163 }
2164 }
2165
2166 if (LastFieldBitfieldOrUnnamed) {
2167 if (LastFieldBitfieldOrUnnamed->isBitField()) {
2168 // Last field was a bitfield. Must update the info.
2169 uint64_t BitFieldSize
2170 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002171 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
Eli Friedman8cbca202012-11-06 22:15:52 +00002172 ((BitFieldSize % ByteSizeInBits) != 0);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002173 CharUnits Size = CharUnits::fromQuantity(UnsSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002174 Size += LastBitfieldOrUnnamedOffset;
2175 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002176 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2177 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002178 BytePos + LastBitfieldOrUnnamedOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002179 Size);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002180 } else {
2181 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2182 // Last field was unnamed. Must update skip info.
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002183 CharUnits FieldSize
2184 = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002185 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002186 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2187 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002188 BytePos + LastBitfieldOrUnnamedOffset,
2189 FieldSize);
2190 }
2191 }
2192
2193 if (MaxField)
2194 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002195 getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002196 BytePos + MaxFieldOffset,
2197 MaxUnionSize);
2198}
2199
2200void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002201 CharUnits BytePos,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002202 bool &HasUnion,
2203 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002204 const RecordDecl *RD = RT->getDecl();
2205 SmallVector<const FieldDecl*, 16> Fields;
2206 for (RecordDecl::field_iterator i = RD->field_begin(),
2207 e = RD->field_end(); i != e; ++i)
2208 Fields.push_back(*i);
2209 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
2210 const llvm::StructLayout *RecLayout =
2211 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2212
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002213 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002214}
2215
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002216/// InlineLayoutInstruction - This routine produce an inline instruction for the
2217/// block variable layout if it can. If not, it returns 0. Rules are as follow:
2218/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
2219/// an inline layout of value 0x0000000000000xyz is interpreted as follows:
2220/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
2221/// y captured object of BLOCK_LAYOUT_BYREF. Followed by
2222/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
2223/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
2224/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
2225uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2226 SmallVectorImpl<unsigned char> &Layout) {
2227 uint64_t Result = 0;
2228 if (Layout.size() <= 3) {
2229 unsigned size = Layout.size();
2230 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2231 unsigned char inst;
2232 enum BLOCK_LAYOUT_OPCODE opcode ;
2233 switch (size) {
2234 case 3:
2235 inst = Layout[0];
2236 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2237 if (opcode == BLOCK_LAYOUT_STRONG)
2238 strong_word_count = (inst & 0xF)+1;
2239 else
2240 return 0;
2241 inst = Layout[1];
2242 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2243 if (opcode == BLOCK_LAYOUT_BYREF)
2244 byref_word_count = (inst & 0xF)+1;
2245 else
2246 return 0;
2247 inst = Layout[2];
2248 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2249 if (opcode == BLOCK_LAYOUT_WEAK)
2250 weak_word_count = (inst & 0xF)+1;
2251 else
2252 return 0;
2253 break;
2254
2255 case 2:
2256 inst = Layout[0];
2257 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2258 if (opcode == BLOCK_LAYOUT_STRONG) {
2259 strong_word_count = (inst & 0xF)+1;
2260 inst = Layout[1];
2261 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2262 if (opcode == BLOCK_LAYOUT_BYREF)
2263 byref_word_count = (inst & 0xF)+1;
2264 else if (opcode == BLOCK_LAYOUT_WEAK)
2265 weak_word_count = (inst & 0xF)+1;
2266 else
2267 return 0;
2268 }
2269 else if (opcode == BLOCK_LAYOUT_BYREF) {
2270 byref_word_count = (inst & 0xF)+1;
2271 inst = Layout[1];
2272 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2273 if (opcode == BLOCK_LAYOUT_WEAK)
2274 weak_word_count = (inst & 0xF)+1;
2275 else
2276 return 0;
2277 }
2278 else
2279 return 0;
2280 break;
2281
2282 case 1:
2283 inst = Layout[0];
2284 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2285 if (opcode == BLOCK_LAYOUT_STRONG)
2286 strong_word_count = (inst & 0xF)+1;
2287 else if (opcode == BLOCK_LAYOUT_BYREF)
2288 byref_word_count = (inst & 0xF)+1;
2289 else if (opcode == BLOCK_LAYOUT_WEAK)
2290 weak_word_count = (inst & 0xF)+1;
2291 else
2292 return 0;
2293 break;
2294
2295 default:
2296 return 0;
2297 }
2298
2299 // Cannot inline when any of the word counts is 15. Because this is one less
2300 // than the actual work count (so 15 means 16 actual word counts),
2301 // and we can only display 0 thru 15 word counts.
2302 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2303 return 0;
2304
2305 unsigned count =
2306 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2307
2308 if (size == count) {
2309 if (strong_word_count)
2310 Result = strong_word_count;
2311 Result <<= 4;
2312 if (byref_word_count)
2313 Result += byref_word_count;
2314 Result <<= 4;
2315 if (weak_word_count)
2316 Result += weak_word_count;
2317 }
2318 }
2319 return Result;
2320}
2321
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002322llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
2323 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2324 if (RunSkipBlockVars.empty())
2325 return nullPtr;
John McCallc8e01702013-04-16 22:48:15 +00002326 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2327 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002328 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2329
2330 // Sort on byte position; captures might not be allocated in order,
2331 // and unions can do funny things.
2332 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2333 SmallVector<unsigned char, 16> Layout;
2334
2335 unsigned size = RunSkipBlockVars.size();
2336 for (unsigned i = 0; i < size; i++) {
2337 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2338 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2339 CharUnits end_byte_pos = start_byte_pos;
2340 unsigned j = i+1;
2341 while (j < size) {
2342 if (opcode == RunSkipBlockVars[j].opcode) {
2343 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2344 i++;
2345 }
2346 else
2347 break;
2348 }
2349 CharUnits size_in_bytes =
2350 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2351 if (j < size) {
2352 CharUnits gap =
2353 RunSkipBlockVars[j].block_var_bytepos -
2354 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2355 size_in_bytes += gap;
2356 }
2357 CharUnits residue_in_bytes = CharUnits::Zero();
2358 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2359 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2360 size_in_bytes -= residue_in_bytes;
2361 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2362 }
2363
2364 unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
2365 while (size_in_words >= 16) {
2366 // Note that value in imm. is one less that the actual
2367 // value. So, 0xf means 16 words follow!
2368 unsigned char inst = (opcode << 4) | 0xf;
2369 Layout.push_back(inst);
2370 size_in_words -= 16;
2371 }
2372 if (size_in_words > 0) {
2373 // Note that value in imm. is one less that the actual
2374 // value. So, we subtract 1 away!
2375 unsigned char inst = (opcode << 4) | (size_in_words-1);
2376 Layout.push_back(inst);
2377 }
2378 if (residue_in_bytes > CharUnits::Zero()) {
2379 unsigned char inst =
2380 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
2381 Layout.push_back(inst);
2382 }
2383 }
2384
2385 int e = Layout.size()-1;
2386 while (e >= 0) {
2387 unsigned char inst = Layout[e--];
2388 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2389 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2390 Layout.pop_back();
2391 else
2392 break;
2393 }
2394
2395 uint64_t Result = InlineLayoutInstruction(Layout);
2396 if (Result != 0) {
2397 // Block variable layout instruction has been inlined.
2398 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2399 if (ComputeByrefLayout)
2400 printf("\n Inline instruction for BYREF variable layout: ");
2401 else
2402 printf("\n Inline instruction for block variable layout: ");
Benjamin Kramerc2727942013-04-22 16:10:38 +00002403 printf("0x0%" PRIx64 "\n", Result);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002404 }
2405 if (WordSizeInBytes == 8) {
2406 const llvm::APInt Instruction(64, Result);
2407 return llvm::Constant::getIntegerValue(CGM.Int64Ty, Instruction);
2408 }
2409 else {
2410 const llvm::APInt Instruction(32, Result);
2411 return llvm::Constant::getIntegerValue(CGM.Int32Ty, Instruction);
2412 }
2413 }
2414
2415 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2416 Layout.push_back(inst);
2417 std::string BitMap;
2418 for (unsigned i = 0, e = Layout.size(); i != e; i++)
2419 BitMap += Layout[i];
2420
2421 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2422 if (ComputeByrefLayout)
2423 printf("\n BYREF variable layout: ");
2424 else
2425 printf("\n block variable layout: ");
2426 for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
2427 unsigned char inst = BitMap[i];
2428 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2429 unsigned delta = 1;
2430 switch (opcode) {
2431 case BLOCK_LAYOUT_OPERATOR:
2432 printf("BL_OPERATOR:");
2433 delta = 0;
2434 break;
2435 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2436 printf("BL_NON_OBJECT_BYTES:");
2437 break;
2438 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2439 printf("BL_NON_OBJECT_WORD:");
2440 break;
2441 case BLOCK_LAYOUT_STRONG:
2442 printf("BL_STRONG:");
2443 break;
2444 case BLOCK_LAYOUT_BYREF:
2445 printf("BL_BYREF:");
2446 break;
2447 case BLOCK_LAYOUT_WEAK:
2448 printf("BL_WEAK:");
2449 break;
2450 case BLOCK_LAYOUT_UNRETAINED:
2451 printf("BL_UNRETAINED:");
2452 break;
2453 }
2454 // Actual value of word count is one more that what is in the imm.
2455 // field of the instruction
2456 printf("%d", (inst & 0xf) + delta);
2457 if (i < e-1)
2458 printf(", ");
2459 else
2460 printf("\n");
2461 }
2462 }
2463
2464 llvm::GlobalVariable * Entry =
2465 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
2466 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
2467 "__TEXT,__objc_classname,cstring_literals", 1, true);
2468 return getConstantGEP(VMContext, Entry, 0, 0);
2469}
2470
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002471llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2472 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002473 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2474
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002475 RunSkipBlockVars.clear();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002476 bool hasUnion = false;
2477
John McCallc8e01702013-04-16 22:48:15 +00002478 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2479 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002480 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2481
2482 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2483
2484 // Calculate the basic layout of the block structure.
2485 const llvm::StructLayout *layout =
2486 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
2487
2488 // Ignore the optional 'this' capture: C++ objects are not assumed
2489 // to be GC'ed.
Fariborz Jahanian4cf177e2012-12-04 17:20:57 +00002490 if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
2491 UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
2492 blockInfo.BlockHeaderForcedGapOffset,
2493 blockInfo.BlockHeaderForcedGapSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002494 // Walk the captured variables.
2495 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
2496 ce = blockDecl->capture_end(); ci != ce; ++ci) {
2497 const VarDecl *variable = ci->getVariable();
2498 QualType type = variable->getType();
2499
2500 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2501
2502 // Ignore constant captures.
2503 if (capture.isConstant()) continue;
2504
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002505 CharUnits fieldOffset =
2506 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002507
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002508 assert(!type->isArrayType() && "array variable should not be caught");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002509 if (!ci->isByRef())
2510 if (const RecordType *record = type->getAs<RecordType>()) {
2511 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2512 continue;
2513 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002514 CharUnits fieldSize;
2515 if (ci->isByRef())
2516 fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2517 else
2518 fieldSize = CGM.getContext().getTypeSizeInChars(type);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002519 UpdateRunSkipBlockVars(ci->isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002520 fieldOffset, fieldSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002521 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002522 return getBitmapBlockLayout(false);
2523}
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002524
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002525
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002526llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2527 QualType T) {
2528 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2529 assert(!T->isArrayType() && "__block array variable should not be caught");
2530 CharUnits fieldOffset;
2531 RunSkipBlockVars.clear();
2532 bool hasUnion = false;
2533 if (const RecordType *record = T->getAs<RecordType>()) {
2534 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
2535 llvm::Constant *Result = getBitmapBlockLayout(true);
2536 return Result;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002537 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002538 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2539 return nullPtr;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002540}
2541
John McCall882987f2013-02-28 19:01:20 +00002542llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00002543 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00002544 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002545 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00002546 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2547
Owen Andersonade90fd2009-07-29 18:54:39 +00002548 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00002549 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002550}
2551
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002552void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00002553 // FIXME: We shouldn't need this, the protocol decl should contain enough
2554 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00002555 DefinedProtocols.insert(PD->getIdentifier());
2556
2557 // If we have generated a forward reference to this protocol, emit
2558 // it now. Otherwise do nothing, the protocol objects are lazily
2559 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002560 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00002561 GetOrEmitProtocol(PD);
2562}
2563
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002564llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002565 if (DefinedProtocols.count(PD->getIdentifier()))
2566 return GetOrEmitProtocol(PD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002567
Daniel Dunbarc475d422008-10-29 22:36:39 +00002568 return GetOrEmitProtocolRef(PD);
2569}
2570
Rafael Espindola21039aa2014-02-27 16:26:32 +00002571static void assertPrivateName(const llvm::GlobalValue *GV) {
2572 StringRef NameRef = GV->getName();
Rui Ueyamaad33e602014-02-27 20:50:04 +00002573 (void)NameRef;
Rafael Espindola21039aa2014-02-27 16:26:32 +00002574 assert(NameRef[0] == '\01' && (NameRef[1] == 'L' || NameRef[1] == 'l'));
Rafael Espindola5179a4e2014-02-27 19:01:11 +00002575 assert(GV->getVisibility() == llvm::GlobalValue::DefaultVisibility);
2576 assert(GV->getLinkage() == llvm::GlobalValue::PrivateLinkage);
Rafael Espindola21039aa2014-02-27 16:26:32 +00002577}
2578
Daniel Dunbarb036db82008-08-13 03:21:16 +00002579/*
Rafael Espindolaf9e1e5e2014-02-20 14:09:04 +00002580// Objective-C 1.0 extensions
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002581struct _objc_protocol {
2582struct _objc_protocol_extension *isa;
2583char *protocol_name;
2584struct _objc_protocol_list *protocol_list;
2585struct _objc__method_prototype_list *instance_methods;
2586struct _objc__method_prototype_list *class_methods
2587};
Daniel Dunbarb036db82008-08-13 03:21:16 +00002588
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002589See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00002590*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00002591llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00002592 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbarc475d422008-10-29 22:36:39 +00002593
2594 // Early exit if a defining object has already been generated.
2595 if (Entry && Entry->hasInitializer())
2596 return Entry;
2597
Douglas Gregora715bff2012-01-01 19:51:50 +00002598 // Use the protocol definition, if there is one.
2599 if (const ObjCProtocolDecl *Def = PD->getDefinition())
2600 PD = Def;
2601
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002602 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002603 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002604 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2605
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002606 // Construct method lists.
2607 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2608 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002609 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002610 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002611 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002612 ObjCMethodDecl *MD = *i;
2613 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002614 if (!C)
2615 return GetOrEmitProtocolRef(PD);
2616
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002617 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2618 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002619 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002620 } else {
2621 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002622 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002623 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002624 }
2625
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002626 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002627 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002628 ObjCMethodDecl *MD = *i;
2629 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002630 if (!C)
2631 return GetOrEmitProtocolRef(PD);
2632
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002633 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2634 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002635 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002636 } else {
2637 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002638 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002639 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002640 }
2641
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002642 MethodTypesExt.insert(MethodTypesExt.end(),
2643 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
2644
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002645 llvm::Constant *Values[] = {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002646 EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods,
2647 MethodTypesExt),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002648 GetClassName(PD->getIdentifier()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002649 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardec75f82008-08-21 21:57:41 +00002650 PD->protocol_begin(),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002651 PD->protocol_end()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002652 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002653 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002654 InstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002655 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002656 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002657 ClassMethods)
2658 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002659 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002660 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002661
Daniel Dunbarb036db82008-08-13 03:21:16 +00002662 if (Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002663 // Already created, fix the linkage and update the initializer.
Fariborz Jahanian1d5c1fa2014-03-03 21:53:57 +00002664 Entry->setLinkage(llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002665 Entry->setInitializer(Init);
2666 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002667 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002668 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00002669 llvm::GlobalValue::PrivateLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002670 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002671 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002672 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002673 // FIXME: Is this necessary? Why only for protocol?
2674 Entry->setAlignment(4);
John McCallf9582a72012-03-30 21:29:05 +00002675
2676 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002677 }
Rafael Espindola21039aa2014-02-27 16:26:32 +00002678 assertPrivateName(Entry);
Chris Lattnerf56501c2009-07-17 23:57:13 +00002679 CGM.AddUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00002680
2681 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002682}
2683
Daniel Dunbarc475d422008-10-29 22:36:39 +00002684llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002685 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
2686
2687 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002688 // We use the initializer as a marker of whether this is a forward
2689 // reference or not. At module finalization we add the empty
2690 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002691 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002692 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00002693 llvm::GlobalValue::PrivateLinkage,
Daniel Dunbarc475d422008-10-29 22:36:39 +00002694 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002695 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002696 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002697 // FIXME: Is this necessary? Why only for protocol?
2698 Entry->setAlignment(4);
2699 }
Rafael Espindola21039aa2014-02-27 16:26:32 +00002700 assertPrivateName(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002701
Daniel Dunbarb036db82008-08-13 03:21:16 +00002702 return Entry;
2703}
2704
2705/*
2706 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002707 uint32_t size;
2708 struct objc_method_description_list *optional_instance_methods;
2709 struct objc_method_description_list *optional_class_methods;
2710 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002711 const char ** extendedMethodTypes;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002712 };
2713*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002714llvm::Constant *
2715CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002716 ArrayRef<llvm::Constant*> OptInstanceMethods,
2717 ArrayRef<llvm::Constant*> OptClassMethods,
2718 ArrayRef<llvm::Constant*> MethodTypesExt) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002719 uint64_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00002720 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002721 llvm::Constant *Values[] = {
2722 llvm::ConstantInt::get(ObjCTypes.IntTy, Size),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002723 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002724 + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002725 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002726 OptInstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002727 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002728 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002729 OptClassMethods),
2730 EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002731 ObjCTypes),
2732 EmitProtocolMethodTypes("\01L_OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
2733 MethodTypesExt, ObjCTypes)
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002734 };
Daniel Dunbarb036db82008-08-13 03:21:16 +00002735
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002736 // Return null if no extension bits are used.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002737 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002738 Values[3]->isNullValue() && Values[4]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002739 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002740
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002741 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002742 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002743
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002744 // No special section, but goes in llvm.used
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002745 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002746 Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002747 0, 0, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002748}
2749
2750/*
2751 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002752 struct objc_protocol_list *next;
2753 long count;
2754 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002755 };
2756*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00002757llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002758CGObjCMac::EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00002759 ObjCProtocolDecl::protocol_iterator begin,
2760 ObjCProtocolDecl::protocol_iterator end) {
Dmitri Gribenkof8579502013-01-12 19:30:44 +00002761 SmallVector<llvm::Constant *, 16> ProtocolRefs;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002762
Daniel Dunbardec75f82008-08-21 21:57:41 +00002763 for (; begin != end; ++begin)
2764 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002765
2766 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002767 if (ProtocolRefs.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002768 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002769
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002770 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00002771 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002772
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002773 llvm::Constant *Values[3];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002774 // This field is only used by the runtime.
Owen Anderson0b75f232009-07-31 20:28:54 +00002775 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002776 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002777 ProtocolRefs.size() - 1);
2778 Values[2] =
2779 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
2780 ProtocolRefs.size()),
Daniel Dunbarb036db82008-08-13 03:21:16 +00002781 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002782
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002783 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002784 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002785 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002786 4, false);
Owen Andersonade90fd2009-07-29 18:54:39 +00002787 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002788}
2789
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002790void CGObjCCommonMac::
2791PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
Dmitri Gribenkof8579502013-01-12 19:30:44 +00002792 SmallVectorImpl<llvm::Constant *> &Properties,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002793 const Decl *Container,
2794 const ObjCProtocolDecl *PROTO,
2795 const ObjCCommonTypesHelper &ObjCTypes) {
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002796 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
2797 E = PROTO->protocol_end(); P != E; ++P)
2798 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
2799 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
2800 E = PROTO->prop_end(); I != E; ++I) {
David Blaikie40ed2972012-06-06 20:45:41 +00002801 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002802 if (!PropertySet.insert(PD->getIdentifier()))
2803 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002804 llvm::Constant *Prop[] = {
2805 GetPropertyName(PD->getIdentifier()),
2806 GetPropertyTypeString(PD, Container)
2807 };
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002808 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
2809 }
2810}
2811
Daniel Dunbarb036db82008-08-13 03:21:16 +00002812/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002813 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00002814 const char * const name;
2815 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002816 };
2817
2818 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002819 uint32_t entsize; // sizeof (struct _objc_property)
2820 uint32_t prop_count;
2821 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002822 };
2823*/
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002824llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002825 const Decl *Container,
2826 const ObjCContainerDecl *OCD,
2827 const ObjCCommonTypesHelper &ObjCTypes) {
Dmitri Gribenkof8579502013-01-12 19:30:44 +00002828 SmallVector<llvm::Constant *, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002829 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002830 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
2831 E = OCD->prop_end(); I != E; ++I) {
David Blaikie40ed2972012-06-06 20:45:41 +00002832 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002833 PropertySet.insert(PD->getIdentifier());
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002834 llvm::Constant *Prop[] = {
2835 GetPropertyName(PD->getIdentifier()),
2836 GetPropertyTypeString(PD, Container)
2837 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002838 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002839 Prop));
2840 }
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002841 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek0ef508d2010-09-01 01:21:15 +00002842 for (ObjCInterfaceDecl::all_protocol_iterator
2843 P = OID->all_referenced_protocol_begin(),
2844 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002845 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2846 ObjCTypes);
2847 }
2848 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
2849 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
2850 E = CD->protocol_end(); P != E; ++P)
2851 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2852 ObjCTypes);
2853 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002854
2855 // Return null for empty list.
2856 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002857 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002858
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002859 unsigned PropertySize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00002860 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002861 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002862 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
2863 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002864 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002865 Properties.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002866 Values[2] = llvm::ConstantArray::get(AT, Properties);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002867 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002868
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002869 llvm::GlobalVariable *GV =
2870 CreateMetadataVar(Name, Init,
2871 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002872 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002873 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002874 true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002875 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002876}
2877
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002878llvm::Constant *
2879CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
2880 ArrayRef<llvm::Constant*> MethodTypes,
2881 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002882 // Return null for empty list.
2883 if (MethodTypes.empty())
2884 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
2885
2886 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
2887 MethodTypes.size());
2888 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
2889
2890 llvm::GlobalVariable *GV =
2891 CreateMetadataVar(Name, Init,
2892 (ObjCABI == 2) ? "__DATA, __objc_const" : 0,
2893 (ObjCABI == 2) ? 8 : 4,
2894 true);
2895 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
2896}
2897
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002898/*
Daniel Dunbarb036db82008-08-13 03:21:16 +00002899 struct objc_method_description_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002900 int count;
2901 struct objc_method_description list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002902 };
2903*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002904llvm::Constant *
2905CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002906 llvm::Constant *Desc[] = {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002907 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002908 ObjCTypes.SelectorPtrTy),
2909 GetMethodVarType(MD)
2910 };
Douglas Gregora9d84932011-05-27 01:19:52 +00002911 if (!Desc[1])
2912 return 0;
2913
Owen Anderson0e0189d2009-07-27 22:29:56 +00002914 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002915 Desc);
2916}
Daniel Dunbarb036db82008-08-13 03:21:16 +00002917
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002918llvm::Constant *
2919CGObjCMac::EmitMethodDescList(Twine Name, const char *Section,
2920 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002921 // Return null for empty list.
2922 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002923 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002924
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002925 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002926 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002927 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002928 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002929 Values[1] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002930 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002931
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002932 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002933 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002934 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002935}
2936
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002937/*
2938 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002939 char *category_name;
2940 char *class_name;
2941 struct _objc_method_list *instance_methods;
2942 struct _objc_method_list *class_methods;
2943 struct _objc_protocol_list *protocols;
2944 uint32_t size; // <rdar://4585769>
2945 struct _objc_property_list *instance_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002946 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002947*/
Daniel Dunbar92992502008-08-15 22:20:32 +00002948void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00002949 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002950
Mike Stump18bb9282009-05-16 07:57:57 +00002951 // FIXME: This is poor design, the OCD should have a pointer to the category
2952 // decl. Additionally, note that Category can be null for the @implementation
2953 // w/o an @interface case. Sema should just create one for us as it does for
2954 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002955 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002956 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002957 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002958
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002959 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002960 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2961 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002962
Dmitri Gribenkof8579502013-01-12 19:30:44 +00002963 SmallVector<llvm::Constant *, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002964 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002965 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002966 // Instance methods should always be defined.
2967 InstanceMethods.push_back(GetMethodConstant(*i));
2968 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002969 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002970 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002971 // Class methods should always be defined.
2972 ClassMethods.push_back(GetMethodConstant(*i));
2973 }
2974
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002975 llvm::Constant *Values[7];
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002976 Values[0] = GetClassName(OCD->getIdentifier());
2977 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00002978 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002979 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002980 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002981 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002982 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002983 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002984 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002985 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002986 ClassMethods);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002987 if (Category) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002988 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002989 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002990 Category->protocol_begin(),
2991 Category->protocol_end());
2992 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002993 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002994 }
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002995 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002996
2997 // If there is no category @interface then there can be no properties.
2998 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002999 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00003000 OCD, Category, ObjCTypes);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003001 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00003002 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003003 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003004
Owen Anderson0e0189d2009-07-27 22:29:56 +00003005 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003006 Values);
3007
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003008 llvm::GlobalVariable *GV =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003009 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003010 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00003011 4, true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003012 DefinedCategories.push_back(GV);
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00003013 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003014 // method definition entries must be clear for next implementation.
3015 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003016}
3017
John McCallef19dbb2012-10-17 04:53:23 +00003018enum FragileClassFlags {
3019 FragileABI_Class_Factory = 0x00001,
3020 FragileABI_Class_Meta = 0x00002,
3021 FragileABI_Class_HasCXXStructors = 0x02000,
3022 FragileABI_Class_Hidden = 0x20000
3023};
3024
3025enum NonFragileClassFlags {
3026 /// Is a meta-class.
3027 NonFragileABI_Class_Meta = 0x00001,
3028
3029 /// Is a root class.
3030 NonFragileABI_Class_Root = 0x00002,
3031
3032 /// Has a C++ constructor and destructor.
3033 NonFragileABI_Class_HasCXXStructors = 0x00004,
3034
3035 /// Has hidden visibility.
3036 NonFragileABI_Class_Hidden = 0x00010,
3037
3038 /// Has the exception attribute.
3039 NonFragileABI_Class_Exception = 0x00020,
3040
3041 /// (Obsolete) ARC-specific: this class has a .release_ivars method
3042 NonFragileABI_Class_HasIvarReleaser = 0x00040,
3043
3044 /// Class implementation was compiled under ARC.
John McCall0d54a172012-10-17 04:53:31 +00003045 NonFragileABI_Class_CompiledByARC = 0x00080,
3046
3047 /// Class has non-trivial destructors, but zero-initialization is okay.
3048 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003049};
3050
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003051/*
3052 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003053 Class isa;
3054 Class super_class;
3055 const char *name;
3056 long version;
3057 long info;
3058 long instance_size;
3059 struct _objc_ivar_list *ivars;
3060 struct _objc_method_list *methods;
3061 struct _objc_cache *cache;
3062 struct _objc_protocol_list *protocols;
3063 // Objective-C 1.0 extensions (<rdr://4585769>)
3064 const char *ivar_layout;
3065 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003066 };
3067
3068 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003069*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003070void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003071 DefinedSymbols.insert(ID->getIdentifier());
3072
Chris Lattner86d7d912008-11-24 03:54:41 +00003073 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003074 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003075 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003076 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003077 llvm::Constant *Protocols =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003078 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003079 Interface->all_referenced_protocol_begin(),
3080 Interface->all_referenced_protocol_end());
John McCallef19dbb2012-10-17 04:53:23 +00003081 unsigned Flags = FragileABI_Class_Factory;
John McCall0d54a172012-10-17 04:53:31 +00003082 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCallef19dbb2012-10-17 04:53:23 +00003083 Flags |= FragileABI_Class_HasCXXStructors;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003084 unsigned Size =
Ken Dyckc8ae5502011-02-09 01:59:34 +00003085 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003086
3087 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00003088 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003089 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003090
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003091 SmallVector<llvm::Constant *, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003092 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003093 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003094 // Instance methods should always be defined.
3095 InstanceMethods.push_back(GetMethodConstant(*i));
3096 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003097 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003098 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003099 // Class methods should always be defined.
3100 ClassMethods.push_back(GetMethodConstant(*i));
3101 }
3102
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003103 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003104 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie40ed2972012-06-06 20:45:41 +00003105 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003106
3107 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3108 ObjCPropertyDecl *PD = PID->getPropertyDecl();
3109
3110 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
3111 if (llvm::Constant *C = GetMethodConstant(MD))
3112 InstanceMethods.push_back(C);
3113 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
3114 if (llvm::Constant *C = GetMethodConstant(MD))
3115 InstanceMethods.push_back(C);
3116 }
3117 }
3118
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003119 llvm::Constant *Values[12];
Daniel Dunbarccf61832009-05-03 08:56:52 +00003120 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003121 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003122 // Record a reference to the super class.
3123 LazySymbols.insert(Super->getIdentifier());
3124
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003125 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003126 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003127 ObjCTypes.ClassPtrTy);
3128 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00003129 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003130 }
3131 Values[ 2] = GetClassName(ID->getIdentifier());
3132 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003133 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3134 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3135 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003136 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003137 Values[ 7] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003138 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003139 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003140 InstanceMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003141 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003142 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003143 Values[ 9] = Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003144 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003145 Values[11] = EmitClassExtension(ID);
Owen Anderson0e0189d2009-07-27 22:29:56 +00003146 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003147 Values);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003148 std::string Name("\01L_OBJC_CLASS_");
3149 Name += ClassName;
3150 const char *Section = "__OBJC,__class,regular,no_dead_strip";
3151 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003152 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003153 if (GV) {
3154 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3155 "Forward metaclass reference has incorrect type.");
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003156 GV->setInitializer(Init);
3157 GV->setSection(Section);
3158 GV->setAlignment(4);
3159 CGM.AddUsedGlobal(GV);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003160 } else
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003161 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003162 assertPrivateName(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003163 DefinedClasses.push_back(GV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003164 // method definition entries must be clear for next implementation.
3165 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003166}
3167
3168llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3169 llvm::Constant *Protocols,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003170 ArrayRef<llvm::Constant*> Methods) {
John McCallef19dbb2012-10-17 04:53:23 +00003171 unsigned Flags = FragileABI_Class_Meta;
Micah Villmowdd31ca12012-10-08 16:25:52 +00003172 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003173
John McCall457a04e2010-10-22 21:05:15 +00003174 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003175 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003176
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003177 llvm::Constant *Values[12];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003178 // The isa for the metaclass is the root of the hierarchy.
3179 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3180 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3181 Root = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003182 Values[ 0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003183 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003184 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003185 // The super class for the metaclass is emitted as the name of the
3186 // super class. The runtime fixes this up to point to the
3187 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003188 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003189 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003190 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003191 ObjCTypes.ClassPtrTy);
3192 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00003193 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003194 }
3195 Values[ 2] = GetClassName(ID->getIdentifier());
3196 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003197 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3198 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3199 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003200 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003201 Values[ 7] =
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00003202 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003203 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003204 Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003205 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003206 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003207 Values[ 9] = Protocols;
3208 // ivar_layout for metaclass is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003209 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003210 // The class extension is always unused for metaclasses.
Owen Anderson0b75f232009-07-31 20:28:54 +00003211 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00003212 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003213 Values);
3214
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003215 std::string Name("\01L_OBJC_METACLASS_");
Benjamin Kramer1bbcbd02012-07-31 11:45:39 +00003216 Name += ID->getName();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003217
3218 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003219 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003220 if (GV) {
3221 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3222 "Forward metaclass reference has incorrect type.");
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003223 GV->setInitializer(Init);
3224 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00003225 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00003226 llvm::GlobalValue::PrivateLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00003227 Init, Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003228 }
Rafael Espindola21039aa2014-02-27 16:26:32 +00003229 assertPrivateName(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003230 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbarae333842009-03-09 22:18:41 +00003231 GV->setAlignment(4);
Chris Lattnerf56501c2009-07-17 23:57:13 +00003232 CGM.AddUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003233
3234 return GV;
3235}
3236
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003237llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00003238 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003239
Mike Stump18bb9282009-05-16 07:57:57 +00003240 // FIXME: Should we look these up somewhere other than the module. Its a bit
3241 // silly since we only generate these while processing an implementation, so
3242 // exactly one pointer would work if know when we entered/exitted an
3243 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003244
3245 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00003246 // Previously, metaclass with internal linkage may have been defined.
3247 // pass 'true' as 2nd argument so it is returned.
Rafael Espindola21039aa2014-02-27 16:26:32 +00003248 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3249 if (!GV)
3250 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00003251 llvm::GlobalValue::PrivateLinkage, 0, Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003252
3253 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3254 "Forward metaclass reference has incorrect type.");
3255 assertPrivateName(GV);
3256 return GV;
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003257}
3258
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003259llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
3260 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
Rafael Espindola21039aa2014-02-27 16:26:32 +00003261 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3262
3263 if (!GV)
3264 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00003265 llvm::GlobalValue::PrivateLinkage, 0, Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003266
3267 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3268 "Forward class metadata reference has incorrect type.");
3269 assertPrivateName(GV);
3270 return GV;
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003271}
3272
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003273/*
3274 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003275 uint32_t size;
3276 const char *weak_ivar_layout;
3277 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003278 };
3279*/
3280llvm::Constant *
3281CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003282 uint64_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00003283 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003284
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003285 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003286 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian6df69862009-04-22 23:00:43 +00003287 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003288 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00003289 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003290
3291 // Return null if no extension bits are used.
3292 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00003293 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003294
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003295 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00003296 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003297 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003298 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003299 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003300}
3301
3302/*
3303 struct objc_ivar {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003304 char *ivar_name;
3305 char *ivar_type;
3306 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003307 };
3308
3309 struct objc_ivar_list {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003310 int ivar_count;
3311 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003312 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003313*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003314llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003315 bool ForClass) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003316 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003317
3318 // When emitting the root class GCC emits ivar entries for the
3319 // actual class structure. It is not clear if we need to follow this
3320 // behavior; for now lets try and get away with not doing it. If so,
3321 // the cleanest solution would be to make up an ObjCInterfaceDecl
3322 // for the class.
3323 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00003324 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003325
Jordy Rosea91768e2011-07-22 02:08:32 +00003326 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003327
Jordy Rosea91768e2011-07-22 02:08:32 +00003328 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00003329 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00003330 // Ignore unnamed bit-fields.
3331 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003332 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003333 llvm::Constant *Ivar[] = {
3334 GetMethodVarName(IVD->getIdentifier()),
3335 GetMethodVarType(IVD),
3336 llvm::ConstantInt::get(ObjCTypes.IntTy,
Eli Friedman8cbca202012-11-06 22:15:52 +00003337 ComputeIvarBaseOffset(CGM, OID, IVD))
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003338 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00003339 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003340 }
3341
3342 // Return null for empty list.
3343 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003344 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003345
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003346 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003347 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00003348 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003349 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00003350 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003351 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003352
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003353 llvm::GlobalVariable *GV;
3354 if (ForClass)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003355 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003356 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00003357 4, true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003358 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003359 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003360 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003361 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003362 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003363}
3364
3365/*
3366 struct objc_method {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003367 SEL method_name;
3368 char *method_types;
3369 void *method;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003370 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003371
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003372 struct objc_method_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003373 struct objc_method_list *obsolete;
3374 int count;
3375 struct objc_method methods_list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003376 };
3377*/
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003378
3379/// GetMethodConstant - Return a struct objc_method constant for the
3380/// given method if it has been defined. The result is null if the
3381/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003382llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00003383 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003384 if (!Fn)
3385 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003386
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003387 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00003388 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003389 ObjCTypes.SelectorPtrTy),
3390 GetMethodVarType(MD),
3391 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
3392 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00003393 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003394}
3395
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003396llvm::Constant *CGObjCMac::EmitMethodList(Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003397 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003398 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003399 // Return null for empty list.
3400 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003401 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003402
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003403 llvm::Constant *Values[3];
Owen Anderson0b75f232009-07-31 20:28:54 +00003404 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003405 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00003406 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003407 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00003408 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003409 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003410
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003411 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003412 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003413}
3414
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00003415llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003416 const ObjCContainerDecl *CD) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003417 SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00003418 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003419
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00003420 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00003421 llvm::FunctionType *MethodTy =
John McCalla729c622012-02-17 03:33:10 +00003422 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003423 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00003424 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003425 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00003426 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003427 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003428 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003429
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003430 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003431}
3432
Daniel Dunbar30c65362009-03-09 20:09:19 +00003433llvm::GlobalVariable *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003434CGObjCCommonMac::CreateMetadataVar(Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00003435 llvm::Constant *Init,
3436 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003437 unsigned Align,
3438 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003439 llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003440 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00003441 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00003442 llvm::GlobalValue::PrivateLinkage, Init, Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003443 assertPrivateName(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003444 if (Section)
3445 GV->setSection(Section);
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003446 if (Align)
3447 GV->setAlignment(Align);
3448 if (AddToUsed)
Chris Lattnerf56501c2009-07-17 23:57:13 +00003449 CGM.AddUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003450 return GV;
3451}
3452
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003453llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003454 // Abuse this interface function as a place to finalize.
3455 FinishModule();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003456 return NULL;
3457}
3458
Chris Lattnerd4808922009-03-22 21:03:39 +00003459llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003460 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003461}
3462
Chris Lattnerd4808922009-03-22 21:03:39 +00003463llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003464 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003465}
3466
Ted Kremeneke65b0862012-03-06 20:05:56 +00003467llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
3468 bool copy) {
3469 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
3470}
3471
David Chisnall168b80f2010-12-26 22:13:16 +00003472llvm::Constant *CGObjCMac::GetGetStructFunction() {
3473 return ObjCTypes.getCopyStructFn();
3474}
3475llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00003476 return ObjCTypes.getCopyStructFn();
3477}
3478
David Chisnall0d75e062012-12-17 18:54:24 +00003479llvm::Constant *CGObjCMac::GetCppAtomicObjectGetFunction() {
3480 return ObjCTypes.getCppAtomicObjectFunction();
3481}
3482llvm::Constant *CGObjCMac::GetCppAtomicObjectSetFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00003483 return ObjCTypes.getCppAtomicObjectFunction();
3484}
3485
Chris Lattnerd4808922009-03-22 21:03:39 +00003486llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003487 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00003488}
3489
John McCallbd309292010-07-06 01:34:17 +00003490void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
3491 return EmitTryOrSynchronizedStmt(CGF, S);
3492}
3493
3494void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
3495 const ObjCAtSynchronizedStmt &S) {
3496 return EmitTryOrSynchronizedStmt(CGF, S);
3497}
3498
John McCall65bea082010-07-21 06:59:36 +00003499namespace {
John McCallcda666c2010-07-21 07:22:38 +00003500 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00003501 const Stmt &S;
John McCall2dd7d442010-08-04 05:59:32 +00003502 llvm::Value *SyncArgSlot;
John McCall65bea082010-07-21 06:59:36 +00003503 llvm::Value *CallTryExitVar;
3504 llvm::Value *ExceptionData;
3505 ObjCTypesHelper &ObjCTypes;
3506 PerformFragileFinally(const Stmt *S,
John McCall2dd7d442010-08-04 05:59:32 +00003507 llvm::Value *SyncArgSlot,
John McCall65bea082010-07-21 06:59:36 +00003508 llvm::Value *CallTryExitVar,
3509 llvm::Value *ExceptionData,
3510 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00003511 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00003512 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
3513
John McCall30317fd2011-07-12 20:27:29 +00003514 void Emit(CodeGenFunction &CGF, Flags flags) {
John McCall65bea082010-07-21 06:59:36 +00003515 // Check whether we need to call objc_exception_try_exit.
3516 // In optimized code, this branch will always be folded.
3517 llvm::BasicBlock *FinallyCallExit =
3518 CGF.createBasicBlock("finally.call_exit");
3519 llvm::BasicBlock *FinallyNoCallExit =
3520 CGF.createBasicBlock("finally.no_call_exit");
3521 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
3522 FinallyCallExit, FinallyNoCallExit);
3523
3524 CGF.EmitBlock(FinallyCallExit);
John McCall882987f2013-02-28 19:01:20 +00003525 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
3526 ExceptionData);
John McCall65bea082010-07-21 06:59:36 +00003527
3528 CGF.EmitBlock(FinallyNoCallExit);
3529
3530 if (isa<ObjCAtTryStmt>(S)) {
3531 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00003532 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
John McCall638d4f52013-04-03 00:56:07 +00003533 // Don't try to do the @finally if this is an EH cleanup.
3534 if (flags.isForEHCleanup()) return;
3535
John McCallcebe0ca2010-08-11 00:16:14 +00003536 // Save the current cleanup destination in case there's
3537 // control flow inside the finally statement.
3538 llvm::Value *CurCleanupDest =
3539 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
3540
John McCall65bea082010-07-21 06:59:36 +00003541 CGF.EmitStmt(FinallyStmt->getFinallyBody());
3542
John McCallcebe0ca2010-08-11 00:16:14 +00003543 if (CGF.HaveInsertPoint()) {
3544 CGF.Builder.CreateStore(CurCleanupDest,
3545 CGF.getNormalCleanupDestSlot());
3546 } else {
3547 // Currently, the end of the cleanup must always exist.
3548 CGF.EnsureInsertPoint();
3549 }
3550 }
John McCall65bea082010-07-21 06:59:36 +00003551 } else {
3552 // Emit objc_sync_exit(expr); as finally's sole statement for
3553 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00003554 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall882987f2013-02-28 19:01:20 +00003555 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg);
John McCall65bea082010-07-21 06:59:36 +00003556 }
3557 }
3558 };
John McCall42227ed2010-07-31 23:20:56 +00003559
3560 class FragileHazards {
3561 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003562 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00003563 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
3564
3565 llvm::InlineAsm *ReadHazard;
3566 llvm::InlineAsm *WriteHazard;
3567
3568 llvm::FunctionType *GetAsmFnType();
3569
3570 void collectLocals();
3571 void emitReadHazard(CGBuilderTy &Builder);
3572
3573 public:
3574 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00003575
John McCall42227ed2010-07-31 23:20:56 +00003576 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00003577 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003578 };
3579}
3580
3581/// Create the fragile-ABI read and write hazards based on the current
3582/// state of the function, which is presumed to be immediately prior
3583/// to a @try block. These hazards are used to maintain correct
3584/// semantics in the face of optimization and the fragile ABI's
3585/// cavalier use of setjmp/longjmp.
3586FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
3587 collectLocals();
3588
3589 if (Locals.empty()) return;
3590
3591 // Collect all the blocks in the function.
3592 for (llvm::Function::iterator
3593 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
3594 BlocksBeforeTry.insert(&*I);
3595
3596 llvm::FunctionType *AsmFnTy = GetAsmFnType();
3597
3598 // Create a read hazard for the allocas. This inhibits dead-store
3599 // optimizations and forces the values to memory. This hazard is
3600 // inserted before any 'throwing' calls in the protected scope to
3601 // reflect the possibility that the variables might be read from the
3602 // catch block if the call throws.
3603 {
3604 std::string Constraint;
3605 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3606 if (I) Constraint += ',';
3607 Constraint += "*m";
3608 }
3609
3610 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3611 }
3612
3613 // Create a write hazard for the allocas. This inhibits folding
3614 // loads across the hazard. This hazard is inserted at the
3615 // beginning of the catch path to reflect the possibility that the
3616 // variables might have been written within the protected scope.
3617 {
3618 std::string Constraint;
3619 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3620 if (I) Constraint += ',';
3621 Constraint += "=*m";
3622 }
3623
3624 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3625 }
3626}
3627
3628/// Emit a write hazard at the current location.
3629void FragileHazards::emitWriteHazard() {
3630 if (Locals.empty()) return;
3631
John McCall882987f2013-02-28 19:01:20 +00003632 CGF.EmitNounwindRuntimeCall(WriteHazard, Locals);
John McCall42227ed2010-07-31 23:20:56 +00003633}
3634
John McCall42227ed2010-07-31 23:20:56 +00003635void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
3636 assert(!Locals.empty());
John McCall882987f2013-02-28 19:01:20 +00003637 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
3638 call->setDoesNotThrow();
3639 call->setCallingConv(CGF.getRuntimeCC());
John McCall42227ed2010-07-31 23:20:56 +00003640}
3641
3642/// Emit read hazards in all the protected blocks, i.e. all the blocks
3643/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00003644void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00003645 if (Locals.empty()) return;
3646
3647 CGBuilderTy Builder(CGF.getLLVMContext());
3648
3649 // Iterate through all blocks, skipping those prior to the try.
3650 for (llvm::Function::iterator
3651 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
3652 llvm::BasicBlock &BB = *FI;
3653 if (BlocksBeforeTry.count(&BB)) continue;
3654
3655 // Walk through all the calls in the block.
3656 for (llvm::BasicBlock::iterator
3657 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
3658 llvm::Instruction &I = *BI;
3659
3660 // Ignore instructions that aren't non-intrinsic calls.
3661 // These are the only calls that can possibly call longjmp.
3662 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
3663 if (isa<llvm::IntrinsicInst>(I))
3664 continue;
3665
3666 // Ignore call sites marked nounwind. This may be questionable,
3667 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
3668 llvm::CallSite CS(&I);
3669 if (CS.doesNotThrow()) continue;
3670
John McCall2dd7d442010-08-04 05:59:32 +00003671 // Insert a read hazard before the call. This will ensure that
3672 // any writes to the locals are performed before making the
3673 // call. If the call throws, then this is sufficient to
3674 // guarantee correctness as long as it doesn't also write to any
3675 // locals.
John McCall42227ed2010-07-31 23:20:56 +00003676 Builder.SetInsertPoint(&BB, BI);
3677 emitReadHazard(Builder);
3678 }
3679 }
3680}
3681
3682static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
3683 if (V) S.insert(V);
3684}
3685
3686void FragileHazards::collectLocals() {
3687 // Compute a set of allocas to ignore.
3688 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
3689 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
3690 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00003691
3692 // Collect all the allocas currently in the function. This is
3693 // probably way too aggressive.
3694 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
3695 for (llvm::BasicBlock::iterator
3696 I = Entry.begin(), E = Entry.end(); I != E; ++I)
3697 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
3698 Locals.push_back(&*I);
3699}
3700
3701llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003702 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00003703 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
3704 tys[i] = Locals[i]->getType();
3705 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00003706}
3707
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003708/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003709
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003710 Objective-C setjmp-longjmp (sjlj) Exception Handling
3711 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003712
John McCallbd309292010-07-06 01:34:17 +00003713 A catch buffer is a setjmp buffer plus:
3714 - a pointer to the exception that was caught
3715 - a pointer to the previous exception data buffer
3716 - two pointers of reserved storage
3717 Therefore catch buffers form a stack, with a pointer to the top
3718 of the stack kept in thread-local storage.
3719
3720 objc_exception_try_enter pushes a catch buffer onto the EH stack.
3721 objc_exception_try_exit pops the given catch buffer, which is
3722 required to be the top of the EH stack.
3723 objc_exception_throw pops the top of the EH stack, writes the
3724 thrown exception into the appropriate field, and longjmps
3725 to the setjmp buffer. It crashes the process (with a printf
3726 and an abort()) if there are no catch buffers on the stack.
3727 objc_exception_extract just reads the exception pointer out of the
3728 catch buffer.
3729
3730 There's no reason an implementation couldn't use a light-weight
3731 setjmp here --- something like __builtin_setjmp, but API-compatible
3732 with the heavyweight setjmp. This will be more important if we ever
3733 want to implement correct ObjC/C++ exception interactions for the
3734 fragile ABI.
3735
3736 Note that for this use of setjmp/longjmp to be correct, we may need
3737 to mark some local variables volatile: if a non-volatile local
3738 variable is modified between the setjmp and the longjmp, it has
3739 indeterminate value. For the purposes of LLVM IR, it may be
3740 sufficient to make loads and stores within the @try (to variables
3741 declared outside the @try) volatile. This is necessary for
3742 optimized correctness, but is not currently being done; this is
3743 being tracked as rdar://problem/8160285
3744
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003745 The basic framework for a @try-catch-finally is as follows:
3746 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003747 objc_exception_data d;
3748 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00003749 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003750
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003751 objc_exception_try_enter(&d);
3752 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003753 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003754 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003755 // exception path
3756 id _caught = objc_exception_extract(&d);
3757
3758 // enter new try scope for handlers
3759 if (!setjmp(d.jmp_buf)) {
3760 ... match exception and execute catch blocks ...
3761
3762 // fell off end, rethrow.
3763 _rethrow = _caught;
3764 ... jump-through-finally to finally_rethrow ...
3765 } else {
3766 // exception in catch block
3767 _rethrow = objc_exception_extract(&d);
3768 _call_try_exit = false;
3769 ... jump-through-finally to finally_rethrow ...
3770 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003771 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003772 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003773
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003774 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00003775 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003776 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00003777
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003778 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003779 ... dispatch to finally destination ...
3780
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003781 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003782 objc_exception_throw(_rethrow);
3783
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003784 finally_end:
3785 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003786
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003787 This framework differs slightly from the one gcc uses, in that gcc
3788 uses _rethrow to determine if objc_exception_try_exit should be called
3789 and if the object should be rethrown. This breaks in the face of
3790 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003791
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003792 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003793
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003794 - If there are no catch blocks, then we avoid emitting the second
3795 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003796
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003797 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
3798 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003799
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003800 - FIXME: If there is no @finally block we can do a few more
3801 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003802
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003803 Rethrows and Jumps-Through-Finally
3804 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003805
John McCallbd309292010-07-06 01:34:17 +00003806 '@throw;' is supported by pushing the currently-caught exception
3807 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003808
John McCallbd309292010-07-06 01:34:17 +00003809 Branches through the @finally block are handled with an ordinary
3810 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
3811 exceptions are not compatible with C++ exceptions, and this is
3812 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003813
John McCallbd309292010-07-06 01:34:17 +00003814 @synchronized(expr) { stmt; } is emitted as if it were:
3815 id synch_value = expr;
3816 objc_sync_enter(synch_value);
3817 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003818*/
3819
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00003820void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
3821 const Stmt &S) {
3822 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00003823
3824 // A destination for the fall-through edges of the catch handlers to
3825 // jump to.
3826 CodeGenFunction::JumpDest FinallyEnd =
3827 CGF.getJumpDestInCurrentScope("finally.end");
3828
3829 // A destination for the rethrow edge of the catch handlers to jump
3830 // to.
3831 CodeGenFunction::JumpDest FinallyRethrow =
3832 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003833
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003834 // For @synchronized, call objc_sync_enter(sync.expr). The
3835 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00003836 // @synchronized. We can't avoid a temp here because we need the
3837 // value to be preserved. If the backend ever does liveness
3838 // correctly after setjmp, this will be unnecessary.
3839 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003840 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00003841 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003842 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
3843 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00003844 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);
John McCall2dd7d442010-08-04 05:59:32 +00003845
3846 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
3847 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003848 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003849
John McCall2dd7d442010-08-04 05:59:32 +00003850 // Allocate memory for the setjmp buffer. This needs to be kept
3851 // live throughout the try and catch blocks.
3852 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
3853 "exceptiondata.ptr");
3854
John McCall42227ed2010-07-31 23:20:56 +00003855 // Create the fragile hazards. Note that this will not capture any
3856 // of the allocas required for exception processing, but will
3857 // capture the current basic block (which extends all the way to the
3858 // setjmp call) as "before the @try".
3859 FragileHazards Hazards(CGF);
3860
John McCallbd309292010-07-06 01:34:17 +00003861 // Create a flag indicating whether the cleanup needs to call
3862 // objc_exception_try_exit. This is true except when
3863 // - no catches match and we're branching through the cleanup
3864 // just to rethrow the exception, or
3865 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00003866 // The setjmp-safety rule here is that we should always store to this
3867 // variable in a place that dominates the branch through the cleanup
3868 // without passing through any setjmps.
John McCallbd309292010-07-06 01:34:17 +00003869 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlssonda0e4562009-02-07 21:26:04 +00003870 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003871
John McCall9916e3f2010-10-04 23:42:51 +00003872 // A slot containing the exception to rethrow. Only needed when we
3873 // have both a @catch and a @finally.
3874 llvm::Value *PropagatingExnVar = 0;
3875
John McCallbd309292010-07-06 01:34:17 +00003876 // Push a normal cleanup to leave the try scope.
John McCall638d4f52013-04-03 00:56:07 +00003877 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00003878 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00003879 CallTryExitVar,
3880 ExceptionData,
3881 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00003882
3883 // Enter a try block:
3884 // - Call objc_exception_try_enter to push ExceptionData on top of
3885 // the EH stack.
John McCall882987f2013-02-28 19:01:20 +00003886 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData);
John McCallbd309292010-07-06 01:34:17 +00003887
3888 // - Call setjmp on the exception data buffer.
3889 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
3890 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
3891 llvm::Value *SetJmpBuffer =
Jay Foad040dd822011-07-22 08:16:57 +00003892 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
John McCallbd309292010-07-06 01:34:17 +00003893 llvm::CallInst *SetJmpResult =
John McCall882987f2013-02-28 19:01:20 +00003894 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003895 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00003896
3897 // If setjmp returned 0, enter the protected block; otherwise,
3898 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00003899 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3900 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00003901 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00003902 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3903 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003904
John McCallbd309292010-07-06 01:34:17 +00003905 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003906 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00003907 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003908 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00003909 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00003910
3911 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003912
John McCallbd309292010-07-06 01:34:17 +00003913 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00003914 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003915
John McCall42227ed2010-07-31 23:20:56 +00003916 // Don't optimize loads of the in-scope locals across this point.
3917 Hazards.emitWriteHazard();
3918
John McCallbd309292010-07-06 01:34:17 +00003919 // For a @synchronized (or a @try with no catches), just branch
3920 // through the cleanup to the rethrow block.
3921 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
3922 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00003923 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003924 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00003925
3926 // Otherwise, we have to match against the caught exceptions.
3927 } else {
John McCall2dd7d442010-08-04 05:59:32 +00003928 // Retrieve the exception object. We may emit multiple blocks but
3929 // nothing can cross this so the value is already in SSA form.
3930 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00003931 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
3932 ExceptionData, "caught");
John McCall2dd7d442010-08-04 05:59:32 +00003933
John McCallbd309292010-07-06 01:34:17 +00003934 // Push the exception to rethrow onto the EH value stack for the
3935 // benefit of any @throws in the handlers.
3936 CGF.ObjCEHValueStack.push_back(Caught);
3937
Douglas Gregor96c79492010-04-23 22:50:49 +00003938 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003939
John McCall2dd7d442010-08-04 05:59:32 +00003940 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallbd309292010-07-06 01:34:17 +00003941
John McCall2dd7d442010-08-04 05:59:32 +00003942 llvm::BasicBlock *CatchBlock = 0;
3943 llvm::BasicBlock *CatchHandler = 0;
3944 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00003945 // Save the currently-propagating exception before
3946 // objc_exception_try_enter clears the exception slot.
3947 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
3948 "propagating_exception");
3949 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
3950
John McCall2dd7d442010-08-04 05:59:32 +00003951 // Enter a new exception try block (in case a @catch block
3952 // throws an exception).
John McCall882987f2013-02-28 19:01:20 +00003953 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
3954 ExceptionData);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003955
John McCall2dd7d442010-08-04 05:59:32 +00003956 llvm::CallInst *SetJmpResult =
John McCall882987f2013-02-28 19:01:20 +00003957 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(),
3958 SetJmpBuffer, "setjmp.result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003959 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003960
John McCall2dd7d442010-08-04 05:59:32 +00003961 llvm::Value *Threw =
3962 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3963
3964 CatchBlock = CGF.createBasicBlock("catch");
3965 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3966 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3967
3968 CGF.EmitBlock(CatchBlock);
3969 }
3970
3971 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003972
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003973 // Handle catch list. As a special case we check if everything is
3974 // matched and avoid generating code for falling off the end if
3975 // so.
3976 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00003977 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3978 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003979
Douglas Gregor46a572b2010-04-26 16:46:50 +00003980 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff7cae42b2009-07-10 23:34:53 +00003981 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar523208f2008-09-27 07:36:24 +00003982
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003983 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003984 if (!CatchParam) {
3985 AllMatched = true;
3986 } else {
John McCall9dd450b2009-09-21 23:43:11 +00003987 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003988
John McCallbd309292010-07-06 01:34:17 +00003989 // catch(id e) always matches under this ABI, since only
3990 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00003991 // FIXME: For the time being we also match id<X>; this should
3992 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00003993 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003994 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003995 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003996
John McCallbd309292010-07-06 01:34:17 +00003997 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003998 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00003999 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4000
Anders Carlsson9396a892008-09-11 09:15:33 +00004001 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00004002 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004003 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00004004
4005 // These types work out because ConvertType(id) == i8*.
Steve Naroff371b8fb2009-03-03 19:52:17 +00004006 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson9396a892008-09-11 09:15:33 +00004007 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004008
Anders Carlsson9396a892008-09-11 09:15:33 +00004009 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004010
4011 // The scope of the catch variable ends right here.
4012 CatchVarCleanups.ForceCleanup();
4013
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004014 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004015 break;
4016 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004017
Steve Naroff7cae42b2009-07-10 23:34:53 +00004018 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00004019 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00004020
4021 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00004022 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
4023 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004024
4025 // Check if the @catch block matches the exception object.
John McCall882987f2013-02-28 19:01:20 +00004026 llvm::Value *Class = EmitClassRef(CGF, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004027
John McCall882987f2013-02-28 19:01:20 +00004028 llvm::Value *matchArgs[] = { Class, Caught };
John McCallbd309292010-07-06 01:34:17 +00004029 llvm::CallInst *Match =
John McCall882987f2013-02-28 19:01:20 +00004030 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(),
4031 matchArgs, "match");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004032
John McCallbd309292010-07-06 01:34:17 +00004033 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
4034 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004035
4036 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00004037 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004038
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004039 // Emit the @catch block.
4040 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00004041
4042 // Collect any cleanups for the catch variable. The scope lasts until
4043 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00004044 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00004045
John McCall1c9c3fd2010-10-15 04:57:14 +00004046 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004047 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004048
John McCallbd309292010-07-06 01:34:17 +00004049 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004050 llvm::Value *Tmp =
4051 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004052 CGF.ConvertType(CatchParam->getType()));
Steve Naroff371b8fb2009-03-03 19:52:17 +00004053 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004054
Anders Carlsson9396a892008-09-11 09:15:33 +00004055 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004056
4057 // We're done with the catch variable.
4058 CatchVarCleanups.ForceCleanup();
4059
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004060 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004061
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004062 CGF.EmitBlock(NextCatchBlock);
4063 }
4064
John McCallbd309292010-07-06 01:34:17 +00004065 CGF.ObjCEHValueStack.pop_back();
4066
John McCall2dd7d442010-08-04 05:59:32 +00004067 // If nothing wanted anything to do with the caught exception,
4068 // kill the extract call.
4069 if (Caught->use_empty())
4070 Caught->eraseFromParent();
4071
4072 if (!AllMatched)
4073 CGF.EmitBranchThroughCleanup(FinallyRethrow);
4074
4075 if (HasFinally) {
4076 // Emit the exception handler for the @catch blocks.
4077 CGF.EmitBlock(CatchHandler);
4078
4079 // In theory we might now need a write hazard, but actually it's
4080 // unnecessary because there's no local-accessing code between
4081 // the try's write hazard and here.
4082 //Hazards.emitWriteHazard();
4083
John McCall9916e3f2010-10-04 23:42:51 +00004084 // Extract the new exception and save it to the
4085 // propagating-exception slot.
4086 assert(PropagatingExnVar);
4087 llvm::CallInst *NewCaught =
John McCall882987f2013-02-28 19:01:20 +00004088 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
4089 ExceptionData, "caught");
John McCall9916e3f2010-10-04 23:42:51 +00004090 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4091
John McCall2dd7d442010-08-04 05:59:32 +00004092 // Don't pop the catch handler; the throw already did.
4093 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004094 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004095 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004096 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004097
John McCall42227ed2010-07-31 23:20:56 +00004098 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00004099 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004100
John McCallbd309292010-07-06 01:34:17 +00004101 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00004102 CGF.Builder.restoreIP(TryFallthroughIP);
4103 if (CGF.HaveInsertPoint())
4104 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00004105 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00004106 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004107
John McCallbd309292010-07-06 01:34:17 +00004108 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00004109 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00004110 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00004111 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00004112 // If we have a propagating-exception variable, check it.
4113 llvm::Value *PropagatingExn;
4114 if (PropagatingExnVar) {
4115 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00004116
John McCall9916e3f2010-10-04 23:42:51 +00004117 // Otherwise, just look in the buffer for the exception to throw.
4118 } else {
4119 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004120 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
4121 ExceptionData);
John McCall9916e3f2010-10-04 23:42:51 +00004122 PropagatingExn = Caught;
4123 }
4124
John McCall882987f2013-02-28 19:01:20 +00004125 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(),
4126 PropagatingExn);
John McCallbd309292010-07-06 01:34:17 +00004127 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00004128 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004129
John McCall42227ed2010-07-31 23:20:56 +00004130 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004131}
4132
4133void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004134 const ObjCAtThrowStmt &S,
4135 bool ClearInsertionPoint) {
Anders Carlssone005aa12008-09-09 16:16:55 +00004136 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004137
Anders Carlssone005aa12008-09-09 16:16:55 +00004138 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00004139 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004140 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004141 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00004142 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004143 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004144 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00004145 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00004146 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004147
John McCall882987f2013-02-28 19:01:20 +00004148 CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
John McCallbd309292010-07-06 01:34:17 +00004149 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004150 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004151
4152 // Clear the insertion point to indicate we are in unreachable code.
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004153 if (ClearInsertionPoint)
4154 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004155}
4156
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004157/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004158/// object: objc_read_weak (id *src)
4159///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004160llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004161 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004162 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004163 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
4164 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4165 ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004166 llvm::Value *read_weak =
4167 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
4168 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00004169 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004170 return read_weak;
4171}
4172
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004173/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4174/// objc_assign_weak (id src, id *dst)
4175///
4176void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004177 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004178 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004179 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004180 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004181 assert(Size <= 8 && "does not support size > 8");
4182 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004183 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004184 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4185 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004186 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4187 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004188 llvm::Value *args[] = { src, dst };
4189 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4190 args, "weakassign");
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004191 return;
4192}
4193
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004194/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4195/// objc_assign_global (id src, id *dst)
4196///
4197void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00004198 llvm::Value *src, llvm::Value *dst,
4199 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004200 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004201 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004202 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004203 assert(Size <= 8 && "does not support size > 8");
4204 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004205 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004206 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4207 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004208 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4209 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004210 llvm::Value *args[] = { src, dst };
Fariborz Jahanian217af242010-07-20 20:30:03 +00004211 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00004212 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4213 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00004214 else
John McCall882987f2013-02-28 19:01:20 +00004215 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4216 args, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004217 return;
4218}
4219
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004220/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004221/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004222///
4223void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004224 llvm::Value *src, llvm::Value *dst,
4225 llvm::Value *ivarOffset) {
4226 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00004227 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004228 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004229 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004230 assert(Size <= 8 && "does not support size > 8");
4231 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004232 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004233 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4234 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004235 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4236 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004237 llvm::Value *args[] = { src, dst, ivarOffset };
4238 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004239 return;
4240}
4241
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004242/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
4243/// objc_assign_strongCast (id src, id *dst)
4244///
4245void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004246 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004247 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004248 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004249 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004250 assert(Size <= 8 && "does not support size > 8");
4251 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004252 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004253 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4254 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004255 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4256 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004257 llvm::Value *args[] = { src, dst };
4258 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
4259 args, "weakassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004260 return;
4261}
4262
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004263void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004264 llvm::Value *DestPtr,
4265 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00004266 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004267 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
4268 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall882987f2013-02-28 19:01:20 +00004269 llvm::Value *args[] = { DestPtr, SrcPtr, size };
4270 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004271}
4272
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004273/// EmitObjCValueForIvar - Code Gen for ivar reference.
4274///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004275LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4276 QualType ObjectTy,
4277 llvm::Value *BaseValue,
4278 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004279 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00004280 const ObjCInterfaceDecl *ID =
4281 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00004282 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4283 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004284}
4285
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004286llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00004287 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004288 const ObjCIvarDecl *Ivar) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004289 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4290 return llvm::ConstantInt::get(
4291 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
4292 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004293}
4294
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004295/* *** Private Interface *** */
4296
4297/// EmitImageInfo - Emit the image info marker used to encode some module
4298/// level information.
4299///
4300/// See: <rdr://4810609&4810587&4810587>
4301/// struct IMAGE_INFO {
4302/// unsigned version;
4303/// unsigned flags;
4304/// };
4305enum ImageInfoFlags {
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004306 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004307 eImageInfo_GarbageCollected = (1 << 1),
4308 eImageInfo_GCOnly = (1 << 2),
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004309 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
Daniel Dunbar75e909f2009-04-20 07:11:47 +00004310
Daniel Dunbar5e639272010-04-25 20:39:01 +00004311 // A flag indicating that the module has no instances of a @synthesize of a
4312 // superclass variable. <rdar://problem/6803242>
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004313 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004314 eImageInfo_ImageIsSimulated = (1 << 5)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004315};
4316
Daniel Dunbar5e639272010-04-25 20:39:01 +00004317void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004318 unsigned version = 0; // Version is unused?
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004319 const char *Section = (ObjCABI == 1) ?
4320 "__OBJC, __image_info,regular" :
4321 "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004322
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004323 // Generate module-level named metadata to convey this information to the
4324 // linker and code-gen.
4325 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004326
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004327 // Add the ObjC ABI version to the module flags.
4328 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
4329 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
4330 version);
4331 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
4332 llvm::MDString::get(VMContext,Section));
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004333
David Blaikiebbafb8a2012-03-11 07:00:24 +00004334 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004335 // Non-GC overrides those files which specify GC.
4336 Mod.addModuleFlag(llvm::Module::Override,
4337 "Objective-C Garbage Collection", (uint32_t)0);
4338 } else {
4339 // Add the ObjC garbage collection value.
4340 Mod.addModuleFlag(llvm::Module::Error,
4341 "Objective-C Garbage Collection",
4342 eImageInfo_GarbageCollected);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004343
David Blaikiebbafb8a2012-03-11 07:00:24 +00004344 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004345 // Add the ObjC GC Only value.
4346 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
4347 eImageInfo_GCOnly);
4348
4349 // Require that GC be specified and set to eImageInfo_GarbageCollected.
4350 llvm::Value *Ops[2] = {
4351 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
4352 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
4353 eImageInfo_GarbageCollected)
4354 };
4355 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
4356 llvm::MDNode::get(VMContext, Ops));
4357 }
4358 }
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004359
4360 // Indicate whether we're compiling this to run on a simulator.
4361 const llvm::Triple &Triple = CGM.getTarget().getTriple();
Cameron Esfahani556d91e2013-09-14 01:09:11 +00004362 if (Triple.isiOS() &&
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004363 (Triple.getArch() == llvm::Triple::x86 ||
4364 Triple.getArch() == llvm::Triple::x86_64))
4365 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
4366 eImageInfo_ImageIsSimulated);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004367}
4368
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004369// struct objc_module {
4370// unsigned long version;
4371// unsigned long size;
4372// const char *name;
4373// Symtab symtab;
4374// };
4375
4376// FIXME: Get from somewhere
4377static const int ModuleVersion = 7;
4378
4379void CGObjCMac::EmitModuleInfo() {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004380 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004381
Benjamin Kramer22d24c22011-10-15 12:20:02 +00004382 llvm::Constant *Values[] = {
4383 llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion),
4384 llvm::ConstantInt::get(ObjCTypes.LongTy, Size),
4385 // This used to be the filename, now it is unused. <rdr://4327263>
4386 GetClassName(&CGM.getContext().Idents.get("")),
4387 EmitModuleSymbols()
4388 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004389 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson0e0189d2009-07-27 22:29:56 +00004390 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004391 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00004392 4, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004393}
4394
4395llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004396 unsigned NumClasses = DefinedClasses.size();
4397 unsigned NumCategories = DefinedCategories.size();
4398
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004399 // Return null if no symbols were defined.
4400 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00004401 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004402
Chris Lattnere64d7ba2011-06-20 04:01:35 +00004403 llvm::Constant *Values[5];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004404 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Anderson0b75f232009-07-31 20:28:54 +00004405 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004406 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
4407 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004408
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004409 // The runtime expects exactly the list of defined classes followed
4410 // by the list of defined categories, in a single array.
Chris Lattner3def9ae2012-02-06 22:16:34 +00004411 SmallVector<llvm::Constant*, 8> Symbols(NumClasses + NumCategories);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004412 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00004413 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004414 ObjCTypes.Int8PtrTy);
4415 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004416 Symbols[NumClasses + i] =
Owen Andersonade90fd2009-07-29 18:54:39 +00004417 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004418 ObjCTypes.Int8PtrTy);
4419
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004420 Values[4] =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004421 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00004422 Symbols.size()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004423 Symbols);
4424
Chris Lattnere64d7ba2011-06-20 04:01:35 +00004425 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004426
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004427 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004428 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
4429 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00004430 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00004431 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004432}
4433
John McCall882987f2013-02-28 19:01:20 +00004434llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
4435 IdentifierInfo *II) {
John McCall31168b02011-06-15 23:02:42 +00004436 LazySymbols.insert(II);
4437
4438 llvm::GlobalVariable *&Entry = ClassReferences[II];
4439
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004440 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004441 llvm::Constant *Casted =
John McCall31168b02011-06-15 23:02:42 +00004442 llvm::ConstantExpr::getBitCast(GetClassName(II),
4443 ObjCTypes.ClassPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004444 Entry =
John McCall31168b02011-06-15 23:02:42 +00004445 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
4446 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
4447 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004448 }
John McCall31168b02011-06-15 23:02:42 +00004449
John McCall882987f2013-02-28 19:01:20 +00004450 return CGF.Builder.CreateLoad(Entry);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004451}
4452
John McCall882987f2013-02-28 19:01:20 +00004453llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00004454 const ObjCInterfaceDecl *ID) {
John McCall882987f2013-02-28 19:01:20 +00004455 return EmitClassRefFromId(CGF, ID->getIdentifier());
John McCall31168b02011-06-15 23:02:42 +00004456}
4457
John McCall882987f2013-02-28 19:01:20 +00004458llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00004459 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
John McCall882987f2013-02-28 19:01:20 +00004460 return EmitClassRefFromId(CGF, II);
John McCall31168b02011-06-15 23:02:42 +00004461}
4462
John McCall882987f2013-02-28 19:01:20 +00004463llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00004464 bool lvalue) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004465 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004466
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004467 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004468 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00004469 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004470 ObjCTypes.SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004471 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004472 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
4473 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00004474 4, true);
Michael Gottesman5c205962013-02-05 23:08:45 +00004475 Entry->setExternallyInitialized(true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004476 }
4477
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00004478 if (lvalue)
4479 return Entry;
John McCall882987f2013-02-28 19:01:20 +00004480 return CGF.Builder.CreateLoad(Entry);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004481}
4482
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004483llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00004484 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004485
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004486 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004487 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004488 llvm::ConstantDataArray::getString(VMContext,
4489 Ident->getNameStart()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004490 ((ObjCABI == 2) ?
4491 "__TEXT,__objc_classname,cstring_literals" :
4492 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004493 1, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004494
Owen Anderson170229f2009-07-14 23:10:40 +00004495 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004496}
4497
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004498llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
4499 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
4500 I = MethodDefinitions.find(MD);
4501 if (I != MethodDefinitions.end())
4502 return I->second;
4503
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004504 return NULL;
4505}
4506
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004507/// GetIvarLayoutName - Returns a unique constant for the given
4508/// ivar layout bitmap.
4509llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004510 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00004511 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004512}
4513
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004514void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Eli Friedman8cbca202012-11-06 22:15:52 +00004515 unsigned int BytePos,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004516 bool ForStrongLayout,
4517 bool &HasUnion) {
4518 const RecordDecl *RD = RT->getDecl();
4519 // FIXME - Use iterator.
David Blaikie2d7c57e2012-04-30 02:36:29 +00004520 SmallVector<const FieldDecl*, 16> Fields;
4521 for (RecordDecl::field_iterator i = RD->field_begin(),
4522 e = RD->field_end(); i != e; ++i)
David Blaikie40ed2972012-06-06 20:45:41 +00004523 Fields.push_back(*i);
Chris Lattner2192fe52011-07-18 04:24:23 +00004524 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004525 const llvm::StructLayout *RecLayout =
Micah Villmowdd31ca12012-10-08 16:25:52 +00004526 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004527
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004528 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
4529 ForStrongLayout, HasUnion);
4530}
4531
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +00004532void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004533 const llvm::StructLayout *Layout,
4534 const RecordDecl *RD,
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00004535 ArrayRef<const FieldDecl*> RecFields,
Eli Friedman8cbca202012-11-06 22:15:52 +00004536 unsigned int BytePos, bool ForStrongLayout,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004537 bool &HasUnion) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004538 bool IsUnion = (RD && RD->isUnion());
Eli Friedman8cbca202012-11-06 22:15:52 +00004539 uint64_t MaxUnionIvarSize = 0;
4540 uint64_t MaxSkippedUnionIvarSize = 0;
Jordy Rosea91768e2011-07-22 02:08:32 +00004541 const FieldDecl *MaxField = 0;
4542 const FieldDecl *MaxSkippedField = 0;
4543 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Eli Friedman8cbca202012-11-06 22:15:52 +00004544 uint64_t MaxFieldOffset = 0;
4545 uint64_t MaxSkippedFieldOffset = 0;
4546 uint64_t LastBitfieldOrUnnamedOffset = 0;
4547 uint64_t FirstFieldDelta = 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004548
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004549 if (RecFields.empty())
4550 return;
John McCallc8e01702013-04-16 22:48:15 +00004551 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
4552 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
David Blaikiebbafb8a2012-03-11 07:00:24 +00004553 if (!RD && CGM.getLangOpts().ObjCAutoRefCount) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004554 const FieldDecl *FirstField = RecFields[0];
4555 FirstFieldDelta =
4556 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
John McCall31168b02011-06-15 23:02:42 +00004557 }
4558
Chris Lattner5b36ddb2009-03-31 08:48:01 +00004559 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004560 const FieldDecl *Field = RecFields[i];
Eli Friedman8cbca202012-11-06 22:15:52 +00004561 uint64_t FieldOffset;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00004562 if (RD) {
Daniel Dunbard51c1a62010-04-14 17:02:21 +00004563 // Note that 'i' here is actually the field index inside RD of Field,
4564 // although this dependency is hidden.
4565 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Eli Friedman8cbca202012-11-06 22:15:52 +00004566 FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00004567 } else
John McCall31168b02011-06-15 23:02:42 +00004568 FieldOffset =
4569 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004570
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004571 // Skip over unnamed or bitfields
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004572 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004573 LastFieldBitfieldOrUnnamed = Field;
4574 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004575 continue;
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004576 }
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004577
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004578 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004579 QualType FQT = Field->getType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004580 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004581 if (FQT->isUnionType())
4582 HasUnion = true;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004583
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004584 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004585 BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004586 ForStrongLayout, HasUnion);
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004587 continue;
4588 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004589
Chris Lattner5b36ddb2009-03-31 08:48:01 +00004590 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004591 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004592 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004593 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004594 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004595 FQT = CArray->getElementType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004596 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
4597 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004598 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004599 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004600 FQT = CArray->getElementType();
4601 }
Fariborz Jahanian9a7d57d2011-01-03 19:23:18 +00004602 if (FQT->isRecordType() && ElCount) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004603 int OldIndex = IvarsInfo.size() - 1;
4604 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004605
Ted Kremenekc23c7e62009-07-29 21:53:49 +00004606 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004607 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004608 ForStrongLayout, HasUnion);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004609
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004610 // Replicate layout information for each array element. Note that
4611 // one element is already done.
4612 uint64_t ElIx = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004613 for (int FirstIndex = IvarsInfo.size() - 1,
4614 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004615 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004616 for (int i = OldIndex+1; i <= FirstIndex; ++i)
4617 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
4618 IvarsInfo[i].ivar_size));
4619 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
4620 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
4621 SkipIvars[i].ivar_size));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004622 }
4623 continue;
4624 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004625 }
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004626 // At this point, we are done with Record/Union and array there of.
4627 // For other arrays we are down to its element type.
John McCall8ccfcb52009-09-24 19:53:00 +00004628 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004629
Eli Friedman8cbca202012-11-06 22:15:52 +00004630 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall8ccfcb52009-09-24 19:53:00 +00004631 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
4632 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00004633 if (IsUnion) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004634 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00004635 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004636 MaxUnionIvarSize = UnionIvarSize;
4637 MaxField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00004638 MaxFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004639 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00004640 } else {
Eli Friedman8cbca202012-11-06 22:15:52 +00004641 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
4642 FieldSize / WordSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004643 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004644 } else if ((ForStrongLayout &&
John McCall8ccfcb52009-09-24 19:53:00 +00004645 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
4646 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00004647 if (IsUnion) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004648 // FIXME: Why the asymmetry? We divide by word size in bits on other
4649 // side.
4650 uint64_t UnionIvarSize = FieldSize / ByteSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00004651 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004652 MaxSkippedUnionIvarSize = UnionIvarSize;
4653 MaxSkippedField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00004654 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004655 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00004656 } else {
Eli Friedman8cbca202012-11-06 22:15:52 +00004657 // FIXME: Why the asymmetry, we divide by byte size in bits here?
4658 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
4659 FieldSize / ByteSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004660 }
4661 }
4662 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004663
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004664 if (LastFieldBitfieldOrUnnamed) {
4665 if (LastFieldBitfieldOrUnnamed->isBitField()) {
4666 // Last field was a bitfield. Must update skip info.
Richard Smithcaf33902011-10-10 18:28:20 +00004667 uint64_t BitFieldSize
4668 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004669 GC_IVAR skivar;
4670 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
Eli Friedman8cbca202012-11-06 22:15:52 +00004671 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
4672 + ((BitFieldSize % ByteSizeInBits) != 0);
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004673 SkipIvars.push_back(skivar);
4674 } else {
4675 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
4676 // Last field was unnamed. Must update skip info.
Eli Friedman8cbca202012-11-06 22:15:52 +00004677 unsigned FieldSize
4678 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004679 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
Eli Friedman8cbca202012-11-06 22:15:52 +00004680 FieldSize / ByteSizeInBits));
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004681 }
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004682 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004683
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004684 if (MaxField)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004685 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004686 MaxUnionIvarSize));
4687 if (MaxSkippedField)
Daniel Dunbar5b743912009-05-03 23:31:46 +00004688 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004689 MaxSkippedUnionIvarSize));
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004690}
4691
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004692/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
4693/// the computations and returning the layout bitmap (for ivar or blocks) in
4694/// the given argument BitMap string container. Routine reads
4695/// two containers, IvarsInfo and SkipIvars which are assumed to be
4696/// filled already by the caller.
Chris Lattner9c818332012-02-05 02:30:40 +00004697llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004698 unsigned int WordsToScan, WordsToSkip;
Chris Lattnerece04092012-02-07 00:39:47 +00004699 llvm::Type *PtrTy = CGM.Int8PtrTy;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004700
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004701 // Build the string of skip/scan nibbles
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004702 SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Eli Friedman8cbca202012-11-06 22:15:52 +00004703 unsigned int WordSize =
4704 CGM.getTypes().getDataLayout().getTypeAllocSize(PtrTy);
4705 if (IvarsInfo[0].ivar_bytepos == 0) {
4706 WordsToSkip = 0;
4707 WordsToScan = IvarsInfo[0].ivar_size;
4708 } else {
4709 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
4710 WordsToScan = IvarsInfo[0].ivar_size;
4711 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004712 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004713 unsigned int TailPrevGCObjC =
4714 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004715 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004716 // consecutive 'scanned' object pointers.
Eli Friedman8cbca202012-11-06 22:15:52 +00004717 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004718 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004719 // Skip over 'gc'able object pointer which lay over each other.
4720 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
4721 continue;
4722 // Must skip over 1 or more words. We save current skip/scan values
4723 // and start a new pair.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004724 SKIP_SCAN SkScan;
4725 SkScan.skip = WordsToSkip;
4726 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004727 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004728
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004729 // Skip the hole.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004730 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
4731 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004732 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004733 WordsToSkip = 0;
Eli Friedman8cbca202012-11-06 22:15:52 +00004734 WordsToScan = IvarsInfo[i].ivar_size;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004735 }
4736 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004737 if (WordsToScan > 0) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004738 SKIP_SCAN SkScan;
4739 SkScan.skip = WordsToSkip;
4740 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004741 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004742 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004743
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004744 if (!SkipIvars.empty()) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004745 unsigned int LastIndex = SkipIvars.size()-1;
Eli Friedman8cbca202012-11-06 22:15:52 +00004746 int LastByteSkipped =
4747 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004748 LastIndex = IvarsInfo.size()-1;
Eli Friedman8cbca202012-11-06 22:15:52 +00004749 int LastByteScanned =
4750 IvarsInfo[LastIndex].ivar_bytepos +
4751 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004752 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramerd20ef752009-12-25 15:43:36 +00004753 if (LastByteSkipped > LastByteScanned) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004754 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004755 SKIP_SCAN SkScan;
Eli Friedman8cbca202012-11-06 22:15:52 +00004756 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004757 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004758 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004759 }
4760 }
4761 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
4762 // as 0xMN.
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004763 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004764 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004765 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
4766 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
4767 // 0xM0 followed by 0x0N detected.
4768 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
4769 for (int j = i+1; j < SkipScan; j++)
4770 SkipScanIvars[j] = SkipScanIvars[j+1];
4771 --SkipScan;
4772 }
4773 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004774
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004775 // Generate the string.
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004776 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004777 unsigned char byte;
4778 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
4779 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
4780 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
4781 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004782
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004783 // first skip big.
4784 for (unsigned int ix = 0; ix < skip_big; ix++)
4785 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004786
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004787 // next (skip small, scan)
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004788 if (skip_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004789 byte = skip_small << 4;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004790 if (scan_big > 0) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004791 byte |= 0xf;
4792 --scan_big;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004793 } else if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004794 byte |= scan_small;
4795 scan_small = 0;
4796 }
4797 BitMap += byte;
4798 }
4799 // next scan big
4800 for (unsigned int ix = 0; ix < scan_big; ix++)
4801 BitMap += (unsigned char)(0x0f);
4802 // last scan small
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004803 if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004804 byte = scan_small;
4805 BitMap += byte;
4806 }
4807 }
4808 // null terminate string.
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004809 unsigned char zero = 0;
4810 BitMap += zero;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004811
4812 llvm::GlobalVariable * Entry =
4813 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004814 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004815 ((ObjCABI == 2) ?
4816 "__TEXT,__objc_classname,cstring_literals" :
4817 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004818 1, true);
4819 return getConstantGEP(VMContext, Entry, 0, 0);
4820}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004821
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004822/// BuildIvarLayout - Builds ivar layout bitmap for the class
4823/// implementation for the __strong or __weak case.
4824/// The layout map displays which words in ivar list must be skipped
4825/// and which must be scanned by GC (see below). String is built of bytes.
4826/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
4827/// of words to skip and right nibble is count of words to scan. So, each
4828/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
4829/// represented by a 0x00 byte which also ends the string.
4830/// 1. when ForStrongLayout is true, following ivars are scanned:
4831/// - id, Class
4832/// - object *
4833/// - __strong anything
4834///
4835/// 2. When ForStrongLayout is false, following ivars are scanned:
4836/// - __weak anything
4837///
4838llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
4839 const ObjCImplementationDecl *OMD,
4840 bool ForStrongLayout) {
4841 bool hasUnion = false;
4842
Chris Lattnerece04092012-02-07 00:39:47 +00004843 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikiebbafb8a2012-03-11 07:00:24 +00004844 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
4845 !CGM.getLangOpts().ObjCAutoRefCount)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004846 return llvm::Constant::getNullValue(PtrTy);
4847
Jordy Rosea91768e2011-07-22 02:08:32 +00004848 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
4849 SmallVector<const FieldDecl*, 32> RecFields;
David Blaikiebbafb8a2012-03-11 07:00:24 +00004850 if (CGM.getLangOpts().ObjCAutoRefCount) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004851 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004852 IVD; IVD = IVD->getNextIvar())
4853 RecFields.push_back(cast<FieldDecl>(IVD));
4854 }
4855 else {
Jordy Rosea91768e2011-07-22 02:08:32 +00004856 SmallVector<const ObjCIvarDecl*, 32> Ivars;
John McCall31168b02011-06-15 23:02:42 +00004857 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004858
Jordy Rosea91768e2011-07-22 02:08:32 +00004859 // FIXME: This is not ideal; we shouldn't have to do this copy.
4860 RecFields.append(Ivars.begin(), Ivars.end());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004861 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004862
4863 if (RecFields.empty())
4864 return llvm::Constant::getNullValue(PtrTy);
4865
4866 SkipIvars.clear();
4867 IvarsInfo.clear();
4868
Eli Friedman8cbca202012-11-06 22:15:52 +00004869 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004870 if (IvarsInfo.empty())
4871 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004872 // Sort on byte position in case we encounterred a union nested in
4873 // the ivar list.
4874 if (hasUnion && !IvarsInfo.empty())
4875 std::sort(IvarsInfo.begin(), IvarsInfo.end());
4876 if (hasUnion && !SkipIvars.empty())
4877 std::sort(SkipIvars.begin(), SkipIvars.end());
4878
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004879 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004880 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004881
David Blaikiebbafb8a2012-03-11 07:00:24 +00004882 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004883 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004884 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar56df9772010-08-17 22:39:59 +00004885 OMD->getClassInterface()->getName().data());
Roman Divackye6377112012-09-06 15:59:27 +00004886 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling53136852012-02-07 09:06:01 +00004887 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004888 if (!(s[i] & 0xf0))
4889 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
4890 else
4891 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
4892 printf("\n");
4893 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004894 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004895}
4896
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004897llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004898 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
4899
Chris Lattner3def9ae2012-02-06 22:16:34 +00004900 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004901 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004902 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004903 llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004904 ((ObjCABI == 2) ?
4905 "__TEXT,__objc_methname,cstring_literals" :
4906 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004907 1, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004908
Owen Anderson170229f2009-07-14 23:10:40 +00004909 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004910}
4911
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004912// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004913llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004914 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
4915}
4916
Daniel Dunbarf5c18462009-04-20 06:54:31 +00004917llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004918 std::string TypeStr;
4919 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
4920
4921 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarb036db82008-08-13 03:21:16 +00004922
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004923 if (!Entry)
4924 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004925 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004926 ((ObjCABI == 2) ?
4927 "__TEXT,__objc_methtype,cstring_literals" :
4928 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004929 1, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004930
Owen Anderson170229f2009-07-14 23:10:40 +00004931 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004932}
4933
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004934llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
4935 bool Extended) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004936 std::string TypeStr;
Bill Wendlinge22bef72012-02-09 22:45:21 +00004937 if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended))
Douglas Gregora9d84932011-05-27 01:19:52 +00004938 return 0;
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004939
4940 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4941
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004942 if (!Entry)
4943 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004944 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004945 ((ObjCABI == 2) ?
4946 "__TEXT,__objc_methtype,cstring_literals" :
4947 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004948 1, true);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004949
Owen Anderson170229f2009-07-14 23:10:40 +00004950 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004951}
4952
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004953// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004954llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004955 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004956
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004957 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004958 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Chris Lattner9c818332012-02-05 02:30:40 +00004959 llvm::ConstantDataArray::getString(VMContext,
4960 Ident->getNameStart()),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004961 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004962 1, true);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004963
Owen Anderson170229f2009-07-14 23:10:40 +00004964 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004965}
4966
4967// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00004968// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004969llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004970CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4971 const Decl *Container) {
Daniel Dunbar4932b362008-08-28 04:38:10 +00004972 std::string TypeStr;
4973 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004974 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4975}
4976
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004977void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004978 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004979 SmallVectorImpl<char> &Name) {
Daniel Dunbard2386812009-10-19 01:21:19 +00004980 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00004981 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00004982 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4983 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004984 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00004985 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer2f569922012-02-07 11:57:45 +00004986 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00004987 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004988}
4989
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004990void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004991 EmitModuleInfo();
4992
Daniel Dunbarc475d422008-10-29 22:36:39 +00004993 // Emit the dummy bodies for any protocols which were referenced but
4994 // never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004995 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerf56501c2009-07-17 23:57:13 +00004996 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4997 if (I->second->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00004998 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004999
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005000 llvm::Constant *Values[5];
Owen Anderson0b75f232009-07-31 20:28:54 +00005001 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005002 Values[1] = GetClassName(I->first);
Owen Anderson0b75f232009-07-31 20:28:54 +00005003 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarc475d422008-10-29 22:36:39 +00005004 Values[3] = Values[4] =
Owen Anderson0b75f232009-07-31 20:28:54 +00005005 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Rafael Espindola21039aa2014-02-27 16:26:32 +00005006 assertPrivateName(I->second);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005007 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarc475d422008-10-29 22:36:39 +00005008 Values));
Chris Lattnerf56501c2009-07-17 23:57:13 +00005009 CGM.AddUsedGlobal(I->second);
Daniel Dunbarc475d422008-10-29 22:36:39 +00005010 }
5011
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005012 // Add assembler directives to add lazy undefined symbol references
5013 // for classes which are referenced but not defined. This is
5014 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00005015 //
5016 // FIXME: It would be nice if we had an LLVM construct for this.
5017 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005018 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00005019 Asm += CGM.getModule().getModuleInlineAsm();
5020 if (!Asm.empty() && Asm.back() != '\n')
5021 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005022
Daniel Dunbard027a922009-09-07 00:20:42 +00005023 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbard027a922009-09-07 00:20:42 +00005024 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
5025 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar07d07852009-10-18 21:17:35 +00005026 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
5027 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnera299f2c2010-04-17 18:26:20 +00005028 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00005029 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnera299f2c2010-04-17 18:26:20 +00005030 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00005031 }
5032
Bill Wendling53136852012-02-07 09:06:01 +00005033 for (size_t i = 0, e = DefinedCategoryNames.size(); i < e; ++i) {
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00005034 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
5035 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
5036 }
Chris Lattnera299f2c2010-04-17 18:26:20 +00005037
Daniel Dunbard027a922009-09-07 00:20:42 +00005038 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005039 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005040}
5041
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005042CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005043 : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00005044 ObjCTypes(cgm) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00005045 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005046 ObjCABI = 2;
5047}
5048
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005049/* *** */
5050
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005051ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00005052 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(0)
5053{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005054 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5055 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005056
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005057 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005058 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005059 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005060 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Chris Lattnerece04092012-02-07 00:39:47 +00005061 Int8PtrTy = CGM.Int8PtrTy;
5062 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005063
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005064 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005065 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005066 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005067
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005068 // I'm not sure I like this. The implicit coordination is a bit
5069 // gross. We should solve this in a reasonable fashion because this
5070 // is a pretty common task (match some runtime data structure with
5071 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005072
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005073 // FIXME: This is leaked.
5074 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005075
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005076 // struct _objc_super {
5077 // id self;
5078 // Class cls;
5079 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00005080 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005081 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005082 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005083 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005084 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005085 Ctx.getObjCIdType(), 0, 0, false, ICIS_NoInit));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005086 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005087 Ctx.getObjCClassType(), 0, 0, false,
5088 ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005089 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005090
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005091 SuperCTy = Ctx.getTagDeclType(RD);
5092 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005093
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005094 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005095 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5096
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005097 // struct _prop_t {
5098 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005099 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005100 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005101 PropertyTy = llvm::StructType::create("struct._prop_t",
5102 Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005103
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005104 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005105 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005106 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005107 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005108 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005109 PropertyListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005110 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
5111 llvm::ArrayType::get(PropertyTy, 0), NULL);
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005112 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005113 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005114
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005115 // struct _objc_method {
5116 // SEL _cmd;
5117 // char *method_type;
5118 // char *_imp;
5119 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005120 MethodTy = llvm::StructType::create("struct._objc_method",
5121 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
5122 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005123
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005124 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00005125 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005126 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005127
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005128}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005129
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005130ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005131 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005132 // struct _objc_method_description {
5133 // SEL name;
5134 // char *types;
5135 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005136 MethodDescriptionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005137 llvm::StructType::create("struct._objc_method_description",
5138 SelectorPtrTy, Int8PtrTy, NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005139
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005140 // struct _objc_method_description_list {
5141 // int count;
5142 // struct _objc_method_description[1];
5143 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005144 MethodDescriptionListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005145 llvm::StructType::create("struct._objc_method_description_list",
5146 IntTy,
5147 llvm::ArrayType::get(MethodDescriptionTy, 0),NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005148
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005149 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005150 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005151 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005152
Daniel Dunbarb036db82008-08-13 03:21:16 +00005153 // Protocol description structures
5154
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005155 // struct _objc_protocol_extension {
5156 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5157 // struct _objc_method_description_list *optional_instance_methods;
5158 // struct _objc_method_description_list *optional_class_methods;
5159 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005160 // const char ** extendedMethodTypes;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005161 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005162 ProtocolExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005163 llvm::StructType::create("struct._objc_protocol_extension",
5164 IntTy, MethodDescriptionListPtrTy,
5165 MethodDescriptionListPtrTy, PropertyListPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005166 Int8PtrPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005167
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005168 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005169 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005170
Daniel Dunbarc475d422008-10-29 22:36:39 +00005171 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00005172
Chris Lattnera5f58b02011-07-09 17:41:47 +00005173 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005174 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00005175
Chris Lattnera5f58b02011-07-09 17:41:47 +00005176 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005177 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005178 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005179 LongTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00005180 llvm::ArrayType::get(ProtocolTy, 0),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005181 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005182
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005183 // struct _objc_protocol {
5184 // struct _objc_protocol_extension *isa;
5185 // char *protocol_name;
5186 // struct _objc_protocol **_objc_protocol_list;
5187 // struct _objc_method_description_list *instance_methods;
5188 // struct _objc_method_description_list *class_methods;
5189 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005190 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5191 llvm::PointerType::getUnqual(ProtocolListTy),
5192 MethodDescriptionListPtrTy,
5193 MethodDescriptionListPtrTy,
5194 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005195
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005196 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005197 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005198
Owen Anderson9793f0e2009-07-29 22:16:19 +00005199 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005200
5201 // Class description structures
5202
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005203 // struct _objc_ivar {
5204 // char *ivar_name;
5205 // char *ivar_type;
5206 // int ivar_offset;
5207 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005208 IvarTy = llvm::StructType::create("struct._objc_ivar",
5209 Int8PtrTy, Int8PtrTy, IntTy, NULL);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005210
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005211 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005212 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005213 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005214 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005215
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005216 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005217 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005218 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005219 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005220
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005221 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005222 ClassExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005223 llvm::StructType::create("struct._objc_class_extension",
5224 IntTy, Int8PtrTy, PropertyListPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005225 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005226
Chris Lattner5ec04a52011-08-12 17:43:31 +00005227 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005228
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005229 // struct _objc_class {
5230 // Class isa;
5231 // Class super_class;
5232 // char *name;
5233 // long version;
5234 // long info;
5235 // long instance_size;
5236 // struct _objc_ivar_list *ivars;
5237 // struct _objc_method_list *methods;
5238 // struct _objc_cache *cache;
5239 // struct _objc_protocol_list *protocols;
5240 // char *ivar_layout;
5241 // struct _objc_class_ext *ext;
5242 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005243 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
5244 llvm::PointerType::getUnqual(ClassTy),
5245 Int8PtrTy,
5246 LongTy,
5247 LongTy,
5248 LongTy,
5249 IvarListPtrTy,
5250 MethodListPtrTy,
5251 CachePtrTy,
5252 ProtocolListPtrTy,
5253 Int8PtrTy,
5254 ClassExtensionPtrTy,
5255 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005256
Owen Anderson9793f0e2009-07-29 22:16:19 +00005257 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005258
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005259 // struct _objc_category {
5260 // char *category_name;
5261 // char *class_name;
5262 // struct _objc_method_list *instance_method;
5263 // struct _objc_method_list *class_method;
5264 // uint32_t size; // sizeof(struct _objc_category)
5265 // struct _objc_property_list *instance_properties;// category's @property
5266 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005267 CategoryTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005268 llvm::StructType::create("struct._objc_category",
5269 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5270 MethodListPtrTy, ProtocolListPtrTy,
5271 IntTy, PropertyListPtrTy, NULL);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005272
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005273 // Global metadata structures
5274
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005275 // struct _objc_symtab {
5276 // long sel_ref_cnt;
5277 // SEL *refs;
5278 // short cls_def_cnt;
5279 // short cat_def_cnt;
5280 // char *defs[cls_def_cnt + cat_def_cnt];
5281 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005282 SymtabTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005283 llvm::StructType::create("struct._objc_symtab",
5284 LongTy, SelectorPtrTy, ShortTy, ShortTy,
5285 llvm::ArrayType::get(Int8PtrTy, 0), NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005286 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005287
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00005288 // struct _objc_module {
5289 // long version;
5290 // long size; // sizeof(struct _objc_module)
5291 // char *name;
5292 // struct _objc_symtab* symtab;
5293 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005294 ModuleTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005295 llvm::StructType::create("struct._objc_module",
5296 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, NULL);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00005297
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005298
Mike Stump18bb9282009-05-16 07:57:57 +00005299 // FIXME: This is the size of the setjmp buffer and should be target
5300 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00005301 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005302
Anders Carlsson9ff22482008-09-09 10:10:21 +00005303 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00005304 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005305
5306 ExceptionDataTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005307 llvm::StructType::create("struct._objc_exception_data",
Chris Lattnerece04092012-02-07 00:39:47 +00005308 llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
5309 StackPtrTy, NULL);
Anders Carlsson9ff22482008-09-09 10:10:21 +00005310
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005311}
5312
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005313ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005314 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005315 // struct _method_list_t {
5316 // uint32_t entsize; // sizeof(struct _objc_method)
5317 // uint32_t method_count;
5318 // struct _objc_method method_list[method_count];
5319 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005320 MethodListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005321 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
5322 llvm::ArrayType::get(MethodTy, 0), NULL);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005323 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005324 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005325
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005326 // struct _protocol_t {
5327 // id isa; // NULL
5328 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005329 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005330 // const struct method_list_t * const instance_methods;
5331 // const struct method_list_t * const class_methods;
5332 // const struct method_list_t *optionalInstanceMethods;
5333 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005334 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005335 // const uint32_t size; // sizeof(struct _protocol_t)
5336 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005337 // const char ** extendedMethodTypes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005338 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005339
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005340 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005341 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005342 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005343
Chris Lattnera5f58b02011-07-09 17:41:47 +00005344 ProtocolnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005345 llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
5346 llvm::PointerType::getUnqual(ProtocolListnfABITy),
5347 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5348 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005349 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
5350 NULL);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005351
5352 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005353 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005354
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005355 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005356 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005357 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005358 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005359 ProtocolListnfABITy->setBody(LongTy,
5360 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
5361 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005362
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005363 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005364 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005365
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005366 // struct _ivar_t {
5367 // unsigned long int *offset; // pointer to ivar offset location
5368 // char *name;
5369 // char *type;
5370 // uint32_t alignment;
5371 // uint32_t size;
5372 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005373 IvarnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005374 llvm::StructType::create("struct._ivar_t",
5375 llvm::PointerType::getUnqual(LongTy),
5376 Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005377
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005378 // struct _ivar_list_t {
5379 // uint32 entsize; // sizeof(struct _ivar_t)
5380 // uint32 count;
5381 // struct _iver_t list[count];
5382 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005383 IvarListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005384 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
5385 llvm::ArrayType::get(IvarnfABITy, 0), NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005386
Owen Anderson9793f0e2009-07-29 22:16:19 +00005387 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005388
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005389 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005390 // uint32_t const flags;
5391 // uint32_t const instanceStart;
5392 // uint32_t const instanceSize;
5393 // uint32_t const reserved; // only when building for 64bit targets
5394 // const uint8_t * const ivarLayout;
5395 // const char *const name;
5396 // const struct _method_list_t * const baseMethods;
5397 // const struct _objc_protocol_list *const baseProtocols;
5398 // const struct _ivar_list_t *const ivars;
5399 // const uint8_t * const weakIvarLayout;
5400 // const struct _prop_list_t * const properties;
5401 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005402
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005403 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattner5ec04a52011-08-12 17:43:31 +00005404 ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
5405 IntTy, IntTy, IntTy, Int8PtrTy,
5406 Int8PtrTy, MethodListnfABIPtrTy,
5407 ProtocolListnfABIPtrTy,
5408 IvarListnfABIPtrTy,
5409 Int8PtrTy, PropertyListPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005410
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005411 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00005412 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00005413 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
5414 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005415
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005416 // struct _class_t {
5417 // struct _class_t *isa;
5418 // struct _class_t * const superclass;
5419 // void *cache;
5420 // IMP *vtable;
5421 // struct class_ro_t *ro;
5422 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005423
Chris Lattner5ec04a52011-08-12 17:43:31 +00005424 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005425 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
5426 llvm::PointerType::getUnqual(ClassnfABITy),
5427 CachePtrTy,
5428 llvm::PointerType::getUnqual(ImpnfABITy),
5429 llvm::PointerType::getUnqual(ClassRonfABITy),
5430 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005431
Fariborz Jahanian71394042009-01-23 23:53:38 +00005432 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005433 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005434
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005435 // struct _category_t {
5436 // const char * const name;
5437 // struct _class_t *const cls;
5438 // const struct _method_list_t * const instance_methods;
5439 // const struct _method_list_t * const class_methods;
5440 // const struct _protocol_list_t * const protocols;
5441 // const struct _prop_list_t * const properties;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00005442 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005443 CategorynfABITy = llvm::StructType::create("struct._category_t",
5444 Int8PtrTy, ClassnfABIPtrTy,
5445 MethodListnfABIPtrTy,
5446 MethodListnfABIPtrTy,
5447 ProtocolListnfABIPtrTy,
5448 PropertyListPtrTy,
5449 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005450
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005451 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005452 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5453 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005454
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005455 // MessageRefTy - LLVM for:
5456 // struct _message_ref_t {
5457 // IMP messenger;
5458 // SEL name;
5459 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005460
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005461 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00005462 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005463 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005464 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005465 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005466 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005467 Ctx.VoidPtrTy, 0, 0, false, ICIS_NoInit));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005468 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005469 Ctx.getObjCSelType(), 0, 0, false,
5470 ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005471 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005472
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005473 MessageRefCTy = Ctx.getTagDeclType(RD);
5474 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
5475 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005476
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005477 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005478 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005479
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005480 // SuperMessageRefTy - LLVM for:
5481 // struct _super_message_ref_t {
5482 // SUPER_IMP messenger;
5483 // SEL name;
5484 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005485 SuperMessageRefTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005486 llvm::StructType::create("struct._super_message_ref_t",
5487 ImpnfABITy, SelectorPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005488
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005489 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005490 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005491
Daniel Dunbarb1559a42009-03-01 04:46:24 +00005492
5493 // struct objc_typeinfo {
5494 // const void** vtable; // objc_ehtype_vtable + 2
5495 // const char* name; // c++ typeinfo string
5496 // Class cls;
5497 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005498 EHTypeTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005499 llvm::StructType::create("struct._objc_typeinfo",
5500 llvm::PointerType::getUnqual(Int8PtrTy),
5501 Int8PtrTy, ClassnfABIPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005502 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005503}
5504
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005505llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00005506 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005507
Fariborz Jahanian71394042009-01-23 23:53:38 +00005508 return NULL;
5509}
5510
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00005511void CGObjCNonFragileABIMac::
5512AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
5513 const char *SymbolName,
5514 const char *SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00005515 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005516
Daniel Dunbar19573e72009-05-15 21:48:48 +00005517 if (!NumClasses)
5518 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005519
Chris Lattner3def9ae2012-02-06 22:16:34 +00005520 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005521 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00005522 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00005523 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00005524 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005525 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00005526 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00005527 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005528
Daniel Dunbar19573e72009-05-15 21:48:48 +00005529 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005530 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00005531 llvm::GlobalValue::PrivateLinkage,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005532 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005533 SymbolName);
Rafael Espindola21039aa2014-02-27 16:26:32 +00005534 assertPrivateName(GV);
Micah Villmowdd31ca12012-10-08 16:25:52 +00005535 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00005536 GV->setSection(SectionName);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005537 CGM.AddUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005538}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005539
Fariborz Jahanian71394042009-01-23 23:53:38 +00005540void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
5541 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005542
Daniel Dunbar19573e72009-05-15 21:48:48 +00005543 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005544 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005545 AddModuleClassList(DefinedClasses,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005546 "\01L_OBJC_LABEL_CLASS_$",
5547 "__DATA, __objc_classlist, regular, no_dead_strip");
Rafael Espindola554256c2014-02-26 22:25:45 +00005548
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005549 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005550 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
5551 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005552
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005553 // Build list of all implemented category addresses in array
5554 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005555 AddModuleClassList(DefinedCategories,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005556 "\01L_OBJC_LABEL_CATEGORY_$",
5557 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005558 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005559 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
5560 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005561
Daniel Dunbar5e639272010-04-25 20:39:01 +00005562 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005563}
5564
John McCall9e8bb002011-05-14 03:10:52 +00005565/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
5566/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005567/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005568/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00005569bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
5570 // At various points we've experimented with using vtable-based
5571 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005572 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005573 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00005574 return false;
John McCall9e8bb002011-05-14 03:10:52 +00005575 case CodeGenOptions::NonLegacy:
5576 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005577 case CodeGenOptions::Mixed:
5578 break;
5579 }
5580
5581 // If so, see whether this selector is in the white-list of things which must
5582 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00005583 if (VTableDispatchMethods.empty()) {
5584 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
5585 VTableDispatchMethods.insert(GetNullarySelector("class"));
5586 VTableDispatchMethods.insert(GetNullarySelector("self"));
5587 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
5588 VTableDispatchMethods.insert(GetNullarySelector("length"));
5589 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005590
John McCall9e8bb002011-05-14 03:10:52 +00005591 // These are vtable-based if GC is disabled.
5592 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005593 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00005594 VTableDispatchMethods.insert(GetNullarySelector("retain"));
5595 VTableDispatchMethods.insert(GetNullarySelector("release"));
5596 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
5597 }
5598
5599 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
5600 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
5601 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
5602 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
5603 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
5604 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
5605 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
5606
5607 // These are vtable-based if GC is enabled.
5608 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005609 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00005610 VTableDispatchMethods.insert(GetNullarySelector("hash"));
5611 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
5612
5613 // "countByEnumeratingWithState:objects:count"
5614 IdentifierInfo *KeyIdents[] = {
5615 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
5616 &CGM.getContext().Idents.get("objects"),
5617 &CGM.getContext().Idents.get("count")
5618 };
5619 VTableDispatchMethods.insert(
5620 CGM.getContext().Selectors.getSelector(3, KeyIdents));
5621 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005622 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005623
John McCall9e8bb002011-05-14 03:10:52 +00005624 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005625}
5626
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005627/// BuildClassRoTInitializer - generate meta-data for:
5628/// struct _class_ro_t {
5629/// uint32_t const flags;
5630/// uint32_t const instanceStart;
5631/// uint32_t const instanceSize;
5632/// uint32_t const reserved; // only when building for 64bit targets
5633/// const uint8_t * const ivarLayout;
5634/// const char *const name;
5635/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005636/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005637/// const struct _ivar_list_t *const ivars;
5638/// const uint8_t * const weakIvarLayout;
5639/// const struct _prop_list_t * const properties;
5640/// }
5641///
5642llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005643 unsigned flags,
5644 unsigned InstanceStart,
5645 unsigned InstanceSize,
5646 const ObjCImplementationDecl *ID) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005647 std::string ClassName = ID->getNameAsString();
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005648 llvm::Constant *Values[10]; // 11 for 64bit targets!
John McCall31168b02011-06-15 23:02:42 +00005649
David Blaikiebbafb8a2012-03-11 07:00:24 +00005650 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCallef19dbb2012-10-17 04:53:23 +00005651 flags |= NonFragileABI_Class_CompiledByARC;
John McCall31168b02011-06-15 23:02:42 +00005652
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005653 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
5654 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
5655 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005656 // FIXME. For 64bit targets add 0 here.
John McCallef19dbb2012-10-17 04:53:23 +00005657 Values[ 3] = (flags & NonFragileABI_Class_Meta)
5658 ? GetIvarLayoutName(0, ObjCTypes)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005659 : BuildIvarLayout(ID, true);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005660 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005661 // const struct _method_list_t * const baseMethods;
5662 std::vector<llvm::Constant*> Methods;
5663 std::string MethodListName("\01l_OBJC_$_");
John McCallef19dbb2012-10-17 04:53:23 +00005664 if (flags & NonFragileABI_Class_Meta) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005665 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005666 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005667 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005668 // Class methods should always be defined.
5669 Methods.push_back(GetMethodConstant(*i));
5670 }
5671 } else {
5672 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005673 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005674 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005675 // Instance methods should always be defined.
5676 Methods.push_back(GetMethodConstant(*i));
5677 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005678 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005679 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie40ed2972012-06-06 20:45:41 +00005680 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005681
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005682 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
5683 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005684
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005685 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
5686 if (llvm::Constant *C = GetMethodConstant(MD))
5687 Methods.push_back(C);
5688 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
5689 if (llvm::Constant *C = GetMethodConstant(MD))
5690 Methods.push_back(C);
5691 }
5692 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005693 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005694 Values[ 5] = EmitMethodList(MethodListName,
5695 "__DATA, __objc_const", Methods);
5696
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005697 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5698 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005699 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005700 + OID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00005701 OID->all_referenced_protocol_begin(),
5702 OID->all_referenced_protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005703
John McCallef19dbb2012-10-17 04:53:23 +00005704 if (flags & NonFragileABI_Class_Meta) {
Owen Anderson0b75f232009-07-31 20:28:54 +00005705 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCallef19dbb2012-10-17 04:53:23 +00005706 Values[ 8] = GetIvarLayoutName(0, ObjCTypes);
Owen Anderson0b75f232009-07-31 20:28:54 +00005707 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
John McCallef19dbb2012-10-17 04:53:23 +00005708 } else {
5709 Values[ 7] = EmitIvarList(ID);
5710 Values[ 8] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005711 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
5712 ID, ID->getClassInterface(), ObjCTypes);
John McCallef19dbb2012-10-17 04:53:23 +00005713 }
Owen Anderson0e0189d2009-07-27 22:29:56 +00005714 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005715 Values);
5716 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005717 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00005718 llvm::GlobalValue::PrivateLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005719 Init,
John McCallef19dbb2012-10-17 04:53:23 +00005720 (flags & NonFragileABI_Class_Meta) ?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005721 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
5722 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Rafael Espindola21039aa2014-02-27 16:26:32 +00005723 assertPrivateName(CLASS_RO_GV);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005724 CLASS_RO_GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005725 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005726 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005727 return CLASS_RO_GV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005728
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005729}
5730
5731/// BuildClassMetaData - This routine defines that to-level meta-data
5732/// for the given ClassName for:
5733/// struct _class_t {
5734/// struct _class_t *isa;
5735/// struct _class_t * const superclass;
5736/// void *cache;
5737/// IMP *vtable;
5738/// struct class_ro_t *ro;
5739/// }
5740///
Rafael Espindola554256c2014-02-26 22:25:45 +00005741llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassMetaData(
5742 std::string &ClassName, llvm::Constant *IsAGV, llvm::Constant *SuperClassGV,
5743 llvm::Constant *ClassRoGV, bool HiddenVisibility, bool Weak) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005744 llvm::Constant *Values[] = {
5745 IsAGV,
5746 SuperClassGV,
5747 ObjCEmptyCacheVar, // &ObjCEmptyCacheVar
5748 ObjCEmptyVtableVar, // &ObjCEmptyVtableVar
5749 ClassRoGV // &CLASS_RO_GV
5750 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005751 if (!Values[1])
5752 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Fariborz Jahanian42d49552013-10-24 17:40:28 +00005753 if (!Values[3])
5754 Values[3] = llvm::Constant::getNullValue(
5755 llvm::PointerType::getUnqual(ObjCTypes.ImpnfABITy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005756 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005757 Values);
Rafael Espindola554256c2014-02-26 22:25:45 +00005758 llvm::GlobalVariable *GV = GetClassGlobal(ClassName, Weak);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005759 GV->setInitializer(Init);
Fariborz Jahanian04087232009-01-31 01:07:39 +00005760 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005761 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005762 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian82208252009-01-31 00:59:10 +00005763 if (HiddenVisibility)
5764 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005765 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005766}
5767
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005768bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00005769CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005770 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005771}
5772
Daniel Dunbar961202372009-05-03 12:57:56 +00005773void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00005774 uint32_t &InstanceStart,
5775 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005776 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00005777 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005778
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005779 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00005780 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005781
5782 // If there are no fields, the start is the same as the end.
5783 if (!RL.getFieldCount())
5784 InstanceStart = InstanceSize;
5785 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00005786 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00005787}
5788
Fariborz Jahanian71394042009-01-23 23:53:38 +00005789void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
5790 std::string ClassName = ID->getNameAsString();
5791 if (!ObjCEmptyCacheVar) {
5792 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005793 CGM.getModule(),
5794 ObjCTypes.CacheTy,
5795 false,
5796 llvm::GlobalValue::ExternalLinkage,
5797 0,
5798 "_objc_empty_cache");
Fariborz Jahanian42d49552013-10-24 17:40:28 +00005799
5800 // Make this entry NULL for any iOS device target, any iOS simulator target,
5801 // OS X with deployment target 10.9 or later.
5802 const llvm::Triple &Triple = CGM.getTarget().getTriple();
5803 if (Triple.isiOS() || (Triple.isMacOSX() && !Triple.isMacOSXVersionLT(10, 9)))
5804 // This entry will be null.
5805 ObjCEmptyVtableVar = 0;
5806 else
5807 ObjCEmptyVtableVar = new llvm::GlobalVariable(
5808 CGM.getModule(),
5809 ObjCTypes.ImpnfABITy,
5810 false,
5811 llvm::GlobalValue::ExternalLinkage,
5812 0,
5813 "_objc_empty_vtable");
Fariborz Jahanian71394042009-01-23 23:53:38 +00005814 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005815 assert(ID->getClassInterface() &&
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005816 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00005817 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005818 uint32_t InstanceStart =
Micah Villmowdd31ca12012-10-08 16:25:52 +00005819 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005820 uint32_t InstanceSize = InstanceStart;
John McCallef19dbb2012-10-17 04:53:23 +00005821 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar15894b72009-04-07 05:48:37 +00005822 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
5823 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005824
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005825 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005826
John McCall0d54a172012-10-17 04:53:31 +00005827 // Build the flags for the metaclass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005828 bool classIsHidden =
John McCall457a04e2010-10-22 21:05:15 +00005829 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005830 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00005831 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00005832
5833 // FIXME: why is this flag set on the metaclass?
5834 // ObjC metaclasses have no fields and don't really get constructed.
5835 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00005836 flags |= NonFragileABI_Class_HasCXXStructors;
John McCall0d54a172012-10-17 04:53:31 +00005837 if (!ID->hasNonZeroConstructors())
5838 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5839 }
5840
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005841 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005842 // class is root
John McCallef19dbb2012-10-17 04:53:23 +00005843 flags |= NonFragileABI_Class_Root;
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005844 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Rafael Espindola554256c2014-02-26 22:25:45 +00005845 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName,
5846 ID->getClassInterface()->isWeakImported());
5847
5848 // We are implementing a weak imported interface. Give it external
5849 // linkage.
5850 if (!ID->isWeakImported() && ID->getClassInterface()->isWeakImported())
5851 IsAGV->setLinkage(llvm::GlobalVariable::ExternalLinkage);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005852 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005853 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005854 const ObjCInterfaceDecl *Root = ID->getClassInterface();
5855 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
5856 Root = Super;
Rafael Espindola554256c2014-02-26 22:25:45 +00005857 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString(),
5858 Root->isWeakImported());
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005859 // work on super class metadata symbol.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005860 std::string SuperClassName =
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005861 ObjCMetaClassName +
5862 ID->getClassInterface()->getSuperClass()->getNameAsString();
Rafael Espindola554256c2014-02-26 22:25:45 +00005863 SuperClassGV = GetClassGlobal(
5864 SuperClassName,
5865 ID->getClassInterface()->getSuperClass()->isWeakImported());
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005866 }
5867 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
5868 InstanceStart,
5869 InstanceSize,ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005870 std::string TClassName = ObjCMetaClassName + ClassName;
Rafael Espindola554256c2014-02-26 22:25:45 +00005871 llvm::GlobalVariable *MetaTClass = BuildClassMetaData(
5872 TClassName, IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden,
5873 ID->isWeakImported());
Fariborz Jahanian67260552009-11-17 21:37:35 +00005874 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00005875
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005876 // Metadata for the class
John McCallef19dbb2012-10-17 04:53:23 +00005877 flags = 0;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005878 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00005879 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00005880
5881 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00005882 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005883
John McCall0d54a172012-10-17 04:53:31 +00005884 // Set a flag to enable a runtime optimization when a class has
5885 // fields that require destruction but which don't require
5886 // anything except zero-initialization during construction. This
5887 // is most notably true of __strong and __weak types, but you can
5888 // also imagine there being C++ types with non-trivial default
5889 // constructors that merely set all fields to null.
5890 if (!ID->hasNonZeroConstructors())
5891 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5892 }
5893
Douglas Gregor78bd61f2009-06-18 16:11:24 +00005894 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
John McCallef19dbb2012-10-17 04:53:23 +00005895 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005896
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005897 if (!ID->getClassInterface()->getSuperClass()) {
John McCallef19dbb2012-10-17 04:53:23 +00005898 flags |= NonFragileABI_Class_Root;
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005899 SuperClassGV = 0;
Chris Lattnerb433b272009-04-19 06:02:28 +00005900 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005901 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005902 std::string RootClassName =
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005903 ID->getClassInterface()->getSuperClass()->getNameAsString();
Rafael Espindola554256c2014-02-26 22:25:45 +00005904 SuperClassGV = GetClassGlobal(
5905 ObjCClassName + RootClassName,
5906 ID->getClassInterface()->getSuperClass()->isWeakImported());
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005907 }
Daniel Dunbar961202372009-05-03 12:57:56 +00005908 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005909 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005910 InstanceStart,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005911 InstanceSize,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005912 ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005913
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005914 TClassName = ObjCClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005915 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005916 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5917 classIsHidden);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005918 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005919
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005920 // Determine if this class is also "non-lazy".
5921 if (ImplementationIsNonLazy(ID))
5922 DefinedNonLazyClasses.push_back(ClassMD);
5923
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005924 // Force the definition of the EHType if necessary.
John McCallef19dbb2012-10-17 04:53:23 +00005925 if (flags & NonFragileABI_Class_Exception)
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005926 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005927 // Make sure method definition entries are all clear for next implementation.
5928 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005929}
5930
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005931/// GenerateProtocolRef - This routine is called to generate code for
5932/// a protocol reference expression; as in:
5933/// @code
5934/// @protocol(Proto1);
5935/// @endcode
5936/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5937/// which will hold address of the protocol meta-data.
5938///
John McCall882987f2013-02-28 19:01:20 +00005939llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005940 const ObjCProtocolDecl *PD) {
5941
Fariborz Jahanian464423d2009-04-10 18:47:34 +00005942 // This routine is called for @protocol only. So, we must build definition
5943 // of protocol's meta-data (not a reference to it!)
5944 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005945 llvm::Constant *Init =
5946 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00005947 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005948
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005949 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar56df9772010-08-17 22:39:59 +00005950 ProtocolName += PD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005951
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005952 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5953 if (PTGV)
John McCall882987f2013-02-28 19:01:20 +00005954 return CGF.Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005955 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005956 CGM.getModule(),
5957 Init->getType(), false,
5958 llvm::GlobalValue::WeakAnyLinkage,
5959 Init,
5960 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005961 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5962 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005963 CGM.AddUsedGlobal(PTGV);
John McCall882987f2013-02-28 19:01:20 +00005964 return CGF.Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005965}
5966
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005967/// GenerateCategory - Build metadata for a category implementation.
5968/// struct _category_t {
5969/// const char * const name;
5970/// struct _class_t *const cls;
5971/// const struct _method_list_t * const instance_methods;
5972/// const struct _method_list_t * const class_methods;
5973/// const struct _protocol_list_t * const protocols;
5974/// const struct _prop_list_t * const properties;
5975/// }
5976///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005977void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005978 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005979 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005980 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5981 "_$_" + OCD->getNameAsString());
5982 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar15894b72009-04-07 05:48:37 +00005983 Interface->getNameAsString());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005984
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005985 llvm::Constant *Values[6];
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005986 Values[0] = GetClassName(OCD->getIdentifier());
5987 // meta-class entry symbol
Rafael Espindola554256c2014-02-26 22:25:45 +00005988 llvm::GlobalVariable *ClassGV =
5989 GetClassGlobal(ExtClassName, Interface->isWeakImported());
5990
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005991 Values[1] = ClassGV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005992 std::vector<llvm::Constant*> Methods;
5993 std::string MethodListName(Prefix);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005994 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005995 "_$_" + OCD->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005996
5997 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005998 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005999 // Instance methods should always be defined.
6000 Methods.push_back(GetMethodConstant(*i));
6001 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006002
6003 Values[2] = EmitMethodList(MethodListName,
6004 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006005 Methods);
6006
6007 MethodListName = Prefix;
6008 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
6009 OCD->getNameAsString();
6010 Methods.clear();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006011 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00006012 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006013 // Class methods should always be defined.
6014 Methods.push_back(GetMethodConstant(*i));
6015 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006016
6017 Values[3] = EmitMethodList(MethodListName,
6018 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006019 Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006020 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00006021 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006022 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006023 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006024 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
6025 << OCD->getName();
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006026 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006027 + Interface->getName() + "_$_"
6028 + Category->getName(),
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006029 Category->protocol_begin(),
6030 Category->protocol_end());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006031 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
6032 OCD, Category, ObjCTypes);
Mike Stump658fe022009-07-30 22:28:39 +00006033 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00006034 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
6035 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006036 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006037
6038 llvm::Constant *Init =
6039 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006040 Values);
6041 llvm::GlobalVariable *GCATV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006042 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006043 false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00006044 llvm::GlobalValue::PrivateLinkage,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006045 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006046 ExtCatName);
Rafael Espindola21039aa2014-02-27 16:26:32 +00006047 assertPrivateName(GCATV);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006048 GCATV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006049 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006050 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006051 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006052 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006053
6054 // Determine if this category is also "non-lazy".
6055 if (ImplementationIsNonLazy(OCD))
6056 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006057 // method definition entries must be clear for next implementation.
6058 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006059}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006060
6061/// GetMethodConstant - Return a struct objc_method constant for the
6062/// given method if it has been defined. The result is null if the
6063/// method has not been defined. The return value has type MethodPtrTy.
6064llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006065 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00006066 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006067 if (!Fn)
6068 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006069
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006070 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00006071 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006072 ObjCTypes.SelectorPtrTy),
6073 GetMethodVarType(MD),
6074 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
6075 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00006076 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006077}
6078
6079/// EmitMethodList - Build meta-data for method declarations
6080/// struct _method_list_t {
6081/// uint32_t entsize; // sizeof(struct _objc_method)
6082/// uint32_t method_count;
6083/// struct _objc_method method_list[method_count];
6084/// }
6085///
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00006086llvm::Constant *
6087CGObjCNonFragileABIMac::EmitMethodList(Twine Name,
6088 const char *Section,
6089 ArrayRef<llvm::Constant*> Methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006090 // Return null for empty list.
6091 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006092 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006093
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006094 llvm::Constant *Values[3];
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006095 // sizeof(struct _objc_method)
Micah Villmowdd31ca12012-10-08 16:25:52 +00006096 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006097 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006098 // method_count
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006099 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00006100 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006101 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00006102 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006103 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006104
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006105 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006106 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00006107 llvm::GlobalValue::PrivateLinkage, Init, Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00006108 assertPrivateName(GV);
Micah Villmowdd31ca12012-10-08 16:25:52 +00006109 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006110 GV->setSection(Section);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006111 CGM.AddUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006112 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006113}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006114
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006115/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6116/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006117llvm::GlobalVariable *
6118CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6119 const ObjCIvarDecl *Ivar) {
6120 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar3f86b9c2009-05-05 00:36:57 +00006121 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregorbcced4e2009-04-09 21:40:53 +00006122 '.' + Ivar->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006123 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006124 CGM.getModule().getGlobalVariable(Name);
6125 if (!IvarOffsetGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006126 IvarOffsetGV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006127 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006128 false,
6129 llvm::GlobalValue::ExternalLinkage,
6130 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006131 Name);
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006132 return IvarOffsetGV;
6133}
6134
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006135llvm::Constant *
6136CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6137 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00006138 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006139 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006140 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Eli Friedman8cbca202012-11-06 22:15:52 +00006141 Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006142 IvarOffsetGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006143 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006144
Mike Stump18bb9282009-05-16 07:57:57 +00006145 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
6146 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006147 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6148 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall457a04e2010-10-22 21:05:15 +00006149 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00006150 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00006151 else
Fariborz Jahanianbc3c77b2009-04-06 18:30:00 +00006152 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendlingf7d45982011-05-04 21:37:25 +00006153 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006154 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006155}
6156
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006157/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006158/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006159/// IvarListnfABIPtrTy.
6160/// struct _ivar_t {
6161/// unsigned long int *offset; // pointer to ivar offset location
6162/// char *name;
6163/// char *type;
6164/// uint32_t alignment;
6165/// uint32_t size;
6166/// }
6167/// struct _ivar_list_t {
6168/// uint32 entsize; // sizeof(struct _ivar_t)
6169/// uint32 count;
6170/// struct _iver_t list[count];
6171/// }
6172///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00006173
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006174llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006175 const ObjCImplementationDecl *ID) {
6176
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006177 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006178
Jordy Rosea91768e2011-07-22 02:08:32 +00006179 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006180 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006181
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006182 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006183
Jordy Rosea91768e2011-07-22 02:08:32 +00006184 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00006185 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00006186 // Ignore unnamed bit-fields.
6187 if (!IVD->getDeclName())
6188 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006189 llvm::Constant *Ivar[5];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006190 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar961202372009-05-03 12:57:56 +00006191 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006192 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
6193 Ivar[2] = GetMethodVarType(IVD);
Chris Lattner2192fe52011-07-18 04:24:23 +00006194 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006195 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmowdd31ca12012-10-08 16:25:52 +00006196 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006197 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006198 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006199 Align = llvm::Log2_32(Align);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006200 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00006201 // NOTE. Size of a bitfield does not match gcc's, because of the
6202 // way bitfields are treated special in each. But I am told that
6203 // 'size' for bitfield ivars is ignored by the runtime so it does
6204 // not matter. If it matters, there is enough info to get the
6205 // bitfield right!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006206 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006207 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006208 }
6209 // Return null for empty list.
6210 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006211 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006212
6213 llvm::Constant *Values[3];
Micah Villmowdd31ca12012-10-08 16:25:52 +00006214 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006215 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
6216 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00006217 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006218 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00006219 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006220 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006221 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
6222 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006223 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00006224 llvm::GlobalValue::PrivateLinkage,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006225 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006226 Prefix + OID->getName());
Rafael Espindola21039aa2014-02-27 16:26:32 +00006227 assertPrivateName(GV);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006228 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006229 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006230 GV->setSection("__DATA, __objc_const");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006231
Chris Lattnerf56501c2009-07-17 23:57:13 +00006232 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00006233 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006234}
6235
6236llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006237 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006238 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006239
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006240 if (!Entry) {
6241 // We use the initializer as a marker of whether this is a forward
6242 // reference or not. At module finalization we add the empty
6243 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006244 Entry =
6245 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
6246 llvm::GlobalValue::ExternalLinkage,
6247 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006248 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006249 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006250 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006251
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006252 return Entry;
6253}
6254
6255/// GetOrEmitProtocol - Generate the protocol meta-data:
6256/// @code
6257/// struct _protocol_t {
6258/// id isa; // NULL
6259/// const char * const protocol_name;
6260/// const struct _protocol_list_t * protocol_list; // super protocols
6261/// const struct method_list_t * const instance_methods;
6262/// const struct method_list_t * const class_methods;
6263/// const struct method_list_t *optionalInstanceMethods;
6264/// const struct method_list_t *optionalClassMethods;
6265/// const struct _prop_list_t * properties;
6266/// const uint32_t size; // sizeof(struct _protocol_t)
6267/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006268/// const char ** extendedMethodTypes;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006269/// }
6270/// @endcode
6271///
6272
6273llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006274 const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00006275 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006276
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006277 // Early exit if a defining object has already been generated.
6278 if (Entry && Entry->hasInitializer())
6279 return Entry;
6280
Douglas Gregora715bff2012-01-01 19:51:50 +00006281 // Use the protocol definition, if there is one.
6282 if (const ObjCProtocolDecl *Def = PD->getDefinition())
6283 PD = Def;
6284
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006285 // Construct method lists.
6286 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
6287 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006288 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006289 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00006290 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006291 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006292 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006293 if (!C)
6294 return GetOrEmitProtocolRef(PD);
6295
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006296 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6297 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006298 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006299 } else {
6300 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006301 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006302 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006303 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006304
6305 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00006306 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006307 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006308 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006309 if (!C)
6310 return GetOrEmitProtocolRef(PD);
6311
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006312 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6313 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006314 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006315 } else {
6316 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006317 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006318 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006319 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006320
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006321 MethodTypesExt.insert(MethodTypesExt.end(),
6322 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
6323
6324 llvm::Constant *Values[11];
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006325 // isa is NULL
Owen Anderson0b75f232009-07-31 20:28:54 +00006326 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006327 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006328 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
6329 PD->protocol_begin(),
6330 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006331
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006332 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006333 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006334 "__DATA, __objc_const",
6335 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006336 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006337 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006338 "__DATA, __objc_const",
6339 ClassMethods);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006340 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006341 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006342 "__DATA, __objc_const",
6343 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006344 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006345 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006346 "__DATA, __objc_const",
6347 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006348 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006349 0, PD, ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006350 uint32_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006351 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006352 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0b75f232009-07-31 20:28:54 +00006353 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006354 Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
6355 + PD->getName(),
6356 MethodTypesExt, ObjCTypes);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006357 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006358 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006359
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006360 if (Entry) {
6361 // Already created, fix the linkage and update the initializer.
Fariborz Jahanian1d5c1fa2014-03-03 21:53:57 +00006362 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006363 Entry->setInitializer(Init);
6364 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006365 Entry =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006366 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6367 false, llvm::GlobalValue::WeakAnyLinkage, Init,
6368 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006369 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006370 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006371 Entry->setSection("__DATA,__datacoal_nt,coalesced");
John McCallf9582a72012-03-30 21:29:05 +00006372
6373 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006374 }
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006375 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006376 CGM.AddUsedGlobal(Entry);
6377
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006378 // Use this protocol meta-data to build protocol list table in section
6379 // __DATA, __objc_protolist
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006380 llvm::GlobalVariable *PTGV =
6381 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
6382 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
6383 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006384 PTGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006385 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbarb25452a2009-04-15 02:56:18 +00006386 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006387 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006388 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006389 return Entry;
6390}
6391
6392/// EmitProtocolList - Generate protocol list meta-data:
6393/// @code
6394/// struct _protocol_list_t {
6395/// long protocol_count; // Note, this is 32/64 bit
6396/// struct _protocol_t[protocol_count];
6397/// }
6398/// @endcode
6399///
6400llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006401CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006402 ObjCProtocolDecl::protocol_iterator begin,
6403 ObjCProtocolDecl::protocol_iterator end) {
Dmitri Gribenkof8579502013-01-12 19:30:44 +00006404 SmallVector<llvm::Constant *, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006405
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006406 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006407 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00006408 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006409
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006410 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006411 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006412 Name.toVector(TmpName);
6413 llvm::GlobalVariable *GV =
6414 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006415 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006416 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006417
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006418 for (; begin != end; ++begin)
6419 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
6420
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006421 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00006422 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006423 ObjCTypes.ProtocolnfABIPtrTy));
6424
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006425 llvm::Constant *Values[2];
Owen Anderson170229f2009-07-14 23:10:40 +00006426 Values[0] =
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006427 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006428 Values[1] =
Bill Wendlinga515b582012-02-09 22:16:49 +00006429 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
6430 ProtocolRefs.size()),
6431 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006432
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006433 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Owen Andersonc10c8d32009-07-08 19:05:04 +00006434 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00006435 llvm::GlobalValue::PrivateLinkage,
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006436 Init, Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00006437 assertPrivateName(GV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006438 GV->setSection("__DATA, __objc_const");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006439 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006440 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Chris Lattnerf56501c2009-07-17 23:57:13 +00006441 CGM.AddUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006442 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006443 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006444}
6445
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006446/// GetMethodDescriptionConstant - This routine build following meta-data:
6447/// struct _objc_method {
6448/// SEL _cmd;
6449/// char *method_type;
6450/// char *_imp;
6451/// }
6452
6453llvm::Constant *
6454CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006455 llvm::Constant *Desc[3];
Owen Anderson170229f2009-07-14 23:10:40 +00006456 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006457 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
6458 ObjCTypes.SelectorPtrTy);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006459 Desc[1] = GetMethodVarType(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006460 if (!Desc[1])
6461 return 0;
6462
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006463 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00006464 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006465 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006466}
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006467
6468/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
6469/// This code gen. amounts to generating code for:
6470/// @code
6471/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
6472/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006473///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00006474LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00006475 CodeGen::CodeGenFunction &CGF,
6476 QualType ObjectTy,
6477 llvm::Value *BaseValue,
6478 const ObjCIvarDecl *Ivar,
6479 unsigned CVRQualifiers) {
6480 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006481 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00006482
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00006483 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00006484 if (llvm::LoadInst *LI = cast<llvm::LoadInst>(Offset))
6485 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6486 llvm::MDNode::get(VMContext, ArrayRef<llvm::Value*>()));
6487
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00006488 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006489 Offset);
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006490}
6491
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006492llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006493 CodeGen::CodeGenFunction &CGF,
6494 const ObjCInterfaceDecl *Interface,
6495 const ObjCIvarDecl *Ivar) {
Daniel Dunbarc76493a2009-11-29 21:23:36 +00006496 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006497}
6498
John McCall234eac82011-05-13 23:16:18 +00006499static void appendSelectorForMessageRefTable(std::string &buffer,
6500 Selector selector) {
6501 if (selector.isUnarySelector()) {
6502 buffer += selector.getNameForSlot(0);
6503 return;
6504 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006505
John McCall234eac82011-05-13 23:16:18 +00006506 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
6507 buffer += selector.getNameForSlot(i);
6508 buffer += '_';
6509 }
6510}
6511
John McCall9e8bb002011-05-14 03:10:52 +00006512/// Emit a "v-table" message send. We emit a weak hidden-visibility
6513/// struct, initially containing the selector pointer and a pointer to
6514/// a "fixup" variant of the appropriate objc_msgSend. To call, we
6515/// load and call the function pointer, passing the address of the
6516/// struct as the second parameter. The runtime determines whether
6517/// the selector is currently emitted using vtable dispatch; if so, it
6518/// substitutes a stub function which simply tail-calls through the
6519/// appropriate vtable slot, and if not, it substitues a stub function
6520/// which tail-calls objc_msgSend. Both stubs adjust the selector
6521/// argument to correctly point to the selector.
6522RValue
6523CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
6524 ReturnValueSlot returnSlot,
6525 QualType resultType,
6526 Selector selector,
6527 llvm::Value *arg0,
6528 QualType arg0Type,
6529 bool isSuper,
6530 const CallArgList &formalArgs,
6531 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00006532 // Compute the actual arguments.
6533 CallArgList args;
6534
John McCall9e8bb002011-05-14 03:10:52 +00006535 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00006536 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00006537 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
6538 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00006539
John McCall9e8bb002011-05-14 03:10:52 +00006540 // Second argument: a pointer to the message ref structure. Leave
6541 // the actual argument value blank for now.
John McCall234eac82011-05-13 23:16:18 +00006542 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
6543
6544 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
6545
John McCalla729c622012-02-17 03:33:10 +00006546 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCall234eac82011-05-13 23:16:18 +00006547
John McCall5880fb82011-05-14 21:12:11 +00006548 NullReturnState nullReturn;
6549
John McCall9e8bb002011-05-14 03:10:52 +00006550 // Find the function to call and the mangled name for the message
6551 // ref structure. Using a different mangled name wouldn't actually
6552 // be a problem; it would just be a waste.
6553 //
6554 // The runtime currently never uses vtable dispatch for anything
6555 // except normal, non-super message-sends.
6556 // FIXME: don't use this for that.
John McCall234eac82011-05-13 23:16:18 +00006557 llvm::Constant *fn = 0;
6558 std::string messageRefName("\01l_");
John McCalla729c622012-02-17 03:33:10 +00006559 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
John McCall234eac82011-05-13 23:16:18 +00006560 if (isSuper) {
6561 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
6562 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006563 } else {
John McCall5880fb82011-05-14 21:12:11 +00006564 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00006565 fn = ObjCTypes.getMessageSendStretFixupFn();
6566 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006567 }
John McCall234eac82011-05-13 23:16:18 +00006568 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
6569 fn = ObjCTypes.getMessageSendFpretFixupFn();
6570 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00006571 } else {
John McCall234eac82011-05-13 23:16:18 +00006572 if (isSuper) {
6573 fn = ObjCTypes.getMessageSendSuper2FixupFn();
6574 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006575 } else {
John McCall234eac82011-05-13 23:16:18 +00006576 fn = ObjCTypes.getMessageSendFixupFn();
6577 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006578 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006579 }
John McCall234eac82011-05-13 23:16:18 +00006580 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
6581 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006582
John McCall234eac82011-05-13 23:16:18 +00006583 // Append the selector name, except use underscores anywhere we
6584 // would have used colons.
6585 appendSelectorForMessageRefTable(messageRefName, selector);
6586
6587 llvm::GlobalVariable *messageRef
6588 = CGM.getModule().getGlobalVariable(messageRefName);
6589 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00006590 // Build the message ref structure.
John McCall234eac82011-05-13 23:16:18 +00006591 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006592 llvm::Constant *init = llvm::ConstantStruct::getAnon(values);
John McCall234eac82011-05-13 23:16:18 +00006593 messageRef = new llvm::GlobalVariable(CGM.getModule(),
6594 init->getType(),
6595 /*constant*/ false,
6596 llvm::GlobalValue::WeakAnyLinkage,
6597 init,
6598 messageRefName);
6599 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
6600 messageRef->setAlignment(16);
6601 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
6602 }
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006603
6604 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00006605 if (CGM.getLangOpts().ObjCAutoRefCount && method)
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006606 for (ObjCMethodDecl::param_const_iterator i = method->param_begin(),
6607 e = method->param_end(); i != e; ++i) {
6608 const ParmVarDecl *ParamDecl = (*i);
6609 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
6610 if (!nullReturn.NullBB)
6611 nullReturn.init(CGF, arg0);
6612 requiresnullCheck = true;
6613 break;
6614 }
6615 }
6616
John McCall234eac82011-05-13 23:16:18 +00006617 llvm::Value *mref =
6618 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
6619
John McCall9e8bb002011-05-14 03:10:52 +00006620 // Update the message ref argument.
John McCall234eac82011-05-13 23:16:18 +00006621 args[1].RV = RValue::get(mref);
6622
6623 // Load the function to call from the message ref table.
6624 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
6625 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
6626
John McCalla729c622012-02-17 03:33:10 +00006627 callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
John McCall234eac82011-05-13 23:16:18 +00006628
John McCalla729c622012-02-17 03:33:10 +00006629 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006630 return nullReturn.complete(CGF, result, resultType, formalArgs,
6631 requiresnullCheck ? method : 0);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00006632}
6633
6634/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006635CodeGen::RValue
6636CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00006637 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006638 QualType ResultType,
6639 Selector Sel,
6640 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006641 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00006642 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006643 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00006644 return isVTableDispatchedSelector(Sel)
6645 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006646 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00006647 false, CallArgs, Method)
6648 : EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00006649 EmitSelector(CGF, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006650 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00006651 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00006652}
6653
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006654llvm::GlobalVariable *
Rafael Espindola554256c2014-02-26 22:25:45 +00006655CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name, bool Weak) {
6656 llvm::GlobalValue::LinkageTypes L =
6657 Weak ? llvm::GlobalValue::ExternalWeakLinkage
6658 : llvm::GlobalValue::ExternalLinkage;
6659
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006660 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
6661
Rafael Espindola554256c2014-02-26 22:25:45 +00006662 if (!GV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006663 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Rafael Espindola554256c2014-02-26 22:25:45 +00006664 false, L, 0, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006665
Rafael Espindola554256c2014-02-26 22:25:45 +00006666 assert(GV->getLinkage() == L);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006667 return GV;
6668}
6669
John McCall882987f2013-02-28 19:01:20 +00006670llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
Rafael Espindola554256c2014-02-26 22:25:45 +00006671 IdentifierInfo *II,
6672 bool Weak) {
John McCall31168b02011-06-15 23:02:42 +00006673 llvm::GlobalVariable *&Entry = ClassReferences[II];
6674
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006675 if (!Entry) {
John McCall31168b02011-06-15 23:02:42 +00006676 std::string ClassName(getClassSymbolPrefix() + II->getName().str());
Rafael Espindola554256c2014-02-26 22:25:45 +00006677 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, Weak);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006678 Entry =
John McCall31168b02011-06-15 23:02:42 +00006679 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00006680 false, llvm::GlobalValue::PrivateLinkage,
John McCall31168b02011-06-15 23:02:42 +00006681 ClassGV,
6682 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006683 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006684 CGM.getDataLayout().getABITypeAlignment(
John McCall31168b02011-06-15 23:02:42 +00006685 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006686 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006687 CGM.AddUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006688 }
Rafael Espindola21039aa2014-02-27 16:26:32 +00006689 assertPrivateName(Entry);
John McCall882987f2013-02-28 19:01:20 +00006690 return CGF.Builder.CreateLoad(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006691}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006692
John McCall882987f2013-02-28 19:01:20 +00006693llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00006694 const ObjCInterfaceDecl *ID) {
Rafael Espindola554256c2014-02-26 22:25:45 +00006695 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID->isWeakImported());
John McCall31168b02011-06-15 23:02:42 +00006696}
6697
6698llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
John McCall882987f2013-02-28 19:01:20 +00006699 CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00006700 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
Rafael Espindola554256c2014-02-26 22:25:45 +00006701 return EmitClassRefFromId(CGF, II, false);
John McCall31168b02011-06-15 23:02:42 +00006702}
6703
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006704llvm::Value *
John McCall882987f2013-02-28 19:01:20 +00006705CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006706 const ObjCInterfaceDecl *ID) {
6707 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006708
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006709 if (!Entry) {
6710 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6711 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006712 Entry =
6713 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00006714 false, llvm::GlobalValue::PrivateLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006715 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006716 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006717 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006718 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006719 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006720 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006721 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006722 }
Rafael Espindola21039aa2014-02-27 16:26:32 +00006723 assertPrivateName(Entry);
John McCall882987f2013-02-28 19:01:20 +00006724 return CGF.Builder.CreateLoad(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006725}
6726
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006727/// EmitMetaClassRef - Return a Value * of the address of _class_t
6728/// meta-data
6729///
John McCall882987f2013-02-28 19:01:20 +00006730llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006731 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006732 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
Rafael Espindola21039aa2014-02-27 16:26:32 +00006733 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006734
Rafael Espindola21039aa2014-02-27 16:26:32 +00006735 std::string MetaClassName(getMetaclassSymbolPrefix() +
6736 ID->getNameAsString());
6737 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
6738 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00006739 false, llvm::GlobalValue::PrivateLinkage,
Rafael Espindola21039aa2014-02-27 16:26:32 +00006740 MetaClassGV,
6741 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
6742 Entry->setAlignment(
6743 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006744
Rafael Espindola21039aa2014-02-27 16:26:32 +00006745 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
6746 CGM.AddUsedGlobal(Entry);
6747 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006748
Rafael Espindola21039aa2014-02-27 16:26:32 +00006749 assertPrivateName(Entry);
John McCall882987f2013-02-28 19:01:20 +00006750 return CGF.Builder.CreateLoad(Entry);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006751}
6752
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006753/// GetClass - Return a reference to the class for the given interface
6754/// decl.
John McCall882987f2013-02-28 19:01:20 +00006755llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006756 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00006757 if (ID->isWeakImported()) {
Fariborz Jahanian95ace552009-11-17 22:42:00 +00006758 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Rafael Espindola554256c2014-02-26 22:25:45 +00006759 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, true);
Nick Lewycky9a441642014-02-27 00:36:00 +00006760 (void)ClassGV;
Rafael Espindola554256c2014-02-26 22:25:45 +00006761 assert(ClassGV->getLinkage() == llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian95ace552009-11-17 22:42:00 +00006762 }
6763
John McCall882987f2013-02-28 19:01:20 +00006764 return EmitClassRef(CGF, ID);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006765}
6766
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006767/// Generates a message send where the super is the receiver. This is
6768/// a message send to self with special delivery semantics indicating
6769/// which class's method should be called.
6770CodeGen::RValue
6771CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00006772 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006773 QualType ResultType,
6774 Selector Sel,
6775 const ObjCInterfaceDecl *Class,
6776 bool isCategoryImpl,
6777 llvm::Value *Receiver,
6778 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006779 const CodeGen::CallArgList &CallArgs,
6780 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006781 // ...
6782 // Create and init a super structure; this is a (receiver, class)
6783 // pair we will pass to objc_msgSendSuper.
6784 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00006785 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006786
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006787 llvm::Value *ReceiverAsObject =
6788 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
6789 CGF.Builder.CreateStore(ReceiverAsObject,
6790 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006791
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006792 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00006793 llvm::Value *Target;
Fariborz Jahanian27678b02012-10-10 23:11:18 +00006794 if (IsClassMessage)
John McCall882987f2013-02-28 19:01:20 +00006795 Target = EmitMetaClassRef(CGF, Class);
Fariborz Jahanian27678b02012-10-10 23:11:18 +00006796 else
John McCall882987f2013-02-28 19:01:20 +00006797 Target = EmitSuperClassRef(CGF, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006798
Mike Stump18bb9282009-05-16 07:57:57 +00006799 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
6800 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00006801 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006802 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
6803 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
6804 CGF.Builder.CreateStore(Target,
6805 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006806
John McCall9e8bb002011-05-14 03:10:52 +00006807 return (isVTableDispatchedSelector(Sel))
6808 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006809 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006810 true, CallArgs, Method)
6811 : EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00006812 EmitSelector(CGF, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006813 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006814 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006815}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006816
John McCall882987f2013-02-28 19:01:20 +00006817llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006818 Selector Sel, bool lval) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006819 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006820
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006821 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006822 llvm::Constant *Casted =
6823 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
6824 ObjCTypes.SelectorPtrTy);
6825 Entry =
6826 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00006827 llvm::GlobalValue::PrivateLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006828 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Michael Gottesman5c205962013-02-05 23:08:45 +00006829 Entry->setExternallyInitialized(true);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006830 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006831 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006832 }
Rafael Espindola21039aa2014-02-27 16:26:32 +00006833 assertPrivateName(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006834
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006835 if (lval)
6836 return Entry;
John McCall882987f2013-02-28 19:01:20 +00006837 llvm::LoadInst* LI = CGF.Builder.CreateLoad(Entry);
Pete Cooper9d605512011-11-10 21:45:06 +00006838
6839 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6840 llvm::MDNode::get(VMContext,
6841 ArrayRef<llvm::Value*>()));
6842 return LI;
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006843}
Fariborz Jahanian06292952009-02-16 22:52:32 +00006844/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006845/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00006846///
6847void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006848 llvm::Value *src,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006849 llvm::Value *dst,
6850 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006851 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006852 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006853 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006854 assert(Size <= 8 && "does not support size > 8");
6855 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6856 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006857 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6858 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006859 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6860 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00006861 llvm::Value *args[] = { src, dst, ivarOffset };
6862 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006863}
6864
6865/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
6866/// objc_assign_strongCast (id src, id *dst)
6867///
6868void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006869 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006870 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006871 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006872 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006873 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006874 assert(Size <= 8 && "does not support size > 8");
6875 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006876 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006877 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6878 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006879 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6880 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00006881 llvm::Value *args[] = { src, dst };
6882 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
6883 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00006884}
6885
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006886void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006887 CodeGen::CodeGenFunction &CGF,
6888 llvm::Value *DestPtr,
6889 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00006890 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006891 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
6892 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall882987f2013-02-28 19:01:20 +00006893 llvm::Value *args[] = { DestPtr, SrcPtr, Size };
6894 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006895}
6896
Fariborz Jahanian06292952009-02-16 22:52:32 +00006897/// EmitObjCWeakRead - Code gen for loading value of a __weak
6898/// object: objc_read_weak (id *src)
6899///
6900llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006901 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006902 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006903 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006904 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
6905 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00006906 llvm::Value *read_weak =
6907 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
6908 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00006909 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006910 return read_weak;
6911}
6912
6913/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
6914/// objc_assign_weak (id src, id *dst)
6915///
6916void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006917 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006918 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006919 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006920 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006921 assert(Size <= 8 && "does not support size > 8");
6922 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6923 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006924 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6925 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006926 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6927 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00006928 llvm::Value *args[] = { src, dst };
6929 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
6930 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00006931}
6932
6933/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
6934/// objc_assign_global (id src, id *dst)
6935///
6936void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00006937 llvm::Value *src, llvm::Value *dst,
6938 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006939 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006940 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006941 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006942 assert(Size <= 8 && "does not support size > 8");
6943 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6944 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006945 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6946 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006947 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6948 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00006949 llvm::Value *args[] = { src, dst };
Fariborz Jahanian217af242010-07-20 20:30:03 +00006950 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00006951 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
6952 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00006953 else
John McCall882987f2013-02-28 19:01:20 +00006954 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
6955 args, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00006956}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006957
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006958void
John McCallbd309292010-07-06 01:34:17 +00006959CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6960 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006961 EmitAtSynchronizedStmt(CGF, S,
6962 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6963 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00006964}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006965
John McCall2ca705e2010-07-24 00:37:23 +00006966llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00006967CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00006968 // There's a particular fixed type info for 'id'.
6969 if (T->isObjCIdType() ||
6970 T->isObjCQualifiedIdType()) {
6971 llvm::Constant *IDEHType =
6972 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6973 if (!IDEHType)
6974 IDEHType =
6975 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6976 false,
6977 llvm::GlobalValue::ExternalLinkage,
6978 0, "OBJC_EHTYPE_id");
6979 return IDEHType;
6980 }
6981
6982 // All other types should be Objective-C interface pointer types.
6983 const ObjCObjectPointerType *PT =
6984 T->getAs<ObjCObjectPointerType>();
6985 assert(PT && "Invalid @catch type.");
6986 const ObjCInterfaceType *IT = PT->getInterfaceType();
6987 assert(IT && "Invalid @catch type.");
6988 return GetInterfaceEHType(IT->getDecl(), false);
6989}
6990
John McCallbd309292010-07-06 01:34:17 +00006991void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6992 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006993 EmitTryCatchStmt(CGF, S,
6994 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6995 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6996 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006997}
6998
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006999/// EmitThrowStmt - Generate code for a throw statement.
7000void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007001 const ObjCAtThrowStmt &S,
7002 bool ClearInsertionPoint) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007003 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00007004 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00007005 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00007006 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall17afe452010-10-16 08:21:07 +00007007 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007008 } else {
John McCall882987f2013-02-28 19:01:20 +00007009 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall17afe452010-10-16 08:21:07 +00007010 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007011 }
7012
John McCall17afe452010-10-16 08:21:07 +00007013 CGF.Builder.CreateUnreachable();
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007014 if (ClearInsertionPoint)
7015 CGF.Builder.ClearInsertionPoint();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007016}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007017
John McCall2ca705e2010-07-24 00:37:23 +00007018llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007019CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007020 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007021 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007022
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007023 // If we don't need a definition, return the entry if found or check
7024 // if we use an external reference.
7025 if (!ForDefinition) {
7026 if (Entry)
7027 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00007028
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007029 // If this type (or a super class) has the __objc_exception__
7030 // attribute, emit an external reference.
Douglas Gregor78bd61f2009-06-18 16:11:24 +00007031 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007032 return Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00007033 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007034 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007035 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007036 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00007037 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007038 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007039
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007040 // Otherwise we need to either make a new entry or fill in the
7041 // initializer.
7042 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar15894b72009-04-07 05:48:37 +00007043 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007044 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007045 llvm::GlobalVariable *VTableGV =
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007046 CGM.getModule().getGlobalVariable(VTableName);
7047 if (!VTableGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007048 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
7049 false,
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007050 llvm::GlobalValue::ExternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00007051 0, VTableName);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007052
Chris Lattnerece04092012-02-07 00:39:47 +00007053 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007054
Benjamin Kramer22d24c22011-10-15 12:20:02 +00007055 llvm::Constant *Values[] = {
7056 llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
7057 GetClassName(ID->getIdentifier()),
7058 GetClassGlobal(ClassName)
7059 };
Owen Anderson170229f2009-07-14 23:10:40 +00007060 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00007061 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007062
Rafael Espindola554256c2014-02-26 22:25:45 +00007063 llvm::GlobalValue::LinkageTypes L = ForDefinition
7064 ? llvm::GlobalValue::ExternalLinkage
7065 : llvm::GlobalValue::WeakAnyLinkage;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007066 if (Entry) {
7067 Entry->setInitializer(Init);
7068 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00007069 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Rafael Espindola554256c2014-02-26 22:25:45 +00007070 L,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007071 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007072 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00007073 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007074 }
Rafael Espindola554256c2014-02-26 22:25:45 +00007075 assert(Entry->getLinkage() == L);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007076
John McCalla4960982013-02-19 01:57:29 +00007077 if (ID->getVisibility() == HiddenVisibility)
Daniel Dunbar15894b72009-04-07 05:48:37 +00007078 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Micah Villmowdd31ca12012-10-08 16:25:52 +00007079 Entry->setAlignment(CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00007080 ObjCTypes.EHTypeTy));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007081
Rafael Espindola554256c2014-02-26 22:25:45 +00007082 if (ForDefinition)
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007083 Entry->setSection("__DATA,__objc_const");
Rafael Espindola554256c2014-02-26 22:25:45 +00007084 else
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007085 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007086
7087 return Entry;
7088}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007089
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00007090/* *** */
7091
Daniel Dunbarb036db82008-08-13 03:21:16 +00007092CodeGen::CGObjCRuntime *
7093CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall5fb5df92012-06-20 06:18:46 +00007094 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7095 case ObjCRuntime::FragileMacOSX:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007096 return new CGObjCMac(CGM);
John McCall5fb5df92012-06-20 06:18:46 +00007097
7098 case ObjCRuntime::MacOSX:
7099 case ObjCRuntime::iOS:
7100 return new CGObjCNonFragileABIMac(CGM);
7101
David Chisnallb601c962012-07-03 20:49:52 +00007102 case ObjCRuntime::GNUstep:
7103 case ObjCRuntime::GCC:
John McCall775086e2012-07-12 02:07:58 +00007104 case ObjCRuntime::ObjFW:
John McCall5fb5df92012-06-20 06:18:46 +00007105 llvm_unreachable("these runtimes are not Mac runtimes");
7106 }
7107 llvm_unreachable("bad runtime");
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007108}