blob: 5b49bcca09a78f8e03d575352e67eb5dd053d5ad [file] [log] [blame]
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattner57540c52011-04-15 05:22:18 +000010// This provides Objective-C code generation targeting the Apple runtime.
Daniel Dunbar303e2c22008-08-11 02:45:11 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000015
Daniel Dunbar034299e2010-03-31 01:09:11 +000016#include "CGRecordLayout.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000017#include "CodeGenModule.h"
Daniel Dunbara94ecd22008-08-16 03:19:19 +000018#include "CodeGenFunction.h"
John McCallad7c5c12011-02-08 08:22:06 +000019#include "CGBlocks.h"
John McCalled1ae862011-01-28 11:13:47 +000020#include "CGCleanup.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000021#include "clang/AST/ASTContext.h"
Daniel Dunbar221fa942008-08-11 04:54:23 +000022#include "clang/AST/Decl.h"
Daniel Dunbarb036db82008-08-13 03:21:16 +000023#include "clang/AST/DeclObjC.h"
Anders Carlsson15b73de2009-07-18 19:43:29 +000024#include "clang/AST/RecordLayout.h"
Chris Lattnerf0b64d72009-04-26 01:32:48 +000025#include "clang/AST/StmtObjC.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000026#include "clang/Basic/LangOptions.h"
Chandler Carruth85098242010-06-15 23:19:56 +000027#include "clang/Frontend/CodeGenOptions.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000028
John McCall42227ed2010-07-31 23:20:56 +000029#include "llvm/InlineAsm.h"
30#include "llvm/IntrinsicInst.h"
Owen Andersonae86c192009-07-13 04:10:07 +000031#include "llvm/LLVMContext.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000032#include "llvm/Module.h"
Daniel Dunbarc475d422008-10-29 22:36:39 +000033#include "llvm/ADT/DenseSet.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000034#include "llvm/ADT/SetVector.h"
35#include "llvm/ADT/SmallString.h"
Fariborz Jahanian751c1e72009-12-12 21:26:21 +000036#include "llvm/ADT/SmallPtrSet.h"
John McCall5c08ab92010-07-13 22:12:14 +000037#include "llvm/Support/CallSite.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000038#include "llvm/Support/raw_ostream.h"
Micah Villmowdd31ca12012-10-08 16:25:52 +000039#include "llvm/DataLayout.h"
Torok Edwindb714922009-08-24 13:25:12 +000040#include <cstdio>
Daniel Dunbar303e2c22008-08-11 02:45:11 +000041
42using namespace clang;
Daniel Dunbar41cf9de2008-09-09 01:06:48 +000043using namespace CodeGen;
Daniel Dunbar303e2c22008-08-11 02:45:11 +000044
45namespace {
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000046
Daniel Dunbar59e476b2009-08-03 17:06:42 +000047// FIXME: We should find a nicer way to make the labels for metadata, string
48// concatenation is lame.
Daniel Dunbarb036db82008-08-13 03:21:16 +000049
Fariborz Jahanian279eda62009-01-21 22:04:16 +000050class ObjCCommonTypesHelper {
Owen Anderson170229f2009-07-14 23:10:40 +000051protected:
52 llvm::LLVMContext &VMContext;
Daniel Dunbar59e476b2009-08-03 17:06:42 +000053
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000054private:
John McCall9dc0db22011-05-15 01:53:33 +000055 // The types of these functions don't really matter because we
56 // should always bitcast before calling them.
57
58 /// id objc_msgSend (id, SEL, ...)
59 ///
60 /// The default messenger, used for sends whose ABI is unchanged from
61 /// the all-integer/pointer case.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000062 llvm::Constant *getMessageSendFn() const {
John McCall31168b02011-06-15 23:02:42 +000063 // Add the non-lazy-bind attribute, since objc_msgSend is likely to
64 // be called a lot.
Chris Lattnera5f58b02011-07-09 17:41:47 +000065 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +000066 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
67 params, true),
John McCall31168b02011-06-15 23:02:42 +000068 "objc_msgSend",
Bill Wendling311c8322012-10-15 04:47:45 +000069 llvm::Attributes::get(CGM.getLLVMContext(),
Bill Wendling507c3512012-10-16 05:23:44 +000070 llvm::Attributes::NonLazyBind));
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000071 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000072
John McCall9dc0db22011-05-15 01:53:33 +000073 /// void objc_msgSend_stret (id, SEL, ...)
74 ///
75 /// The messenger used when the return value is an aggregate returned
76 /// by indirect reference in the first argument, and therefore the
77 /// self and selector parameters are shifted over by one.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000078 llvm::Constant *getMessageSendStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000079 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +000080 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
81 params, true),
82 "objc_msgSend_stret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000083
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000084 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000085
John McCall9dc0db22011-05-15 01:53:33 +000086 /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
87 ///
88 /// The messenger used when the return value is returned on the x87
89 /// floating-point stack; without a special entrypoint, the nil case
90 /// would be unbalanced.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000091 llvm::Constant *getMessageSendFpretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000092 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Chris Lattnerece04092012-02-07 00:39:47 +000093 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
94 params, true),
John McCall9dc0db22011-05-15 01:53:33 +000095 "objc_msgSend_fpret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000096
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000097 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000098
Anders Carlsson2f1a6c32011-10-31 16:27:11 +000099 /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
100 ///
101 /// The messenger used when the return value is returned in two values on the
102 /// x87 floating point stack; without a special entrypoint, the nil case
103 /// would be unbalanced. Only used on 64-bit X86.
104 llvm::Constant *getMessageSendFp2retFn() const {
105 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
106 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
107 llvm::Type *resultType =
108 llvm::StructType::get(longDoubleType, longDoubleType, NULL);
109
110 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
111 params, true),
112 "objc_msgSend_fp2ret");
113 }
114
John McCall9dc0db22011-05-15 01:53:33 +0000115 /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
116 ///
117 /// The messenger used for super calls, which have different dispatch
118 /// semantics. The class passed is the superclass of the current
119 /// class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000120 llvm::Constant *getMessageSendSuperFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000121 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000122 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000123 params, true),
124 "objc_msgSendSuper");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000125 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000126
John McCall9dc0db22011-05-15 01:53:33 +0000127 /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
128 ///
129 /// A slightly different messenger used for super calls. The class
130 /// passed is the current class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000131 llvm::Constant *getMessageSendSuperFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000132 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000133 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000134 params, true),
135 "objc_msgSendSuper2");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000136 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000137
John McCall9dc0db22011-05-15 01:53:33 +0000138 /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
139 /// SEL op, ...)
140 ///
141 /// The messenger used for super calls which return an aggregate indirectly.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000142 llvm::Constant *getMessageSendSuperStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000143 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000144 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000145 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000146 "objc_msgSendSuper_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000147 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000148
John McCall9dc0db22011-05-15 01:53:33 +0000149 /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
150 /// SEL op, ...)
151 ///
152 /// objc_msgSendSuper_stret with the super2 semantics.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000153 llvm::Constant *getMessageSendSuperStretFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000154 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000155 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000156 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000157 "objc_msgSendSuper2_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000158 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000159
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000160 llvm::Constant *getMessageSendSuperFpretFn() const {
161 // There is no objc_msgSendSuper_fpret? How can that work?
162 return getMessageSendSuperFn();
163 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000164
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000165 llvm::Constant *getMessageSendSuperFpretFn2() const {
166 // There is no objc_msgSendSuper_fpret? How can that work?
167 return getMessageSendSuperFn2();
168 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000169
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000170protected:
171 CodeGen::CodeGenModule &CGM;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000172
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000173public:
Chris Lattnera5f58b02011-07-09 17:41:47 +0000174 llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000175 llvm::Type *Int8PtrTy, *Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000176
Daniel Dunbar5d715592008-08-12 05:28:47 +0000177 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000178 llvm::Type *ObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000179
Fariborz Jahanian406b1172008-11-18 20:18:11 +0000180 /// PtrObjectPtrTy - LLVM type for id *
Chris Lattnera5f58b02011-07-09 17:41:47 +0000181 llvm::Type *PtrObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000182
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000183 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000184 llvm::Type *SelectorPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000185
186private:
Daniel Dunbarb036db82008-08-13 03:21:16 +0000187 /// ProtocolPtrTy - LLVM type for external protocol handles
188 /// (typeof(Protocol))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000189 llvm::Type *ExternalProtocolPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000190
191public:
192 llvm::Type *getExternalProtocolPtrTy() {
193 if (!ExternalProtocolPtrTy) {
194 // FIXME: It would be nice to unify this with the opaque type, so that the
195 // IR comes out a bit cleaner.
196 CodeGen::CodeGenTypes &Types = CGM.getTypes();
197 ASTContext &Ctx = CGM.getContext();
198 llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
199 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
200 }
201
202 return ExternalProtocolPtrTy;
203 }
204
Daniel Dunbarc722b852008-08-30 03:02:31 +0000205 // SuperCTy - clang type for struct objc_super.
206 QualType SuperCTy;
207 // SuperPtrCTy - clang type for struct objc_super *.
208 QualType SuperPtrCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000209
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000210 /// SuperTy - LLVM type for struct objc_super.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000211 llvm::StructType *SuperTy;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +0000212 /// SuperPtrTy - LLVM type for struct objc_super *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000213 llvm::Type *SuperPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000214
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000215 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
216 /// in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000217 llvm::StructType *PropertyTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000218
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000219 /// PropertyListTy - LLVM type for struct objc_property_list
220 /// (_prop_list_t in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000221 llvm::StructType *PropertyListTy;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000222 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000223 llvm::Type *PropertyListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000224
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000225 // MethodTy - LLVM type for struct objc_method.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000226 llvm::StructType *MethodTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000227
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000228 /// CacheTy - LLVM type for struct objc_cache.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000229 llvm::Type *CacheTy;
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000230 /// CachePtrTy - LLVM type for struct objc_cache *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000231 llvm::Type *CachePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000232
Chris Lattnerce8754e2009-04-22 02:44:54 +0000233 llvm::Constant *getGetPropertyFn() {
234 CodeGen::CodeGenTypes &Types = CGM.getTypes();
235 ASTContext &Ctx = CGM.getContext();
236 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000237 SmallVector<CanQualType,4> Params;
John McCall2da83a32010-02-26 00:48:12 +0000238 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
239 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000240 Params.push_back(IdType);
241 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000242 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000243 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000244 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000245 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(IdType, Params,
246 FunctionType::ExtInfo(),
247 RequiredArgs::All));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000248 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
249 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000250
Chris Lattnerce8754e2009-04-22 02:44:54 +0000251 llvm::Constant *getSetPropertyFn() {
252 CodeGen::CodeGenTypes &Types = CGM.getTypes();
253 ASTContext &Ctx = CGM.getContext();
254 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000255 SmallVector<CanQualType,6> Params;
John McCall2da83a32010-02-26 00:48:12 +0000256 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
257 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000258 Params.push_back(IdType);
259 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000260 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000261 Params.push_back(IdType);
262 Params.push_back(Ctx.BoolTy);
263 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000264 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000265 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
266 FunctionType::ExtInfo(),
267 RequiredArgs::All));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000268 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
269 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000270
Ted Kremeneke65b0862012-03-06 20:05:56 +0000271 llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) {
272 CodeGen::CodeGenTypes &Types = CGM.getTypes();
273 ASTContext &Ctx = CGM.getContext();
274 // void objc_setProperty_atomic(id self, SEL _cmd,
275 // id newValue, ptrdiff_t offset);
276 // void objc_setProperty_nonatomic(id self, SEL _cmd,
277 // id newValue, ptrdiff_t offset);
278 // void objc_setProperty_atomic_copy(id self, SEL _cmd,
279 // id newValue, ptrdiff_t offset);
280 // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
281 // id newValue, ptrdiff_t offset);
282
283 SmallVector<CanQualType,4> Params;
284 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
285 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
286 Params.push_back(IdType);
287 Params.push_back(SelType);
288 Params.push_back(IdType);
289 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
290 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000291 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
292 FunctionType::ExtInfo(),
293 RequiredArgs::All));
Ted Kremeneke65b0862012-03-06 20:05:56 +0000294 const char *name;
295 if (atomic && copy)
296 name = "objc_setProperty_atomic_copy";
297 else if (atomic && !copy)
298 name = "objc_setProperty_atomic";
299 else if (!atomic && copy)
300 name = "objc_setProperty_nonatomic_copy";
301 else
302 name = "objc_setProperty_nonatomic";
303
304 return CGM.CreateRuntimeFunction(FTy, name);
305 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000306
307 llvm::Constant *getCopyStructFn() {
308 CodeGen::CodeGenTypes &Types = CGM.getTypes();
309 ASTContext &Ctx = CGM.getContext();
310 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000311 SmallVector<CanQualType,5> Params;
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000312 Params.push_back(Ctx.VoidPtrTy);
313 Params.push_back(Ctx.VoidPtrTy);
314 Params.push_back(Ctx.LongTy);
315 Params.push_back(Ctx.BoolTy);
316 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000317 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000318 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
319 FunctionType::ExtInfo(),
320 RequiredArgs::All));
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000321 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
322 }
323
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000324 /// This routine declares and returns address of:
325 /// void objc_copyCppObjectAtomic(
326 /// void *dest, const void *src,
327 /// void (*copyHelper) (void *dest, const void *source));
328 llvm::Constant *getCppAtomicObjectFunction() {
329 CodeGen::CodeGenTypes &Types = CGM.getTypes();
330 ASTContext &Ctx = CGM.getContext();
331 /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
332 SmallVector<CanQualType,3> Params;
333 Params.push_back(Ctx.VoidPtrTy);
334 Params.push_back(Ctx.VoidPtrTy);
335 Params.push_back(Ctx.VoidPtrTy);
336 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000337 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
338 FunctionType::ExtInfo(),
339 RequiredArgs::All));
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000340 return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
341 }
342
Chris Lattnerce8754e2009-04-22 02:44:54 +0000343 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000344 CodeGen::CodeGenTypes &Types = CGM.getTypes();
345 ASTContext &Ctx = CGM.getContext();
Chris Lattnerce8754e2009-04-22 02:44:54 +0000346 // void objc_enumerationMutation (id)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000347 SmallVector<CanQualType,1> Params;
John McCall2da83a32010-02-26 00:48:12 +0000348 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Chris Lattner2192fe52011-07-18 04:24:23 +0000349 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000350 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
John McCalla729c622012-02-17 03:33:10 +0000351 FunctionType::ExtInfo(),
352 RequiredArgs::All));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000353 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
354 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000355
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000356 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattnerce8754e2009-04-22 02:44:54 +0000357 llvm::Constant *getGcReadWeakFn() {
358 // id objc_read_weak (id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000359 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000360 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000361 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000362 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000363 }
364
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000365 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000366 llvm::Constant *getGcAssignWeakFn() {
367 // id objc_assign_weak (id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000368 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000369 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000370 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000371 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
372 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000373
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000374 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000375 llvm::Constant *getGcAssignGlobalFn() {
376 // id objc_assign_global(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000377 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000378 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000379 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000380 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
381 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000382
Fariborz Jahanian217af242010-07-20 20:30:03 +0000383 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
384 llvm::Constant *getGcAssignThreadLocalFn() {
385 // id objc_assign_threadlocal(id src, id * dest)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000386 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian217af242010-07-20 20:30:03 +0000387 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000388 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian217af242010-07-20 20:30:03 +0000389 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
390 }
391
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000392 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000393 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000394 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000395 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
396 CGM.PtrDiffTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000397 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000398 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000399 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
400 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000401
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000402 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
403 llvm::Constant *GcMemmoveCollectableFn() {
404 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000405 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
John McCall9dc0db22011-05-15 01:53:33 +0000406 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000407 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
408 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000409
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000410 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000411 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000412 // id objc_assign_strongCast(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000413 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000414 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000415 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000416 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
417 }
Anders Carlsson9ab53d12009-02-16 22:59:18 +0000418
419 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000420 llvm::Constant *getExceptionThrowFn() {
421 // void objc_exception_throw(id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000422 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000423 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000424 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000425 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
426 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000427
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000428 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
429 llvm::Constant *getExceptionRethrowFn() {
430 // void objc_exception_rethrow(void)
John McCall9dc0db22011-05-15 01:53:33 +0000431 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000432 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
433 }
434
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000435 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerdcceee72009-04-06 16:53:45 +0000436 llvm::Constant *getSyncEnterFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000437 // int objc_sync_enter (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000438 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerdcceee72009-04-06 16:53:45 +0000439 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000440 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000441 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
442 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000443
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000444 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000445 llvm::Constant *getSyncExitFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000446 // int objc_sync_exit (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000447 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000448 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000449 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000450 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
451 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000452
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000453 llvm::Constant *getSendFn(bool IsSuper) const {
454 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
455 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000456
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000457 llvm::Constant *getSendFn2(bool IsSuper) const {
458 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
459 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000460
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000461 llvm::Constant *getSendStretFn(bool IsSuper) const {
462 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
463 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000464
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000465 llvm::Constant *getSendStretFn2(bool IsSuper) const {
466 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
467 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000468
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000469 llvm::Constant *getSendFpretFn(bool IsSuper) const {
470 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
471 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000472
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000473 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
474 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
475 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000476
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000477 llvm::Constant *getSendFp2retFn(bool IsSuper) const {
478 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
479 }
480
481 llvm::Constant *getSendFp2RetFn2(bool IsSuper) const {
482 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
483 }
484
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000485 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
486 ~ObjCCommonTypesHelper(){}
487};
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000488
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000489/// ObjCTypesHelper - Helper class that encapsulates lazy
490/// construction of varies types used during ObjC generation.
491class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000492public:
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000493 /// SymtabTy - LLVM type for struct objc_symtab.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000494 llvm::StructType *SymtabTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000495 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000496 llvm::Type *SymtabPtrTy;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000497 /// ModuleTy - LLVM type for struct objc_module.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000498 llvm::StructType *ModuleTy;
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000499
Daniel Dunbarb036db82008-08-13 03:21:16 +0000500 /// ProtocolTy - LLVM type for struct objc_protocol.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000501 llvm::StructType *ProtocolTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000502 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000503 llvm::Type *ProtocolPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000504 /// ProtocolExtensionTy - LLVM type for struct
505 /// objc_protocol_extension.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000506 llvm::StructType *ProtocolExtensionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000507 /// ProtocolExtensionTy - LLVM type for struct
508 /// objc_protocol_extension *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000509 llvm::Type *ProtocolExtensionPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000510 /// MethodDescriptionTy - LLVM type for struct
511 /// objc_method_description.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000512 llvm::StructType *MethodDescriptionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000513 /// MethodDescriptionListTy - LLVM type for struct
514 /// objc_method_description_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000515 llvm::StructType *MethodDescriptionListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000516 /// MethodDescriptionListPtrTy - LLVM type for struct
517 /// objc_method_description_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000518 llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000519 /// ProtocolListTy - LLVM type for struct objc_property_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000520 llvm::StructType *ProtocolListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000521 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000522 llvm::Type *ProtocolListPtrTy;
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000523 /// CategoryTy - LLVM type for struct objc_category.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000524 llvm::StructType *CategoryTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000525 /// ClassTy - LLVM type for struct objc_class.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000526 llvm::StructType *ClassTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000527 /// ClassPtrTy - LLVM type for struct objc_class *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000528 llvm::Type *ClassPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000529 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000530 llvm::StructType *ClassExtensionTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000531 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000532 llvm::Type *ClassExtensionPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000533 // IvarTy - LLVM type for struct objc_ivar.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000534 llvm::StructType *IvarTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000535 /// IvarListTy - LLVM type for struct objc_ivar_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000536 llvm::Type *IvarListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000537 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000538 llvm::Type *IvarListPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000539 /// MethodListTy - LLVM type for struct objc_method_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000540 llvm::Type *MethodListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000541 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000542 llvm::Type *MethodListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000543
Anders Carlsson9ff22482008-09-09 10:10:21 +0000544 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000545 llvm::Type *ExceptionDataTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000546
Anders Carlsson9ff22482008-09-09 10:10:21 +0000547 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000548 llvm::Constant *getExceptionTryEnterFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000549 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000550 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000551 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000552 "objc_exception_try_enter");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000553 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000554
555 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000556 llvm::Constant *getExceptionTryExitFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000557 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000558 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000559 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000560 "objc_exception_try_exit");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000561 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000562
563 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000564 llvm::Constant *getExceptionExtractFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000565 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000566 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000567 params, false),
Chris Lattnerc6406db2009-04-22 02:26:14 +0000568 "objc_exception_extract");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000569 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000570
Anders Carlsson9ff22482008-09-09 10:10:21 +0000571 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000572 llvm::Constant *getExceptionMatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000573 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000574 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000575 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000576 "objc_exception_match");
577
Chris Lattnerc6406db2009-04-22 02:26:14 +0000578 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000579
Anders Carlsson9ff22482008-09-09 10:10:21 +0000580 /// SetJmpFn - LLVM _setjmp function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000581 llvm::Constant *getSetJmpFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000582 // This is specifically the prototype for x86.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000583 llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
John McCall9dc0db22011-05-15 01:53:33 +0000584 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty,
585 params, false),
Bill Wendlingbcefeae2011-11-29 00:10:10 +0000586 "_setjmp",
Bill Wendling311c8322012-10-15 04:47:45 +0000587 llvm::Attributes::get(CGM.getLLVMContext(),
Bill Wendling507c3512012-10-16 05:23:44 +0000588 llvm::Attributes::NonLazyBind));
Chris Lattnerc6406db2009-04-22 02:26:14 +0000589 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000590
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000591public:
592 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000593 ~ObjCTypesHelper() {}
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000594};
595
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000596/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000597/// modern abi
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000598class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000599public:
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000600
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000601 // MethodListnfABITy - LLVM for struct _method_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000602 llvm::StructType *MethodListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000603
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000604 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000605 llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000606
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000607 // ProtocolnfABITy = LLVM for struct _protocol_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000608 llvm::StructType *ProtocolnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000609
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000610 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000611 llvm::Type *ProtocolnfABIPtrTy;
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000612
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000613 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
Chris Lattnera5f58b02011-07-09 17:41:47 +0000614 llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000615
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000616 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000617 llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000618
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000619 // ClassnfABITy - LLVM for struct _class_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000620 llvm::StructType *ClassnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000621
Fariborz Jahanian71394042009-01-23 23:53:38 +0000622 // ClassnfABIPtrTy - LLVM for struct _class_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000623 llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000624
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000625 // IvarnfABITy - LLVM for struct _ivar_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000626 llvm::StructType *IvarnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000627
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000628 // IvarListnfABITy - LLVM for struct _ivar_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000629 llvm::StructType *IvarListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000630
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000631 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000632 llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000633
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000634 // ClassRonfABITy - LLVM for struct _class_ro_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000635 llvm::StructType *ClassRonfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000636
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000637 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000638 llvm::Type *ImpnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000639
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000640 // CategorynfABITy - LLVM for struct _category_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000641 llvm::StructType *CategorynfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000642
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000643 // New types for nonfragile abi messaging.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000644
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000645 // MessageRefTy - LLVM for:
646 // struct _message_ref_t {
647 // IMP messenger;
648 // SEL name;
649 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000650 llvm::StructType *MessageRefTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000651 // MessageRefCTy - clang type for struct _message_ref_t
652 QualType MessageRefCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000653
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000654 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000655 llvm::Type *MessageRefPtrTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000656 // MessageRefCPtrTy - clang type for struct _message_ref_t*
657 QualType MessageRefCPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000658
Fariborz Jahanian4e87c832009-02-05 01:13:09 +0000659 // MessengerTy - Type of the messenger (shown as IMP above)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000660 llvm::FunctionType *MessengerTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000661
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000662 // SuperMessageRefTy - LLVM for:
663 // struct _super_message_ref_t {
664 // SUPER_IMP messenger;
665 // SEL name;
666 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000667 llvm::StructType *SuperMessageRefTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000668
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000669 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000670 llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000671
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000672 llvm::Constant *getMessageSendFixupFn() {
673 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000674 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000675 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000676 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000677 "objc_msgSend_fixup");
678 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000679
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000680 llvm::Constant *getMessageSendFpretFixupFn() {
681 // id objc_msgSend_fpret_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_fpret_fixup");
686 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000687
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000688 llvm::Constant *getMessageSendStretFixupFn() {
689 // id objc_msgSend_stret_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_stret_fixup");
694 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000695
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000696 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000697 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000698 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000699 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000700 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000701 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000702 "objc_msgSendSuper2_fixup");
703 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000704
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000705 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000706 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000707 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000708 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000709 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000710 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000711 "objc_msgSendSuper2_stret_fixup");
712 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000713
Chris Lattnera7c00b42009-04-22 02:15:23 +0000714 llvm::Constant *getObjCEndCatchFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000715 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000716 "objc_end_catch");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000717
Chris Lattnera7c00b42009-04-22 02:15:23 +0000718 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000719
Chris Lattnera7c00b42009-04-22 02:15:23 +0000720 llvm::Constant *getObjCBeginCatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000721 llvm::Type *params[] = { Int8PtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000722 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000723 params, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000724 "objc_begin_catch");
725 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +0000726
Chris Lattnera5f58b02011-07-09 17:41:47 +0000727 llvm::StructType *EHTypeTy;
728 llvm::Type *EHTypePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000729
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000730 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
731 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000732};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000733
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000734class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000735public:
736 // FIXME - accessibility
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000737 class GC_IVAR {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +0000738 public:
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000739 unsigned ivar_bytepos;
740 unsigned ivar_size;
741 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000742 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar22b0ada2009-04-23 01:29:05 +0000743
744 // Allow sorting based on byte pos.
745 bool operator<(const GC_IVAR &b) const {
746 return ivar_bytepos < b.ivar_bytepos;
747 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000748 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000749
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000750 class SKIP_SCAN {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000751 public:
752 unsigned skip;
753 unsigned scan;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000754 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000755 : skip(_skip), scan(_scan) {}
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000756 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000757
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000758 /// opcode for captured block variables layout 'instructions'.
759 /// In the following descriptions, 'I' is the value of the immediate field.
760 /// (field following the opcode).
761 ///
762 enum BLOCK_LAYOUT_OPCODE {
763 /// An operator which affects how the following layout should be
764 /// interpreted.
765 /// I == 0: Halt interpretation and treat everything else as
766 /// a non-pointer. Note that this instruction is equal
767 /// to '\0'.
768 /// I != 0: Currently unused.
769 BLOCK_LAYOUT_OPERATOR = 0,
770
771 /// The next I+1 bytes do not contain a value of object pointer type.
772 /// Note that this can leave the stream unaligned, meaning that
773 /// subsequent word-size instructions do not begin at a multiple of
774 /// the pointer size.
775 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
776
777 /// The next I+1 words do not contain a value of object pointer type.
778 /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
779 /// when the required skip quantity is a multiple of the pointer size.
780 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
781
782 /// The next I+1 words are __strong pointers to Objective-C
783 /// objects or blocks.
784 BLOCK_LAYOUT_STRONG = 3,
785
786 /// The next I+1 words are pointers to __block variables.
787 BLOCK_LAYOUT_BYREF = 4,
788
789 /// The next I+1 words are __weak pointers to Objective-C
790 /// objects or blocks.
791 BLOCK_LAYOUT_WEAK = 5,
792
793 /// The next I+1 words are __unsafe_unretained pointers to
794 /// Objective-C objects or blocks.
795 BLOCK_LAYOUT_UNRETAINED = 6
796
797 /// The next I+1 words are block or object pointers with some
798 /// as-yet-unspecified ownership semantics. If we add more
799 /// flavors of ownership semantics, values will be taken from
800 /// this range.
801 ///
802 /// This is included so that older tools can at least continue
803 /// processing the layout past such things.
804 //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
805
806 /// All other opcodes are reserved. Halt interpretation and
807 /// treat everything else as opaque.
808 };
809
810 class RUN_SKIP {
811 public:
812 enum BLOCK_LAYOUT_OPCODE opcode;
813 unsigned block_var_bytepos;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +0000814 unsigned block_var_size;
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000815 RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +0000816 unsigned BytePos = 0, unsigned Size = 0)
817 : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000818
819 // Allow sorting based on byte pos.
820 bool operator<(const RUN_SKIP &b) const {
821 return block_var_bytepos < b.block_var_bytepos;
822 }
823 };
824
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000825protected:
Owen Andersonae86c192009-07-13 04:10:07 +0000826 llvm::LLVMContext &VMContext;
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000827 // FIXME! May not be needing this after all.
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000828 unsigned ObjCABI;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000829
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000830 // gc ivar layout bitmap calculation helper caches.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000831 SmallVector<GC_IVAR, 16> SkipIvars;
832 SmallVector<GC_IVAR, 16> IvarsInfo;
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000833
834 // arc/mrr layout of captured block literal variables.
835 SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000836
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000837 /// LazySymbols - Symbols to generate a lazy reference for. See
838 /// DefinedSymbols and FinishModule().
Daniel Dunbard027a922009-09-07 00:20:42 +0000839 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000840
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000841 /// DefinedSymbols - External symbols which are defined by this
842 /// module. The symbols in this list and LazySymbols are used to add
843 /// special linker symbols which ensure that Objective-C modules are
844 /// linked properly.
Daniel Dunbard027a922009-09-07 00:20:42 +0000845 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000846
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000847 /// ClassNames - uniqued class names.
Daniel Dunbarb036db82008-08-13 03:21:16 +0000848 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000849
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000850 /// MethodVarNames - uniqued method variable names.
851 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000852
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000853 /// DefinedCategoryNames - list of category names in form Class_Category.
854 llvm::SetVector<std::string> DefinedCategoryNames;
855
Daniel Dunbarb036db82008-08-13 03:21:16 +0000856 /// MethodVarTypes - uniqued method type signatures. We have to use
857 /// a StringMap here because have no other unique reference.
858 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000859
Daniel Dunbar3c76cb52008-08-26 21:51:14 +0000860 /// MethodDefinitions - map of methods which have been defined in
861 /// this translation unit.
862 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000863
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000864 /// PropertyNames - uniqued method variable names.
865 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000866
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000867 /// ClassReferences - uniqued class references.
868 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000869
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000870 /// SelectorReferences - uniqued selector references.
871 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000872
Daniel Dunbarb036db82008-08-13 03:21:16 +0000873 /// Protocols - Protocols for which an objc_protocol structure has
874 /// been emitted. Forward declarations are handled by creating an
875 /// empty structure whose initializer is filled in when/if defined.
876 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000877
Daniel Dunbarc475d422008-10-29 22:36:39 +0000878 /// DefinedProtocols - Protocols which have actually been
879 /// defined. We should not need this, see FIXME in GenerateProtocol.
880 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000881
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000882 /// DefinedClasses - List of defined classes.
Bill Wendling8392a472012-02-07 09:40:07 +0000883 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000884
885 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
Bill Wendling8392a472012-02-07 09:40:07 +0000886 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000887
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000888 /// DefinedCategories - List of defined categories.
Bill Wendling8392a472012-02-07 09:40:07 +0000889 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000890
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000891 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
Bill Wendling8392a472012-02-07 09:40:07 +0000892 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000893
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000894 /// GetNameForMethod - Return a name for the given method.
895 /// \param[out] NameOut - The return value.
896 void GetNameForMethod(const ObjCMethodDecl *OMD,
897 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000898 SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000899
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000900 /// GetMethodVarName - Return a unique constant for the given
901 /// selector's name. The return value has type char *.
902 llvm::Constant *GetMethodVarName(Selector Sel);
903 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000904
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000905 /// GetMethodVarType - Return a unique constant for the given
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000906 /// method's type encoding string. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000907
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000908 // FIXME: This is a horrible name.
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000909 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
910 bool Extended = false);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000911 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000912
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000913 /// GetPropertyName - Return a unique constant for the given
914 /// name. The return value has type char *.
915 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000916
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000917 // FIXME: This can be dropped once string functions are unified.
918 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
919 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000920
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000921 /// GetClassName - Return a unique constant for the given selector's
922 /// name. The return value has type char *.
923 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000924
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000925 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
926
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000927 /// BuildIvarLayout - Builds ivar layout bitmap for the class
928 /// implementation for the __strong or __weak case.
929 ///
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000930 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
931 bool ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +0000932
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +0000933 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000934
Daniel Dunbar15bd8882009-05-03 14:10:34 +0000935 void BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000936 unsigned int BytePos, bool ForStrongLayout,
937 bool &HasUnion);
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +0000938 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000939 const llvm::StructLayout *Layout,
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000940 const RecordDecl *RD,
Bill Wendlingf1a3fca2012-02-22 09:30:11 +0000941 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000942 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahaniana123b642009-04-24 16:17:09 +0000943 bool &HasUnion);
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000944
Fariborz Jahanian01dff422009-03-05 19:17:31 +0000945 /// GetIvarLayoutName - Returns a unique constant for the given
946 /// ivar layout bitmap.
947 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
948 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000949
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000950 /// EmitPropertyList - Emit the given property list. The return
951 /// value has type PropertyListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000952 llvm::Constant *EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000953 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000954 const ObjCContainerDecl *OCD,
955 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000956
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000957 /// EmitProtocolMethodTypes - Generate the array of extended method type
958 /// strings. The return value has type Int8PtrPtrTy.
959 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +0000960 ArrayRef<llvm::Constant*> MethodTypes,
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000961 const ObjCCommonTypesHelper &ObjCTypes);
962
Fariborz Jahanian751c1e72009-12-12 21:26:21 +0000963 /// PushProtocolProperties - Push protocol's property on the input stack.
Bill Wendlinga515b582012-02-09 22:16:49 +0000964 void PushProtocolProperties(
965 llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
966 llvm::SmallVectorImpl<llvm::Constant*> &Properties,
967 const Decl *Container,
968 const ObjCProtocolDecl *PROTO,
969 const ObjCCommonTypesHelper &ObjCTypes);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +0000970
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000971 /// GetProtocolRef - Return a reference to the internal protocol
972 /// description, creating an empty one if it has not been
973 /// defined. The return value has type ProtocolPtrTy.
974 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +0000975
Daniel Dunbar30c65362009-03-09 20:09:19 +0000976 /// CreateMetadataVar - Create a global variable with internal
977 /// linkage for use by the Objective-C runtime.
978 ///
979 /// This is a convenience wrapper which not only creates the
980 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +0000981 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +0000982 ///
983 /// \param Name - The variable name.
984 /// \param Init - The variable initializer; this is also used to
985 /// define the type of the variable.
986 /// \param Section - The section the variable should go into, or 0.
987 /// \param Align - The alignment for the variable, or 0.
988 /// \param AddToUsed - Whether the variable should be added to
Daniel Dunbar4527d302009-04-14 17:42:51 +0000989 /// "llvm.used".
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000990 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +0000991 llvm::Constant *Init,
992 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +0000993 unsigned Align,
994 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +0000995
John McCall9e8bb002011-05-14 03:10:52 +0000996 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
997 ReturnValueSlot Return,
998 QualType ResultType,
999 llvm::Value *Sel,
1000 llvm::Value *Arg0,
1001 QualType Arg0Ty,
1002 bool IsSuper,
1003 const CallArgList &CallArgs,
1004 const ObjCMethodDecl *OMD,
1005 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +00001006
Daniel Dunbar5e639272010-04-25 20:39:01 +00001007 /// EmitImageInfo - Emit the image info marker used to encode some module
1008 /// level information.
1009 void EmitImageInfo();
1010
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001011public:
Owen Andersonae86c192009-07-13 04:10:07 +00001012 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
John McCalla729c622012-02-17 03:33:10 +00001013 CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001014
David Chisnall481e3a82010-01-23 02:40:42 +00001015 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Ted Kremeneke65b0862012-03-06 20:05:56 +00001016
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001017 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
1018 const ObjCContainerDecl *CD=0);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001019
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001020 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001021
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001022 /// GetOrEmitProtocol - Get the protocol object for the given
1023 /// declaration, emitting it if necessary. The return value has type
1024 /// ProtocolPtrTy.
1025 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001026
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001027 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1028 /// object for the given declaration, emitting it if needed. These
1029 /// forward references will be filled in with empty bodies if no
1030 /// definition is seen. The return value has type ProtocolPtrTy.
1031 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCall351762c2011-02-07 10:33:21 +00001032 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1033 const CGBlockInfo &blockInfo);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00001034 virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1035 const CGBlockInfo &blockInfo);
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00001036
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001037};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001038
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001039class CGObjCMac : public CGObjCCommonMac {
1040private:
1041 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001042
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001043 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001044 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001045 void EmitModuleInfo();
1046
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001047 /// EmitModuleSymols - Emit module symbols, the list of defined
1048 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001049 llvm::Constant *EmitModuleSymbols();
1050
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001051 /// FinishModule - Write out global data structures at the end of
1052 /// processing a translation unit.
1053 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +00001054
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001055 /// EmitClassExtension - Generate the class extension structure used
1056 /// to store the weak ivar layout and properties. The return value
1057 /// has type ClassExtensionPtrTy.
1058 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
1059
1060 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1061 /// for the given class.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001062 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001063 const ObjCInterfaceDecl *ID);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001064
John McCall31168b02011-06-15 23:02:42 +00001065 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
1066 IdentifierInfo *II);
1067
1068 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
1069
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001070 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1071 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001072
1073 /// EmitIvarList - Emit the ivar list for the given
1074 /// implementation. If ForClass is true the list of class ivars
1075 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1076 /// interface ivars will be emitted. The return value has type
1077 /// IvarListPtrTy.
1078 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00001079 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001080
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001081 /// EmitMetaClass - Emit a forward reference to the class structure
1082 /// for the metaclass of the given interface. The return value has
1083 /// type ClassPtrTy.
1084 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1085
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001086 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001087 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001088 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1089 llvm::Constant *Protocols,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001090 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001091
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001092 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001093
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001094 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001095
1096 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +00001097 /// implementation. The return value has type MethodListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001098 llvm::Constant *EmitMethodList(Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00001099 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001100 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001101
1102 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001103 /// method declarations.
Daniel Dunbarb036db82008-08-13 03:21:16 +00001104 /// - TypeName: The name for the type containing the methods.
Sylvestre Ledru33b5baf2012-09-27 10:16:10 +00001105 /// - IsProtocol: True iff these methods are for a protocol.
1106 /// - ClassMethds: True iff these are class methods.
Daniel Dunbarb036db82008-08-13 03:21:16 +00001107 /// - Required: When true, only "required" methods are
1108 /// listed. Similarly, when false only "optional" methods are
1109 /// listed. For classes this should always be true.
1110 /// - begin, end: The method list to output.
1111 ///
1112 /// The return value has type MethodDescriptionListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001113 llvm::Constant *EmitMethodDescList(Twine Name,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001114 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001115 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001116
Daniel Dunbarc475d422008-10-29 22:36:39 +00001117 /// GetOrEmitProtocol - Get the protocol object for the given
1118 /// declaration, emitting it if necessary. The return value has type
1119 /// ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001120 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001121
1122 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1123 /// object for the given declaration, emitting it if needed. These
1124 /// forward references will be filled in with empty bodies if no
1125 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001126 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001127
Daniel Dunbarb036db82008-08-13 03:21:16 +00001128 /// EmitProtocolExtension - Generate the protocol extension
1129 /// structure used to store optional instance and class methods, and
1130 /// protocol properties. The return value has type
1131 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001132 llvm::Constant *
1133 EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001134 ArrayRef<llvm::Constant*> OptInstanceMethods,
1135 ArrayRef<llvm::Constant*> OptClassMethods,
1136 ArrayRef<llvm::Constant*> MethodTypesExt);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001137
1138 /// EmitProtocolList - Generate the list of referenced
1139 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001140 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001141 ObjCProtocolDecl::protocol_iterator begin,
1142 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001143
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001144 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1145 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001146 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1147 bool lval=false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001148
1149public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001150 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001151
Fariborz Jahanian71394042009-01-23 23:53:38 +00001152 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001153
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001154 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001155 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001156 QualType ResultType,
1157 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001158 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001159 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001160 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001161 const ObjCMethodDecl *Method);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001162
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001163 virtual CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001164 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001165 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001166 QualType ResultType,
1167 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001168 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001169 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001170 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001171 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001172 const CallArgList &CallArgs,
1173 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001174
Daniel Dunbarcb463852008-11-01 01:53:16 +00001175 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001176 const ObjCInterfaceDecl *ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001177
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001178 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1179 bool lval = false);
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001180
1181 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1182 /// untyped one.
1183 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1184 const ObjCMethodDecl *Method);
1185
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001186 virtual llvm::Constant *GetEHType(QualType T);
John McCall2ca705e2010-07-24 00:37:23 +00001187
Daniel Dunbar92992502008-08-15 22:20:32 +00001188 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001189
Daniel Dunbar92992502008-08-15 22:20:32 +00001190 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001191
Daniel Dunbarf3d3b012012-02-28 15:36:15 +00001192 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {}
David Chisnall92d436b2012-01-31 18:59:20 +00001193
Daniel Dunbarcb463852008-11-01 01:53:16 +00001194 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00001195 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001196
Chris Lattnerd4808922009-03-22 21:03:39 +00001197 virtual llvm::Constant *GetPropertyGetFunction();
1198 virtual llvm::Constant *GetPropertySetFunction();
Ted Kremeneke65b0862012-03-06 20:05:56 +00001199 virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1200 bool copy);
David Chisnall168b80f2010-12-26 22:13:16 +00001201 virtual llvm::Constant *GetGetStructFunction();
1202 virtual llvm::Constant *GetSetStructFunction();
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001203 virtual llvm::Constant *GetCppAtomicObjectFunction();
Chris Lattnerd4808922009-03-22 21:03:39 +00001204 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001205
John McCallbd309292010-07-06 01:34:17 +00001206 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1207 const ObjCAtTryStmt &S);
1208 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1209 const ObjCAtSynchronizedStmt &S);
1210 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00001211 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1212 const ObjCAtThrowStmt &S);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001213 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001214 llvm::Value *AddrWeakObj);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001215 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001216 llvm::Value *src, llvm::Value *dst);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001217 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001218 llvm::Value *src, llvm::Value *dest,
1219 bool threadlocal = false);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00001220 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001221 llvm::Value *src, llvm::Value *dest,
1222 llvm::Value *ivarOffset);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001223 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1224 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001225 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1226 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001227 llvm::Value *size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001228
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001229 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1230 QualType ObjectTy,
1231 llvm::Value *BaseValue,
1232 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001233 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001234 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001235 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001236 const ObjCIvarDecl *Ivar);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001237
1238 /// GetClassGlobal - Return the global variable for the Objective-C
1239 /// class of the given name.
1240 virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) {
David Blaikie83d382b2011-09-23 05:06:16 +00001241 llvm_unreachable("CGObjCMac::GetClassGlobal");
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001242 }
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001243};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001244
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001245class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001246private:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001247 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001248 llvm::GlobalVariable* ObjCEmptyCacheVar;
1249 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001250
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001251 /// SuperClassReferences - uniqued super class references.
1252 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001253
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001254 /// MetaClassReferences - uniqued meta class references.
1255 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001256
1257 /// EHTypeReferences - uniqued class ehtype references.
1258 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001259
John McCall9e8bb002011-05-14 03:10:52 +00001260 /// VTableDispatchMethods - List of methods for which we generate
1261 /// vtable-based message dispatch.
1262 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001263
Fariborz Jahanian67260552009-11-17 21:37:35 +00001264 /// DefinedMetaClasses - List of defined meta-classes.
1265 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1266
John McCall9e8bb002011-05-14 03:10:52 +00001267 /// isVTableDispatchedSelector - Returns true if SEL is a
1268 /// vtable-based selector.
1269 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001270
Fariborz Jahanian71394042009-01-23 23:53:38 +00001271 /// FinishNonFragileABIModule - Write out global data structures at the end of
1272 /// processing a translation unit.
1273 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001274
Daniel Dunbar19573e72009-05-15 21:48:48 +00001275 /// AddModuleClassList - Add the given list of class pointers to the
1276 /// module with the provided symbol and section names.
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001277 void AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
Daniel Dunbar19573e72009-05-15 21:48:48 +00001278 const char *SymbolName,
1279 const char *SectionName);
1280
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001281 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1282 unsigned InstanceStart,
1283 unsigned InstanceSize,
1284 const ObjCImplementationDecl *ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001285 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001286 llvm::Constant *IsAGV,
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001287 llvm::Constant *SuperClassGV,
Fariborz Jahanian82208252009-01-31 00:59:10 +00001288 llvm::Constant *ClassRoGV,
1289 bool HiddenVisibility);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001290
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001291 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001292
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00001293 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001294
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001295 /// EmitMethodList - Emit the method list for the given
1296 /// implementation. The return value has type MethodListnfABITy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001297 llvm::Constant *EmitMethodList(Twine Name,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001298 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001299 ArrayRef<llvm::Constant*> Methods);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001300 /// EmitIvarList - Emit the ivar list for the given
1301 /// implementation. If ForClass is true the list of class ivars
1302 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1303 /// interface ivars will be emitted. The return value has type
1304 /// IvarListnfABIPtrTy.
1305 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001306
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001307 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001308 const ObjCIvarDecl *Ivar,
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00001309 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001310
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001311 /// GetOrEmitProtocol - Get the protocol object for the given
1312 /// declaration, emitting it if necessary. The return value has type
1313 /// ProtocolPtrTy.
1314 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001315
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001316 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1317 /// object for the given declaration, emitting it if needed. These
1318 /// forward references will be filled in with empty bodies if no
1319 /// definition is seen. The return value has type ProtocolPtrTy.
1320 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001321
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001322 /// EmitProtocolList - Generate the list of referenced
1323 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001324 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001325 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001326 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001327
John McCall9e8bb002011-05-14 03:10:52 +00001328 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1329 ReturnValueSlot Return,
1330 QualType ResultType,
1331 Selector Sel,
1332 llvm::Value *Receiver,
1333 QualType Arg0Ty,
1334 bool IsSuper,
1335 const CallArgList &CallArgs,
1336 const ObjCMethodDecl *Method);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001337
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001338 /// GetClassGlobal - Return the global variable for the Objective-C
1339 /// class of the given name.
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00001340 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001341
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001342 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001343 /// for the given class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001344 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001345 const ObjCInterfaceDecl *ID);
John McCall31168b02011-06-15 23:02:42 +00001346
1347 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
1348 IdentifierInfo *II);
1349
1350 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001351
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001352 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1353 /// for the given super class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001354 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1355 const ObjCInterfaceDecl *ID);
1356
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001357 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1358 /// meta-data
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001359 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001360 const ObjCInterfaceDecl *ID);
1361
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001362 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1363 /// the given ivar.
1364 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001365 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001366 const ObjCInterfaceDecl *ID,
1367 const ObjCIvarDecl *Ivar);
1368
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001369 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1370 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001371 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1372 bool lval=false);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001373
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001374 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001375 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001376 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001377 bool ForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001378
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001379 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar15894b72009-04-07 05:48:37 +00001380 return "OBJC_METACLASS_$_";
1381 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001382
Daniel Dunbar15894b72009-04-07 05:48:37 +00001383 const char *getClassSymbolPrefix() const {
1384 return "OBJC_CLASS_$_";
1385 }
1386
Daniel Dunbar961202372009-05-03 12:57:56 +00001387 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001388 uint32_t &InstanceStart,
1389 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001390
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001391 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001392 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001393 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1394 return CGM.getContext().Selectors.getSelector(0, &II);
1395 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001396
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001397 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001398 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1399 return CGM.getContext().Selectors.getSelector(1, &II);
1400 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001401
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001402 /// ImplementationIsNonLazy - Check whether the given category or
1403 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001404 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001405
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001406public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001407 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001408 // FIXME. All stubs for now!
1409 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001410
Fariborz Jahanian71394042009-01-23 23:53:38 +00001411 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001412 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001413 QualType ResultType,
1414 Selector Sel,
1415 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001416 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001417 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001418 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001419
1420 virtual CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001421 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001422 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001423 QualType ResultType,
1424 Selector Sel,
1425 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001426 bool isCategoryImpl,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001427 llvm::Value *Receiver,
1428 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001429 const CallArgList &CallArgs,
1430 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001431
Fariborz Jahanian71394042009-01-23 23:53:38 +00001432 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001433 const ObjCInterfaceDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001434
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001435 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1436 bool lvalue = false)
1437 { return EmitSelector(Builder, Sel, lvalue); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001438
1439 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1440 /// untyped one.
1441 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1442 const ObjCMethodDecl *Method)
1443 { return EmitSelector(Builder, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001444
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00001445 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001446
Fariborz Jahanian71394042009-01-23 23:53:38 +00001447 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
David Chisnall92d436b2012-01-31 18:59:20 +00001448
Daniel Dunbarf3d3b012012-02-28 15:36:15 +00001449 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {}
David Chisnall92d436b2012-01-31 18:59:20 +00001450
Fariborz Jahanian71394042009-01-23 23:53:38 +00001451 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian097feda2009-01-30 18:58:59 +00001452 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001453
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001454 virtual llvm::Constant *GetEHType(QualType T);
John McCall2ca705e2010-07-24 00:37:23 +00001455
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001456 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001457 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001458 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001459 virtual llvm::Constant *GetPropertySetFunction() {
1460 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001461 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001462
Ted Kremeneke65b0862012-03-06 20:05:56 +00001463 virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1464 bool copy) {
1465 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1466 }
1467
David Chisnall168b80f2010-12-26 22:13:16 +00001468 virtual llvm::Constant *GetSetStructFunction() {
1469 return ObjCTypes.getCopyStructFn();
1470 }
1471 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001472 return ObjCTypes.getCopyStructFn();
1473 }
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001474 virtual llvm::Constant *GetCppAtomicObjectFunction() {
1475 return ObjCTypes.getCppAtomicObjectFunction();
1476 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001477
Chris Lattnerd4808922009-03-22 21:03:39 +00001478 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001479 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001480 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001481
John McCallbd309292010-07-06 01:34:17 +00001482 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1483 const ObjCAtTryStmt &S);
1484 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1485 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001486 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlsson9ab53d12009-02-16 22:59:18 +00001487 const ObjCAtThrowStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001488 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001489 llvm::Value *AddrWeakObj);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001490 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001491 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001492 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001493 llvm::Value *src, llvm::Value *dest,
1494 bool threadlocal = false);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001495 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001496 llvm::Value *src, llvm::Value *dest,
1497 llvm::Value *ivarOffset);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001498 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001499 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001500 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1501 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001502 llvm::Value *size);
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001503 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1504 QualType ObjectTy,
1505 llvm::Value *BaseValue,
1506 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001507 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001508 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001509 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001510 const ObjCIvarDecl *Ivar);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001511};
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001512
1513/// A helper class for performing the null-initialization of a return
1514/// value.
1515struct NullReturnState {
1516 llvm::BasicBlock *NullBB;
1517 llvm::BasicBlock *callBB;
1518 NullReturnState() : NullBB(0), callBB(0) {}
1519
1520 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
1521 // Make blocks for the null-init and call edges.
1522 NullBB = CGF.createBasicBlock("msgSend.nullinit");
1523 callBB = CGF.createBasicBlock("msgSend.call");
1524
1525 // Check for a null receiver and, if there is one, jump to the
1526 // null-init test.
1527 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1528 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1529
1530 // Otherwise, start performing the call.
1531 CGF.EmitBlock(callBB);
1532 }
1533
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001534 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
1535 const CallArgList &CallArgs,
1536 const ObjCMethodDecl *Method) {
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001537 if (!NullBB) return result;
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001538
1539 llvm::Value *NullInitPtr = 0;
1540 if (result.isScalar() && !resultType->isVoidType()) {
1541 NullInitPtr = CGF.CreateTempAlloca(result.getScalarVal()->getType());
1542 CGF.Builder.CreateStore(result.getScalarVal(), NullInitPtr);
1543 }
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001544
1545 // Finish the call path.
1546 llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont");
1547 if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB);
1548
1549 // Emit the null-init block and perform the null-initialization there.
1550 CGF.EmitBlock(NullBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001551
1552 // Release consumed arguments along the null-receiver path.
1553 if (Method) {
1554 CallArgList::const_iterator I = CallArgs.begin();
1555 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1556 e = Method->param_end(); i != e; ++i, ++I) {
1557 const ParmVarDecl *ParamDecl = (*i);
1558 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1559 RValue RV = I->RV;
1560 assert(RV.isScalar() &&
1561 "NullReturnState::complete - arg not on object");
1562 CGF.EmitARCRelease(RV.getScalarVal(), true);
1563 }
1564 }
1565 }
1566
1567 if (result.isScalar()) {
1568 if (NullInitPtr)
1569 CGF.EmitNullInitialization(NullInitPtr, resultType);
1570 // Jump to the continuation block.
1571 CGF.EmitBlock(contBB);
1572 return NullInitPtr ? RValue::get(CGF.Builder.CreateLoad(NullInitPtr))
1573 : result;
1574 }
1575
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001576 if (!resultType->isAnyComplexType()) {
1577 assert(result.isAggregate() && "null init of non-aggregate result?");
1578 CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
1579 // Jump to the continuation block.
1580 CGF.EmitBlock(contBB);
1581 return result;
1582 }
1583
1584 // _Complex type
1585 // FIXME. Now easy to handle any other scalar type whose result is returned
1586 // in memory due to ABI limitations.
1587 CGF.EmitBlock(contBB);
1588 CodeGenFunction::ComplexPairTy CallCV = result.getComplexVal();
1589 llvm::Type *MemberType = CallCV.first->getType();
1590 llvm::Constant *ZeroCV = llvm::Constant::getNullValue(MemberType);
1591 // Create phi instruction for scalar complex value.
1592 llvm::PHINode *PHIReal = CGF.Builder.CreatePHI(MemberType, 2);
1593 PHIReal->addIncoming(ZeroCV, NullBB);
1594 PHIReal->addIncoming(CallCV.first, callBB);
1595 llvm::PHINode *PHIImag = CGF.Builder.CreatePHI(MemberType, 2);
1596 PHIImag->addIncoming(ZeroCV, NullBB);
1597 PHIImag->addIncoming(CallCV.second, callBB);
1598 return RValue::getComplex(PHIReal, PHIImag);
1599 }
1600};
1601
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001602} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001603
1604/* *** Helper Functions *** */
1605
1606/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001607static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001608 llvm::Constant *C,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001609 unsigned idx0,
1610 unsigned idx1) {
1611 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001612 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1613 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001614 };
Jay Foaded8db7d2011-07-21 14:31:17 +00001615 return llvm::ConstantExpr::getGetElementPtr(C, Idxs);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001616}
1617
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001618/// hasObjCExceptionAttribute - Return true if this class or any super
1619/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001620static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001621 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001622 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001623 return true;
1624 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001625 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001626 return false;
1627}
1628
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001629/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001630
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001631CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001632 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001633 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001634 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001635}
1636
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001637/// GetClass - Return a reference to the class for the given interface
1638/// decl.
Daniel Dunbarcb463852008-11-01 01:53:16 +00001639llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001640 const ObjCInterfaceDecl *ID) {
1641 return EmitClassRef(Builder, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001642}
1643
1644/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001645llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1646 bool lval) {
1647 return EmitSelector(Builder, Sel, lval);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001648}
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001649llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001650 *Method) {
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001651 return EmitSelector(Builder, Method->getSelector());
1652}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001653
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001654llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001655 if (T->isObjCIdType() ||
1656 T->isObjCQualifiedIdType()) {
1657 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001658 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001659 }
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001660 if (T->isObjCClassType() ||
1661 T->isObjCQualifiedClassType()) {
1662 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001663 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001664 }
1665 if (T->isObjCObjectPointerType())
1666 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
1667
John McCall2ca705e2010-07-24 00:37:23 +00001668 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall2ca705e2010-07-24 00:37:23 +00001669}
1670
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001671/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001672/*
1673 struct __builtin_CFString {
1674 const int *isa; // point to __CFConstantStringClassReference
1675 int flags;
1676 const char *str;
1677 long length;
1678 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001679*/
1680
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001681/// or Generate a constant NSString object.
1682/*
1683 struct __builtin_NSString {
1684 const int *isa; // point to __NSConstantStringClassReference
1685 const char *str;
1686 unsigned int length;
1687 };
1688*/
1689
Fariborz Jahanian71394042009-01-23 23:53:38 +00001690llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall481e3a82010-01-23 02:40:42 +00001691 const StringLiteral *SL) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001692 return (CGM.getLangOpts().NoConstantCFStrings == 0 ?
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001693 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian50c925f2010-10-19 17:19:29 +00001694 CGM.GetAddrOfConstantString(SL));
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001695}
1696
Ted Kremeneke65b0862012-03-06 20:05:56 +00001697enum {
1698 kCFTaggedObjectID_Integer = (1 << 1) + 1
1699};
1700
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001701/// Generates a message send where the super is the receiver. This is
1702/// a message send to self with special delivery semantics indicating
1703/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001704CodeGen::RValue
1705CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001706 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001707 QualType ResultType,
1708 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001709 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001710 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001711 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001712 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001713 const CodeGen::CallArgList &CallArgs,
1714 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001715 // Create and init a super structure; this is a (receiver, class)
1716 // pair we will pass to objc_msgSendSuper.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001717 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00001718 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001719 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001720 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001721 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001722 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001723
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001724 // If this is a class message the metaclass is passed as the target.
1725 llvm::Value *Target;
1726 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001727 if (isCategoryImpl) {
1728 // Message sent to 'super' in a class method defined in a category
1729 // implementation requires an odd treatment.
1730 // If we are in a class method, we must retrieve the
1731 // _metaclass_ for the current class, pointed at by
1732 // the class's "isa" pointer. The following assumes that
1733 // isa" is the first ivar in a class (which it must be).
1734 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1735 Target = CGF.Builder.CreateStructGEP(Target, 0);
1736 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00001737 } else {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001738 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1739 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1740 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1741 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001742 }
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00001743 }
1744 else if (isCategoryImpl)
1745 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1746 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001747 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1748 ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1749 Target = CGF.Builder.CreateLoad(ClassPtr);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001750 }
Mike Stump18bb9282009-05-16 07:57:57 +00001751 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1752 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00001753 llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00001754 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00001755 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001756 CGF.Builder.CreateStore(Target,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001757 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall9e8bb002011-05-14 03:10:52 +00001758 return EmitMessageSend(CGF, Return, ResultType,
1759 EmitSelector(CGF.Builder, Sel),
1760 ObjCSuper, ObjCTypes.SuperPtrCTy,
1761 true, CallArgs, Method, ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001762}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001763
1764/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001765CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001766 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001767 QualType ResultType,
1768 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001769 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001770 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001771 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001772 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00001773 return EmitMessageSend(CGF, Return, ResultType,
1774 EmitSelector(CGF.Builder, Sel),
1775 Receiver, CGF.getContext().getObjCIdType(),
1776 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00001777}
1778
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001779CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00001780CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1781 ReturnValueSlot Return,
1782 QualType ResultType,
1783 llvm::Value *Sel,
1784 llvm::Value *Arg0,
1785 QualType Arg0Ty,
1786 bool IsSuper,
1787 const CallArgList &CallArgs,
1788 const ObjCMethodDecl *Method,
1789 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc722b852008-08-30 03:02:31 +00001790 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00001791 if (!IsSuper)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00001792 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman43dca6a2011-05-02 17:57:46 +00001793 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1794 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCall31168b02011-06-15 23:02:42 +00001795 ActualArgs.addFrom(CallArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001796
John McCalla729c622012-02-17 03:33:10 +00001797 // If we're calling a method, use the formal signature.
1798 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001799
Anders Carlsson280e61f12010-06-21 20:59:55 +00001800 if (Method)
1801 assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
1802 CGM.getContext().getCanonicalType(ResultType) &&
1803 "Result type mismatch!");
1804
John McCall5880fb82011-05-14 21:12:11 +00001805 NullReturnState nullReturn;
1806
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001807 llvm::Constant *Fn = NULL;
John McCalla729c622012-02-17 03:33:10 +00001808 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001809 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001810 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001811 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001812 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1813 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1814 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +00001815 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
1816 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
1817 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001818 } else {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001819 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001820 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001821 }
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001822
1823 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001824 if (CGM.getLangOpts().ObjCAutoRefCount && Method)
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001825 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1826 e = Method->param_end(); i != e; ++i) {
1827 const ParmVarDecl *ParamDecl = (*i);
1828 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1829 if (!nullReturn.NullBB)
1830 nullReturn.init(CGF, Arg0);
1831 requiresnullCheck = true;
1832 break;
1833 }
1834 }
1835
John McCalla729c622012-02-17 03:33:10 +00001836 Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
1837 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001838 return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
1839 requiresnullCheck ? Method : 0);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001840}
1841
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001842static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1843 if (FQT.isObjCGCStrong())
1844 return Qualifiers::Strong;
1845
John McCall31168b02011-06-15 23:02:42 +00001846 if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001847 return Qualifiers::Weak;
1848
Fariborz Jahanian430b35e2012-02-16 00:15:02 +00001849 // check for __unsafe_unretained
1850 if (FQT.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
1851 return Qualifiers::GCNone;
1852
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001853 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1854 return Qualifiers::Strong;
1855
1856 if (const PointerType *PT = FQT->getAs<PointerType>())
1857 return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1858
1859 return Qualifiers::GCNone;
1860}
1861
John McCall351762c2011-02-07 10:33:21 +00001862llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1863 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00001864
Chris Lattnerece04092012-02-07 00:39:47 +00001865 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001866 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
1867 !CGM.getLangOpts().ObjCAutoRefCount)
John McCall351762c2011-02-07 10:33:21 +00001868 return nullPtr;
1869
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001870 bool hasUnion = false;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001871 SkipIvars.clear();
1872 IvarsInfo.clear();
Douglas Gregore8bbc122011-09-02 00:18:52 +00001873 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
1874 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001875
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00001876 // __isa is the first field in block descriptor and must assume by runtime's
1877 // convention that it is GC'able.
1878 IvarsInfo.push_back(GC_IVAR(0, 1));
John McCall351762c2011-02-07 10:33:21 +00001879
1880 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1881
1882 // Calculate the basic layout of the block structure.
1883 const llvm::StructLayout *layout =
Micah Villmowdd31ca12012-10-08 16:25:52 +00001884 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
John McCall351762c2011-02-07 10:33:21 +00001885
1886 // Ignore the optional 'this' capture: C++ objects are not assumed
1887 // to be GC'ed.
1888
1889 // Walk the captured variables.
1890 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1891 ce = blockDecl->capture_end(); ci != ce; ++ci) {
1892 const VarDecl *variable = ci->getVariable();
1893 QualType type = variable->getType();
1894
1895 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1896
1897 // Ignore constant captures.
1898 if (capture.isConstant()) continue;
1899
1900 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
1901
1902 // __block variables are passed by their descriptor address.
1903 if (ci->isByRef()) {
1904 IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00001905 continue;
John McCall351762c2011-02-07 10:33:21 +00001906 }
1907
1908 assert(!type->isArrayType() && "array variable should not be caught");
1909 if (const RecordType *record = type->getAs<RecordType>()) {
1910 BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00001911 continue;
1912 }
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001913
John McCall351762c2011-02-07 10:33:21 +00001914 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
1915 unsigned fieldSize = CGM.getContext().getTypeSize(type);
1916
1917 if (GCAttr == Qualifiers::Strong)
1918 IvarsInfo.push_back(GC_IVAR(fieldOffset,
1919 fieldSize / WordSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001920 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
John McCall351762c2011-02-07 10:33:21 +00001921 SkipIvars.push_back(GC_IVAR(fieldOffset,
1922 fieldSize / ByteSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001923 }
1924
1925 if (IvarsInfo.empty())
John McCall351762c2011-02-07 10:33:21 +00001926 return nullPtr;
1927
1928 // Sort on byte position; captures might not be allocated in order,
1929 // and unions can do funny things.
1930 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
1931 llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001932
1933 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00001934 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001935 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001936 printf("\n block variable layout for block: ");
Roman Divackye6377112012-09-06 15:59:27 +00001937 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling53136852012-02-07 09:06:01 +00001938 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001939 if (!(s[i] & 0xf0))
1940 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
1941 else
1942 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
1943 printf("\n");
1944 }
1945
1946 return C;
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00001947}
1948
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00001949llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
1950 const CGBlockInfo &blockInfo) {
1951 // FIXME. Temporary call the GC layout routine.
1952 return BuildGCBlockLayout(CGM, blockInfo);
1953
1954 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
1955
1956 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
1957
1958 RunSkipBlockVars.clear();
1959 // bool hasUnion = false;
1960 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
1961 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
1962 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
1963
1964 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1965
1966 // Calculate the basic layout of the block structure.
1967 const llvm::StructLayout *layout =
1968 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
1969
1970 // Ignore the optional 'this' capture: C++ objects are not assumed
1971 // to be GC'ed.
1972
1973 // Walk the captured variables.
1974 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1975 ce = blockDecl->capture_end(); ci != ce; ++ci) {
1976 const VarDecl *variable = ci->getVariable();
1977 QualType type = variable->getType();
1978
1979 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1980
1981 // Ignore constant captures.
1982 if (capture.isConstant()) continue;
1983
1984 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
1985
1986 // __block variables are passed by their descriptor address.
1987 if (ci->isByRef()) {
1988 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, fieldOffset,
1989 WordSizeInBytes));
1990 continue;
1991 }
1992
1993 assert(!type->isArrayType() && "array variable should not be caught");
1994 assert(!type->getAs<RecordType>() &&
1995 "BuildRCBlockLayout - captured records NYI");
1996
1997 unsigned fieldSize = CGM.getContext().getTypeSize(type);
1998
1999 if (type.getObjCLifetime() == Qualifiers::OCL_Strong)
2000 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, fieldOffset,
2001 WordSizeInBytes));
2002 else if (type.getObjCLifetime() == Qualifiers::OCL_Weak)
2003 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, fieldOffset,
2004 WordSizeInBytes));
2005 else if (type.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
2006 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, fieldOffset,
2007 WordSizeInBytes));
2008 else
2009 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, fieldOffset,
2010 fieldSize/ByteSizeInBits));
2011 }
2012
2013 if (RunSkipBlockVars.empty())
2014 return nullPtr;
2015
2016 // Sort on byte position; captures might not be allocated in order,
2017 // and unions can do funny things.
2018 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2019 std::string Layout;
2020
2021 unsigned size = RunSkipBlockVars.size();
2022 unsigned int shift = (WordSizeInBytes == 8) ? 3 : 2;
2023 unsigned int mask = (WordSizeInBytes == 8) ? 0x7 : 0x3;
2024 for (unsigned i = 0; i < size; i++) {
2025 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2026 unsigned start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2027 unsigned end_byte_pos = start_byte_pos;
2028 unsigned j = i+1;
2029 while (j < size) {
2030 if (opcode == RunSkipBlockVars[j].opcode) {
2031 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2032 i++;
2033 }
2034 else
2035 break;
2036 }
2037 unsigned size_in_bytes =
2038 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2039 unsigned residue_in_bytes = 0;
2040 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2041 residue_in_bytes = size_in_bytes & mask;
2042 size_in_bytes -= residue_in_bytes;
2043 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2044 }
2045
2046 unsigned size_in_words = size_in_bytes >> shift;
2047 while (size_in_words >= 16) {
2048 // Note that value in imm. is one less that the actual
2049 // value. So, 0xff means 16 words follow!
2050 unsigned char inst = (opcode << 4) | 0xff;
2051 Layout += inst;
2052 size_in_words -= 16;
2053 }
2054 if (size_in_words > 0) {
2055 // Note that value in imm. is one less that the actual
2056 // value. So, we subtract 1 away!
2057 unsigned char inst = (opcode << 4) | (size_in_words-1);
2058 Layout += inst;
2059 }
2060 if (residue_in_bytes > 0) {
2061 unsigned char inst = (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | residue_in_bytes;
2062 Layout += inst;
2063 }
2064 }
2065 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2066 printf("\n block variable layout: ");
2067 for (unsigned i = 0, e = Layout.size(); i != e; i++) {
2068 unsigned char inst = Layout[i];
2069 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2070 unsigned delta = 1;
2071 switch (opcode) {
2072 case BLOCK_LAYOUT_OPERATOR:
2073 printf("BL_OPERATOR:");
2074 break;
2075 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2076 printf("BL_NON_OBJECT_BYTES:");
2077 delta = 0;
2078 break;
2079 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2080 printf("BL_NON_OBJECT_WORD:");
2081 break;
2082 case BLOCK_LAYOUT_STRONG:
2083 printf("BL_STRONG:");
2084 break;
2085 case BLOCK_LAYOUT_BYREF:
2086 printf("BL_BYREF:");
2087 break;
2088 case BLOCK_LAYOUT_WEAK:
2089 printf("BL_WEAK:");
2090 break;
2091 case BLOCK_LAYOUT_UNRETAINED:
2092 printf("BL_UNRETAINE:");
2093 break;
2094 }
2095 // Actual value of word count is one more that what is in the imm.
2096 // field of the instruction
2097 printf("%d", (inst & 0xf) + delta);
2098 if (i < e-1)
2099 printf(", ");
2100 else
2101 printf("\n");
2102 }
2103 }
2104 return nullPtr;
2105}
2106
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002107llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00002108 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00002109 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002110 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00002111 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2112
Owen Andersonade90fd2009-07-29 18:54:39 +00002113 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00002114 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002115}
2116
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002117void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00002118 // FIXME: We shouldn't need this, the protocol decl should contain enough
2119 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00002120 DefinedProtocols.insert(PD->getIdentifier());
2121
2122 // If we have generated a forward reference to this protocol, emit
2123 // it now. Otherwise do nothing, the protocol objects are lazily
2124 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002125 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00002126 GetOrEmitProtocol(PD);
2127}
2128
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002129llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002130 if (DefinedProtocols.count(PD->getIdentifier()))
2131 return GetOrEmitProtocol(PD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002132
Daniel Dunbarc475d422008-10-29 22:36:39 +00002133 return GetOrEmitProtocolRef(PD);
2134}
2135
Daniel Dunbarb036db82008-08-13 03:21:16 +00002136/*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002137// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
2138struct _objc_protocol {
2139struct _objc_protocol_extension *isa;
2140char *protocol_name;
2141struct _objc_protocol_list *protocol_list;
2142struct _objc__method_prototype_list *instance_methods;
2143struct _objc__method_prototype_list *class_methods
2144};
Daniel Dunbarb036db82008-08-13 03:21:16 +00002145
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002146See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00002147*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00002148llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00002149 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbarc475d422008-10-29 22:36:39 +00002150
2151 // Early exit if a defining object has already been generated.
2152 if (Entry && Entry->hasInitializer())
2153 return Entry;
2154
Douglas Gregora715bff2012-01-01 19:51:50 +00002155 // Use the protocol definition, if there is one.
2156 if (const ObjCProtocolDecl *Def = PD->getDefinition())
2157 PD = Def;
2158
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002159 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002160 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002161 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2162
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002163 // Construct method lists.
2164 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2165 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002166 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002167 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002168 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002169 ObjCMethodDecl *MD = *i;
2170 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002171 if (!C)
2172 return GetOrEmitProtocolRef(PD);
2173
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002174 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2175 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002176 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002177 } else {
2178 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002179 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002180 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002181 }
2182
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002183 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002184 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002185 ObjCMethodDecl *MD = *i;
2186 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002187 if (!C)
2188 return GetOrEmitProtocolRef(PD);
2189
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002190 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2191 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002192 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002193 } else {
2194 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002195 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002196 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002197 }
2198
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002199 MethodTypesExt.insert(MethodTypesExt.end(),
2200 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
2201
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002202 llvm::Constant *Values[] = {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002203 EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods,
2204 MethodTypesExt),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002205 GetClassName(PD->getIdentifier()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002206 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardec75f82008-08-21 21:57:41 +00002207 PD->protocol_begin(),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002208 PD->protocol_end()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002209 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002210 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002211 InstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002212 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002213 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002214 ClassMethods)
2215 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002216 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002217 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002218
Daniel Dunbarb036db82008-08-13 03:21:16 +00002219 if (Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002220 // Already created, fix the linkage and update the initializer.
2221 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002222 Entry->setInitializer(Init);
2223 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002224 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002225 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002226 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002227 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002228 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002229 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002230 // FIXME: Is this necessary? Why only for protocol?
2231 Entry->setAlignment(4);
John McCallf9582a72012-03-30 21:29:05 +00002232
2233 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002234 }
Chris Lattnerf56501c2009-07-17 23:57:13 +00002235 CGM.AddUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00002236
2237 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002238}
2239
Daniel Dunbarc475d422008-10-29 22:36:39 +00002240llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002241 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
2242
2243 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002244 // We use the initializer as a marker of whether this is a forward
2245 // reference or not. At module finalization we add the empty
2246 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002247 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002248 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarc475d422008-10-29 22:36:39 +00002249 llvm::GlobalValue::ExternalLinkage,
2250 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002251 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002252 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002253 // FIXME: Is this necessary? Why only for protocol?
2254 Entry->setAlignment(4);
2255 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002256
Daniel Dunbarb036db82008-08-13 03:21:16 +00002257 return Entry;
2258}
2259
2260/*
2261 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002262 uint32_t size;
2263 struct objc_method_description_list *optional_instance_methods;
2264 struct objc_method_description_list *optional_class_methods;
2265 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002266 const char ** extendedMethodTypes;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002267 };
2268*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002269llvm::Constant *
2270CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002271 ArrayRef<llvm::Constant*> OptInstanceMethods,
2272 ArrayRef<llvm::Constant*> OptClassMethods,
2273 ArrayRef<llvm::Constant*> MethodTypesExt) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002274 uint64_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00002275 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002276 llvm::Constant *Values[] = {
2277 llvm::ConstantInt::get(ObjCTypes.IntTy, Size),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002278 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002279 + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002280 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002281 OptInstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002282 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002283 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002284 OptClassMethods),
2285 EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002286 ObjCTypes),
2287 EmitProtocolMethodTypes("\01L_OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
2288 MethodTypesExt, ObjCTypes)
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002289 };
Daniel Dunbarb036db82008-08-13 03:21:16 +00002290
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002291 // Return null if no extension bits are used.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002292 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002293 Values[3]->isNullValue() && Values[4]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002294 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002295
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002296 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002297 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002298
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002299 // No special section, but goes in llvm.used
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002300 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002301 Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002302 0, 0, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002303}
2304
2305/*
2306 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002307 struct objc_protocol_list *next;
2308 long count;
2309 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002310 };
2311*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00002312llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002313CGObjCMac::EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00002314 ObjCProtocolDecl::protocol_iterator begin,
2315 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendlinga515b582012-02-09 22:16:49 +00002316 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002317
Daniel Dunbardec75f82008-08-21 21:57:41 +00002318 for (; begin != end; ++begin)
2319 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002320
2321 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002322 if (ProtocolRefs.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002323 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002324
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002325 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00002326 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002327
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002328 llvm::Constant *Values[3];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002329 // This field is only used by the runtime.
Owen Anderson0b75f232009-07-31 20:28:54 +00002330 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002331 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002332 ProtocolRefs.size() - 1);
2333 Values[2] =
2334 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
2335 ProtocolRefs.size()),
Daniel Dunbarb036db82008-08-13 03:21:16 +00002336 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002337
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002338 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002339 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002340 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002341 4, false);
Owen Andersonade90fd2009-07-29 18:54:39 +00002342 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002343}
2344
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002345void CGObjCCommonMac::
2346PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
Bill Wendlinga515b582012-02-09 22:16:49 +00002347 llvm::SmallVectorImpl<llvm::Constant*> &Properties,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002348 const Decl *Container,
2349 const ObjCProtocolDecl *PROTO,
2350 const ObjCCommonTypesHelper &ObjCTypes) {
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002351 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
2352 E = PROTO->protocol_end(); P != E; ++P)
2353 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
2354 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
2355 E = PROTO->prop_end(); I != E; ++I) {
David Blaikie40ed2972012-06-06 20:45:41 +00002356 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002357 if (!PropertySet.insert(PD->getIdentifier()))
2358 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002359 llvm::Constant *Prop[] = {
2360 GetPropertyName(PD->getIdentifier()),
2361 GetPropertyTypeString(PD, Container)
2362 };
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002363 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
2364 }
2365}
2366
Daniel Dunbarb036db82008-08-13 03:21:16 +00002367/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002368 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00002369 const char * const name;
2370 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002371 };
2372
2373 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002374 uint32_t entsize; // sizeof (struct _objc_property)
2375 uint32_t prop_count;
2376 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002377 };
2378*/
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002379llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002380 const Decl *Container,
2381 const ObjCContainerDecl *OCD,
2382 const ObjCCommonTypesHelper &ObjCTypes) {
Bill Wendlinga515b582012-02-09 22:16:49 +00002383 llvm::SmallVector<llvm::Constant*, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002384 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002385 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
2386 E = OCD->prop_end(); I != E; ++I) {
David Blaikie40ed2972012-06-06 20:45:41 +00002387 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002388 PropertySet.insert(PD->getIdentifier());
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002389 llvm::Constant *Prop[] = {
2390 GetPropertyName(PD->getIdentifier()),
2391 GetPropertyTypeString(PD, Container)
2392 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002393 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002394 Prop));
2395 }
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002396 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek0ef508d2010-09-01 01:21:15 +00002397 for (ObjCInterfaceDecl::all_protocol_iterator
2398 P = OID->all_referenced_protocol_begin(),
2399 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002400 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2401 ObjCTypes);
2402 }
2403 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
2404 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
2405 E = CD->protocol_end(); P != E; ++P)
2406 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2407 ObjCTypes);
2408 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002409
2410 // Return null for empty list.
2411 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002412 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002413
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002414 unsigned PropertySize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00002415 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002416 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002417 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
2418 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002419 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002420 Properties.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002421 Values[2] = llvm::ConstantArray::get(AT, Properties);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002422 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002423
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002424 llvm::GlobalVariable *GV =
2425 CreateMetadataVar(Name, Init,
2426 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002427 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002428 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002429 true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002430 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002431}
2432
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002433llvm::Constant *
2434CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
2435 ArrayRef<llvm::Constant*> MethodTypes,
2436 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002437 // Return null for empty list.
2438 if (MethodTypes.empty())
2439 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
2440
2441 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
2442 MethodTypes.size());
2443 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
2444
2445 llvm::GlobalVariable *GV =
2446 CreateMetadataVar(Name, Init,
2447 (ObjCABI == 2) ? "__DATA, __objc_const" : 0,
2448 (ObjCABI == 2) ? 8 : 4,
2449 true);
2450 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
2451}
2452
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002453/*
Daniel Dunbarb036db82008-08-13 03:21:16 +00002454 struct objc_method_description_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002455 int count;
2456 struct objc_method_description list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002457 };
2458*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002459llvm::Constant *
2460CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002461 llvm::Constant *Desc[] = {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002462 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002463 ObjCTypes.SelectorPtrTy),
2464 GetMethodVarType(MD)
2465 };
Douglas Gregora9d84932011-05-27 01:19:52 +00002466 if (!Desc[1])
2467 return 0;
2468
Owen Anderson0e0189d2009-07-27 22:29:56 +00002469 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002470 Desc);
2471}
Daniel Dunbarb036db82008-08-13 03:21:16 +00002472
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002473llvm::Constant *
2474CGObjCMac::EmitMethodDescList(Twine Name, const char *Section,
2475 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002476 // Return null for empty list.
2477 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002478 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002479
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002480 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002481 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002482 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002483 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002484 Values[1] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002485 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002486
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002487 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002488 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002489 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002490}
2491
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002492/*
2493 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002494 char *category_name;
2495 char *class_name;
2496 struct _objc_method_list *instance_methods;
2497 struct _objc_method_list *class_methods;
2498 struct _objc_protocol_list *protocols;
2499 uint32_t size; // <rdar://4585769>
2500 struct _objc_property_list *instance_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002501 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002502*/
Daniel Dunbar92992502008-08-15 22:20:32 +00002503void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00002504 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002505
Mike Stump18bb9282009-05-16 07:57:57 +00002506 // FIXME: This is poor design, the OCD should have a pointer to the category
2507 // decl. Additionally, note that Category can be null for the @implementation
2508 // w/o an @interface case. Sema should just create one for us as it does for
2509 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002510 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002511 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002512 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002513
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002514 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002515 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2516 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002517
Bill Wendlinga515b582012-02-09 22:16:49 +00002518 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002519 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002520 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002521 // Instance methods should always be defined.
2522 InstanceMethods.push_back(GetMethodConstant(*i));
2523 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002524 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002525 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002526 // Class methods should always be defined.
2527 ClassMethods.push_back(GetMethodConstant(*i));
2528 }
2529
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002530 llvm::Constant *Values[7];
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002531 Values[0] = GetClassName(OCD->getIdentifier());
2532 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00002533 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002534 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002535 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002536 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002537 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002538 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002539 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002540 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002541 ClassMethods);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002542 if (Category) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002543 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002544 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002545 Category->protocol_begin(),
2546 Category->protocol_end());
2547 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002548 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002549 }
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002550 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002551
2552 // If there is no category @interface then there can be no properties.
2553 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002554 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002555 OCD, Category, ObjCTypes);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002556 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002557 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002558 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002559
Owen Anderson0e0189d2009-07-27 22:29:56 +00002560 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002561 Values);
2562
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002563 llvm::GlobalVariable *GV =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002564 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002565 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002566 4, true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002567 DefinedCategories.push_back(GV);
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00002568 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002569 // method definition entries must be clear for next implementation.
2570 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002571}
2572
John McCallef19dbb2012-10-17 04:53:23 +00002573enum FragileClassFlags {
2574 FragileABI_Class_Factory = 0x00001,
2575 FragileABI_Class_Meta = 0x00002,
2576 FragileABI_Class_HasCXXStructors = 0x02000,
2577 FragileABI_Class_Hidden = 0x20000
2578};
2579
2580enum NonFragileClassFlags {
2581 /// Is a meta-class.
2582 NonFragileABI_Class_Meta = 0x00001,
2583
2584 /// Is a root class.
2585 NonFragileABI_Class_Root = 0x00002,
2586
2587 /// Has a C++ constructor and destructor.
2588 NonFragileABI_Class_HasCXXStructors = 0x00004,
2589
2590 /// Has hidden visibility.
2591 NonFragileABI_Class_Hidden = 0x00010,
2592
2593 /// Has the exception attribute.
2594 NonFragileABI_Class_Exception = 0x00020,
2595
2596 /// (Obsolete) ARC-specific: this class has a .release_ivars method
2597 NonFragileABI_Class_HasIvarReleaser = 0x00040,
2598
2599 /// Class implementation was compiled under ARC.
John McCall0d54a172012-10-17 04:53:31 +00002600 NonFragileABI_Class_CompiledByARC = 0x00080,
2601
2602 /// Class has non-trivial destructors, but zero-initialization is okay.
2603 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002604};
2605
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002606/*
2607 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002608 Class isa;
2609 Class super_class;
2610 const char *name;
2611 long version;
2612 long info;
2613 long instance_size;
2614 struct _objc_ivar_list *ivars;
2615 struct _objc_method_list *methods;
2616 struct _objc_cache *cache;
2617 struct _objc_protocol_list *protocols;
2618 // Objective-C 1.0 extensions (<rdr://4585769>)
2619 const char *ivar_layout;
2620 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002621 };
2622
2623 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002624*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002625void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002626 DefinedSymbols.insert(ID->getIdentifier());
2627
Chris Lattner86d7d912008-11-24 03:54:41 +00002628 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002629 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002630 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002631 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002632 llvm::Constant *Protocols =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002633 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00002634 Interface->all_referenced_protocol_begin(),
2635 Interface->all_referenced_protocol_end());
John McCallef19dbb2012-10-17 04:53:23 +00002636 unsigned Flags = FragileABI_Class_Factory;
John McCall0d54a172012-10-17 04:53:31 +00002637 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCallef19dbb2012-10-17 04:53:23 +00002638 Flags |= FragileABI_Class_HasCXXStructors;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002639 unsigned Size =
Ken Dyckc8ae5502011-02-09 01:59:34 +00002640 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002641
2642 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00002643 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00002644 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002645
Bill Wendlinga515b582012-02-09 22:16:49 +00002646 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002647 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002648 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002649 // Instance methods should always be defined.
2650 InstanceMethods.push_back(GetMethodConstant(*i));
2651 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002652 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002653 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002654 // Class methods should always be defined.
2655 ClassMethods.push_back(GetMethodConstant(*i));
2656 }
2657
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002658 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002659 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie40ed2972012-06-06 20:45:41 +00002660 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002661
2662 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2663 ObjCPropertyDecl *PD = PID->getPropertyDecl();
2664
2665 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
2666 if (llvm::Constant *C = GetMethodConstant(MD))
2667 InstanceMethods.push_back(C);
2668 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
2669 if (llvm::Constant *C = GetMethodConstant(MD))
2670 InstanceMethods.push_back(C);
2671 }
2672 }
2673
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002674 llvm::Constant *Values[12];
Daniel Dunbarccf61832009-05-03 08:56:52 +00002675 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002676 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002677 // Record a reference to the super class.
2678 LazySymbols.insert(Super->getIdentifier());
2679
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002680 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002681 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002682 ObjCTypes.ClassPtrTy);
2683 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002684 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002685 }
2686 Values[ 2] = GetClassName(ID->getIdentifier());
2687 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002688 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2689 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2690 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002691 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002692 Values[ 7] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002693 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002694 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002695 InstanceMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002696 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002697 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002698 Values[ 9] = Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002699 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002700 Values[11] = EmitClassExtension(ID);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002701 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002702 Values);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002703 std::string Name("\01L_OBJC_CLASS_");
2704 Name += ClassName;
2705 const char *Section = "__OBJC,__class,regular,no_dead_strip";
2706 // Check for a forward reference.
2707 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2708 if (GV) {
2709 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2710 "Forward metaclass reference has incorrect type.");
2711 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2712 GV->setInitializer(Init);
2713 GV->setSection(Section);
2714 GV->setAlignment(4);
2715 CGM.AddUsedGlobal(GV);
2716 }
2717 else
2718 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002719 DefinedClasses.push_back(GV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002720 // method definition entries must be clear for next implementation.
2721 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002722}
2723
2724llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2725 llvm::Constant *Protocols,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002726 ArrayRef<llvm::Constant*> Methods) {
John McCallef19dbb2012-10-17 04:53:23 +00002727 unsigned Flags = FragileABI_Class_Meta;
Micah Villmowdd31ca12012-10-08 16:25:52 +00002728 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002729
John McCall457a04e2010-10-22 21:05:15 +00002730 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00002731 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002732
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002733 llvm::Constant *Values[12];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002734 // The isa for the metaclass is the root of the hierarchy.
2735 const ObjCInterfaceDecl *Root = ID->getClassInterface();
2736 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2737 Root = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002738 Values[ 0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002739 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002740 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002741 // The super class for the metaclass is emitted as the name of the
2742 // super class. The runtime fixes this up to point to the
2743 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002744 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002745 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002746 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002747 ObjCTypes.ClassPtrTy);
2748 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002749 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002750 }
2751 Values[ 2] = GetClassName(ID->getIdentifier());
2752 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002753 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2754 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2755 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002756 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002757 Values[ 7] =
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002758 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002759 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002760 Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002761 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002762 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002763 Values[ 9] = Protocols;
2764 // ivar_layout for metaclass is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002765 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002766 // The class extension is always unused for metaclasses.
Owen Anderson0b75f232009-07-31 20:28:54 +00002767 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002768 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002769 Values);
2770
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002771 std::string Name("\01L_OBJC_METACLASS_");
Benjamin Kramer1bbcbd02012-07-31 11:45:39 +00002772 Name += ID->getName();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002773
2774 // Check for a forward reference.
2775 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2776 if (GV) {
2777 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2778 "Forward metaclass reference has incorrect type.");
2779 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2780 GV->setInitializer(Init);
2781 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00002782 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002783 llvm::GlobalValue::InternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002784 Init, Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002785 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002786 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbarae333842009-03-09 22:18:41 +00002787 GV->setAlignment(4);
Chris Lattnerf56501c2009-07-17 23:57:13 +00002788 CGM.AddUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002789
2790 return GV;
2791}
2792
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002793llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002794 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002795
Mike Stump18bb9282009-05-16 07:57:57 +00002796 // FIXME: Should we look these up somewhere other than the module. Its a bit
2797 // silly since we only generate these while processing an implementation, so
2798 // exactly one pointer would work if know when we entered/exitted an
2799 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002800
2801 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00002802 // Previously, metaclass with internal linkage may have been defined.
2803 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002804 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2805 true)) {
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002806 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2807 "Forward metaclass reference has incorrect type.");
2808 return GV;
2809 } else {
2810 // Generate as an external reference to keep a consistent
2811 // module. This will be patched up when we emit the metaclass.
Owen Andersonc10c8d32009-07-08 19:05:04 +00002812 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002813 llvm::GlobalValue::ExternalLinkage,
2814 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002815 Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002816 }
2817}
2818
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002819llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2820 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2821
2822 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2823 true)) {
2824 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2825 "Forward class metadata reference has incorrect type.");
2826 return GV;
2827 } else {
2828 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2829 llvm::GlobalValue::ExternalLinkage,
2830 0,
2831 Name);
2832 }
2833}
2834
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002835/*
2836 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002837 uint32_t size;
2838 const char *weak_ivar_layout;
2839 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002840 };
2841*/
2842llvm::Constant *
2843CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002844 uint64_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00002845 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002846
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002847 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002848 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian6df69862009-04-22 23:00:43 +00002849 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002850 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002851 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002852
2853 // Return null if no extension bits are used.
2854 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002855 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002856
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002857 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002858 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002859 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002860 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002861 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002862}
2863
2864/*
2865 struct objc_ivar {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00002866 char *ivar_name;
2867 char *ivar_type;
2868 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002869 };
2870
2871 struct objc_ivar_list {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00002872 int ivar_count;
2873 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002874 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002875*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002876llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002877 bool ForClass) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002878 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002879
2880 // When emitting the root class GCC emits ivar entries for the
2881 // actual class structure. It is not clear if we need to follow this
2882 // behavior; for now lets try and get away with not doing it. If so,
2883 // the cleanest solution would be to make up an ObjCInterfaceDecl
2884 // for the class.
2885 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00002886 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002887
Jordy Rosea91768e2011-07-22 02:08:32 +00002888 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002889
Jordy Rosea91768e2011-07-22 02:08:32 +00002890 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00002891 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00002892 // Ignore unnamed bit-fields.
2893 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002894 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002895 llvm::Constant *Ivar[] = {
2896 GetMethodVarName(IVD->getIdentifier()),
2897 GetMethodVarType(IVD),
2898 llvm::ConstantInt::get(ObjCTypes.IntTy,
2899 ComputeIvarBaseOffset(CGM, OID, IVD))
2900 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002901 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002902 }
2903
2904 // Return null for empty list.
2905 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002906 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002907
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002908 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002909 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002910 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002911 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002912 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002913 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002914
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002915 llvm::GlobalVariable *GV;
2916 if (ForClass)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002917 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002918 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002919 4, true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002920 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002921 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002922 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002923 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002924 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002925}
2926
2927/*
2928 struct objc_method {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002929 SEL method_name;
2930 char *method_types;
2931 void *method;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002932 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002933
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002934 struct objc_method_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002935 struct objc_method_list *obsolete;
2936 int count;
2937 struct objc_method methods_list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002938 };
2939*/
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002940
2941/// GetMethodConstant - Return a struct objc_method constant for the
2942/// given method if it has been defined. The result is null if the
2943/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002944llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00002945 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002946 if (!Fn)
2947 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002948
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002949 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00002950 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002951 ObjCTypes.SelectorPtrTy),
2952 GetMethodVarType(MD),
2953 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
2954 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002955 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002956}
2957
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002958llvm::Constant *CGObjCMac::EmitMethodList(Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002959 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002960 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002961 // Return null for empty list.
2962 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002963 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002964
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002965 llvm::Constant *Values[3];
Owen Anderson0b75f232009-07-31 20:28:54 +00002966 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002967 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002968 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002969 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002970 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002971 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002972
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002973 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002974 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002975}
2976
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00002977llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002978 const ObjCContainerDecl *CD) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002979 SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00002980 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002981
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00002982 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00002983 llvm::FunctionType *MethodTy =
John McCalla729c622012-02-17 03:33:10 +00002984 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002985 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00002986 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002987 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00002988 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002989 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002990 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002991
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002992 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002993}
2994
Daniel Dunbar30c65362009-03-09 20:09:19 +00002995llvm::GlobalVariable *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002996CGObjCCommonMac::CreateMetadataVar(Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00002997 llvm::Constant *Init,
2998 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00002999 unsigned Align,
3000 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003001 llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003002 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00003003 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerf56501c2009-07-17 23:57:13 +00003004 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003005 if (Section)
3006 GV->setSection(Section);
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003007 if (Align)
3008 GV->setAlignment(Align);
3009 if (AddToUsed)
Chris Lattnerf56501c2009-07-17 23:57:13 +00003010 CGM.AddUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003011 return GV;
3012}
3013
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003014llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003015 // Abuse this interface function as a place to finalize.
3016 FinishModule();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003017 return NULL;
3018}
3019
Chris Lattnerd4808922009-03-22 21:03:39 +00003020llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003021 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003022}
3023
Chris Lattnerd4808922009-03-22 21:03:39 +00003024llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003025 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003026}
3027
Ted Kremeneke65b0862012-03-06 20:05:56 +00003028llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
3029 bool copy) {
3030 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
3031}
3032
David Chisnall168b80f2010-12-26 22:13:16 +00003033llvm::Constant *CGObjCMac::GetGetStructFunction() {
3034 return ObjCTypes.getCopyStructFn();
3035}
3036llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00003037 return ObjCTypes.getCopyStructFn();
3038}
3039
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00003040llvm::Constant *CGObjCMac::GetCppAtomicObjectFunction() {
3041 return ObjCTypes.getCppAtomicObjectFunction();
3042}
3043
Chris Lattnerd4808922009-03-22 21:03:39 +00003044llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003045 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00003046}
3047
John McCallbd309292010-07-06 01:34:17 +00003048void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
3049 return EmitTryOrSynchronizedStmt(CGF, S);
3050}
3051
3052void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
3053 const ObjCAtSynchronizedStmt &S) {
3054 return EmitTryOrSynchronizedStmt(CGF, S);
3055}
3056
John McCall65bea082010-07-21 06:59:36 +00003057namespace {
John McCallcda666c2010-07-21 07:22:38 +00003058 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00003059 const Stmt &S;
John McCall2dd7d442010-08-04 05:59:32 +00003060 llvm::Value *SyncArgSlot;
John McCall65bea082010-07-21 06:59:36 +00003061 llvm::Value *CallTryExitVar;
3062 llvm::Value *ExceptionData;
3063 ObjCTypesHelper &ObjCTypes;
3064 PerformFragileFinally(const Stmt *S,
John McCall2dd7d442010-08-04 05:59:32 +00003065 llvm::Value *SyncArgSlot,
John McCall65bea082010-07-21 06:59:36 +00003066 llvm::Value *CallTryExitVar,
3067 llvm::Value *ExceptionData,
3068 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00003069 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00003070 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
3071
John McCall30317fd2011-07-12 20:27:29 +00003072 void Emit(CodeGenFunction &CGF, Flags flags) {
John McCall65bea082010-07-21 06:59:36 +00003073 // Check whether we need to call objc_exception_try_exit.
3074 // In optimized code, this branch will always be folded.
3075 llvm::BasicBlock *FinallyCallExit =
3076 CGF.createBasicBlock("finally.call_exit");
3077 llvm::BasicBlock *FinallyNoCallExit =
3078 CGF.createBasicBlock("finally.no_call_exit");
3079 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
3080 FinallyCallExit, FinallyNoCallExit);
3081
3082 CGF.EmitBlock(FinallyCallExit);
3083 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
3084 ->setDoesNotThrow();
3085
3086 CGF.EmitBlock(FinallyNoCallExit);
3087
3088 if (isa<ObjCAtTryStmt>(S)) {
3089 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00003090 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
3091 // Save the current cleanup destination in case there's
3092 // control flow inside the finally statement.
3093 llvm::Value *CurCleanupDest =
3094 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
3095
John McCall65bea082010-07-21 06:59:36 +00003096 CGF.EmitStmt(FinallyStmt->getFinallyBody());
3097
John McCallcebe0ca2010-08-11 00:16:14 +00003098 if (CGF.HaveInsertPoint()) {
3099 CGF.Builder.CreateStore(CurCleanupDest,
3100 CGF.getNormalCleanupDestSlot());
3101 } else {
3102 // Currently, the end of the cleanup must always exist.
3103 CGF.EnsureInsertPoint();
3104 }
3105 }
John McCall65bea082010-07-21 06:59:36 +00003106 } else {
3107 // Emit objc_sync_exit(expr); as finally's sole statement for
3108 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00003109 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall65bea082010-07-21 06:59:36 +00003110 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
3111 ->setDoesNotThrow();
3112 }
3113 }
3114 };
John McCall42227ed2010-07-31 23:20:56 +00003115
3116 class FragileHazards {
3117 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003118 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00003119 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
3120
3121 llvm::InlineAsm *ReadHazard;
3122 llvm::InlineAsm *WriteHazard;
3123
3124 llvm::FunctionType *GetAsmFnType();
3125
3126 void collectLocals();
3127 void emitReadHazard(CGBuilderTy &Builder);
3128
3129 public:
3130 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00003131
John McCall42227ed2010-07-31 23:20:56 +00003132 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00003133 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003134 };
3135}
3136
3137/// Create the fragile-ABI read and write hazards based on the current
3138/// state of the function, which is presumed to be immediately prior
3139/// to a @try block. These hazards are used to maintain correct
3140/// semantics in the face of optimization and the fragile ABI's
3141/// cavalier use of setjmp/longjmp.
3142FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
3143 collectLocals();
3144
3145 if (Locals.empty()) return;
3146
3147 // Collect all the blocks in the function.
3148 for (llvm::Function::iterator
3149 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
3150 BlocksBeforeTry.insert(&*I);
3151
3152 llvm::FunctionType *AsmFnTy = GetAsmFnType();
3153
3154 // Create a read hazard for the allocas. This inhibits dead-store
3155 // optimizations and forces the values to memory. This hazard is
3156 // inserted before any 'throwing' calls in the protected scope to
3157 // reflect the possibility that the variables might be read from the
3158 // catch block if the call throws.
3159 {
3160 std::string Constraint;
3161 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3162 if (I) Constraint += ',';
3163 Constraint += "*m";
3164 }
3165
3166 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3167 }
3168
3169 // Create a write hazard for the allocas. This inhibits folding
3170 // loads across the hazard. This hazard is inserted at the
3171 // beginning of the catch path to reflect the possibility that the
3172 // variables might have been written within the protected scope.
3173 {
3174 std::string Constraint;
3175 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3176 if (I) Constraint += ',';
3177 Constraint += "=*m";
3178 }
3179
3180 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3181 }
3182}
3183
3184/// Emit a write hazard at the current location.
3185void FragileHazards::emitWriteHazard() {
3186 if (Locals.empty()) return;
3187
Jay Foad5bd375a2011-07-15 08:37:34 +00003188 CGF.Builder.CreateCall(WriteHazard, Locals)->setDoesNotThrow();
John McCall42227ed2010-07-31 23:20:56 +00003189}
3190
John McCall42227ed2010-07-31 23:20:56 +00003191void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
3192 assert(!Locals.empty());
Jay Foad5bd375a2011-07-15 08:37:34 +00003193 Builder.CreateCall(ReadHazard, Locals)->setDoesNotThrow();
John McCall42227ed2010-07-31 23:20:56 +00003194}
3195
3196/// Emit read hazards in all the protected blocks, i.e. all the blocks
3197/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00003198void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00003199 if (Locals.empty()) return;
3200
3201 CGBuilderTy Builder(CGF.getLLVMContext());
3202
3203 // Iterate through all blocks, skipping those prior to the try.
3204 for (llvm::Function::iterator
3205 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
3206 llvm::BasicBlock &BB = *FI;
3207 if (BlocksBeforeTry.count(&BB)) continue;
3208
3209 // Walk through all the calls in the block.
3210 for (llvm::BasicBlock::iterator
3211 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
3212 llvm::Instruction &I = *BI;
3213
3214 // Ignore instructions that aren't non-intrinsic calls.
3215 // These are the only calls that can possibly call longjmp.
3216 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
3217 if (isa<llvm::IntrinsicInst>(I))
3218 continue;
3219
3220 // Ignore call sites marked nounwind. This may be questionable,
3221 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
3222 llvm::CallSite CS(&I);
3223 if (CS.doesNotThrow()) continue;
3224
John McCall2dd7d442010-08-04 05:59:32 +00003225 // Insert a read hazard before the call. This will ensure that
3226 // any writes to the locals are performed before making the
3227 // call. If the call throws, then this is sufficient to
3228 // guarantee correctness as long as it doesn't also write to any
3229 // locals.
John McCall42227ed2010-07-31 23:20:56 +00003230 Builder.SetInsertPoint(&BB, BI);
3231 emitReadHazard(Builder);
3232 }
3233 }
3234}
3235
3236static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
3237 if (V) S.insert(V);
3238}
3239
3240void FragileHazards::collectLocals() {
3241 // Compute a set of allocas to ignore.
3242 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
3243 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
3244 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00003245
3246 // Collect all the allocas currently in the function. This is
3247 // probably way too aggressive.
3248 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
3249 for (llvm::BasicBlock::iterator
3250 I = Entry.begin(), E = Entry.end(); I != E; ++I)
3251 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
3252 Locals.push_back(&*I);
3253}
3254
3255llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003256 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00003257 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
3258 tys[i] = Locals[i]->getType();
3259 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00003260}
3261
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003262/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003263
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003264 Objective-C setjmp-longjmp (sjlj) Exception Handling
3265 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003266
John McCallbd309292010-07-06 01:34:17 +00003267 A catch buffer is a setjmp buffer plus:
3268 - a pointer to the exception that was caught
3269 - a pointer to the previous exception data buffer
3270 - two pointers of reserved storage
3271 Therefore catch buffers form a stack, with a pointer to the top
3272 of the stack kept in thread-local storage.
3273
3274 objc_exception_try_enter pushes a catch buffer onto the EH stack.
3275 objc_exception_try_exit pops the given catch buffer, which is
3276 required to be the top of the EH stack.
3277 objc_exception_throw pops the top of the EH stack, writes the
3278 thrown exception into the appropriate field, and longjmps
3279 to the setjmp buffer. It crashes the process (with a printf
3280 and an abort()) if there are no catch buffers on the stack.
3281 objc_exception_extract just reads the exception pointer out of the
3282 catch buffer.
3283
3284 There's no reason an implementation couldn't use a light-weight
3285 setjmp here --- something like __builtin_setjmp, but API-compatible
3286 with the heavyweight setjmp. This will be more important if we ever
3287 want to implement correct ObjC/C++ exception interactions for the
3288 fragile ABI.
3289
3290 Note that for this use of setjmp/longjmp to be correct, we may need
3291 to mark some local variables volatile: if a non-volatile local
3292 variable is modified between the setjmp and the longjmp, it has
3293 indeterminate value. For the purposes of LLVM IR, it may be
3294 sufficient to make loads and stores within the @try (to variables
3295 declared outside the @try) volatile. This is necessary for
3296 optimized correctness, but is not currently being done; this is
3297 being tracked as rdar://problem/8160285
3298
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003299 The basic framework for a @try-catch-finally is as follows:
3300 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003301 objc_exception_data d;
3302 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00003303 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003304
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003305 objc_exception_try_enter(&d);
3306 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003307 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003308 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003309 // exception path
3310 id _caught = objc_exception_extract(&d);
3311
3312 // enter new try scope for handlers
3313 if (!setjmp(d.jmp_buf)) {
3314 ... match exception and execute catch blocks ...
3315
3316 // fell off end, rethrow.
3317 _rethrow = _caught;
3318 ... jump-through-finally to finally_rethrow ...
3319 } else {
3320 // exception in catch block
3321 _rethrow = objc_exception_extract(&d);
3322 _call_try_exit = false;
3323 ... jump-through-finally to finally_rethrow ...
3324 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003325 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003326 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003327
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003328 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00003329 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003330 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00003331
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003332 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003333 ... dispatch to finally destination ...
3334
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003335 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003336 objc_exception_throw(_rethrow);
3337
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003338 finally_end:
3339 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003340
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003341 This framework differs slightly from the one gcc uses, in that gcc
3342 uses _rethrow to determine if objc_exception_try_exit should be called
3343 and if the object should be rethrown. This breaks in the face of
3344 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003345
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003346 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003347
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003348 - If there are no catch blocks, then we avoid emitting the second
3349 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003350
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003351 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
3352 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003353
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003354 - FIXME: If there is no @finally block we can do a few more
3355 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003356
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003357 Rethrows and Jumps-Through-Finally
3358 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003359
John McCallbd309292010-07-06 01:34:17 +00003360 '@throw;' is supported by pushing the currently-caught exception
3361 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003362
John McCallbd309292010-07-06 01:34:17 +00003363 Branches through the @finally block are handled with an ordinary
3364 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
3365 exceptions are not compatible with C++ exceptions, and this is
3366 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003367
John McCallbd309292010-07-06 01:34:17 +00003368 @synchronized(expr) { stmt; } is emitted as if it were:
3369 id synch_value = expr;
3370 objc_sync_enter(synch_value);
3371 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003372*/
3373
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00003374void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
3375 const Stmt &S) {
3376 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00003377
3378 // A destination for the fall-through edges of the catch handlers to
3379 // jump to.
3380 CodeGenFunction::JumpDest FinallyEnd =
3381 CGF.getJumpDestInCurrentScope("finally.end");
3382
3383 // A destination for the rethrow edge of the catch handlers to jump
3384 // to.
3385 CodeGenFunction::JumpDest FinallyRethrow =
3386 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003387
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003388 // For @synchronized, call objc_sync_enter(sync.expr). The
3389 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00003390 // @synchronized. We can't avoid a temp here because we need the
3391 // value to be preserved. If the backend ever does liveness
3392 // correctly after setjmp, this will be unnecessary.
3393 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003394 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00003395 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003396 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
3397 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallbd309292010-07-06 01:34:17 +00003398 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
3399 ->setDoesNotThrow();
John McCall2dd7d442010-08-04 05:59:32 +00003400
3401 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
3402 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003403 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003404
John McCall2dd7d442010-08-04 05:59:32 +00003405 // Allocate memory for the setjmp buffer. This needs to be kept
3406 // live throughout the try and catch blocks.
3407 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
3408 "exceptiondata.ptr");
3409
John McCall42227ed2010-07-31 23:20:56 +00003410 // Create the fragile hazards. Note that this will not capture any
3411 // of the allocas required for exception processing, but will
3412 // capture the current basic block (which extends all the way to the
3413 // setjmp call) as "before the @try".
3414 FragileHazards Hazards(CGF);
3415
John McCallbd309292010-07-06 01:34:17 +00003416 // Create a flag indicating whether the cleanup needs to call
3417 // objc_exception_try_exit. This is true except when
3418 // - no catches match and we're branching through the cleanup
3419 // just to rethrow the exception, or
3420 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00003421 // The setjmp-safety rule here is that we should always store to this
3422 // variable in a place that dominates the branch through the cleanup
3423 // without passing through any setjmps.
John McCallbd309292010-07-06 01:34:17 +00003424 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlssonda0e4562009-02-07 21:26:04 +00003425 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003426
John McCall9916e3f2010-10-04 23:42:51 +00003427 // A slot containing the exception to rethrow. Only needed when we
3428 // have both a @catch and a @finally.
3429 llvm::Value *PropagatingExnVar = 0;
3430
John McCallbd309292010-07-06 01:34:17 +00003431 // Push a normal cleanup to leave the try scope.
John McCallcda666c2010-07-21 07:22:38 +00003432 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00003433 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00003434 CallTryExitVar,
3435 ExceptionData,
3436 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00003437
3438 // Enter a try block:
3439 // - Call objc_exception_try_enter to push ExceptionData on top of
3440 // the EH stack.
3441 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3442 ->setDoesNotThrow();
3443
3444 // - Call setjmp on the exception data buffer.
3445 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
3446 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
3447 llvm::Value *SetJmpBuffer =
Jay Foad040dd822011-07-22 08:16:57 +00003448 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
John McCallbd309292010-07-06 01:34:17 +00003449 llvm::CallInst *SetJmpResult =
3450 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
3451 SetJmpResult->setDoesNotThrow();
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003452 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00003453
3454 // If setjmp returned 0, enter the protected block; otherwise,
3455 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00003456 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3457 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00003458 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00003459 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3460 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003461
John McCallbd309292010-07-06 01:34:17 +00003462 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003463 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00003464 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003465 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00003466 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00003467
3468 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003469
John McCallbd309292010-07-06 01:34:17 +00003470 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00003471 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003472
John McCall42227ed2010-07-31 23:20:56 +00003473 // Don't optimize loads of the in-scope locals across this point.
3474 Hazards.emitWriteHazard();
3475
John McCallbd309292010-07-06 01:34:17 +00003476 // For a @synchronized (or a @try with no catches), just branch
3477 // through the cleanup to the rethrow block.
3478 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
3479 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00003480 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003481 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00003482
3483 // Otherwise, we have to match against the caught exceptions.
3484 } else {
John McCall2dd7d442010-08-04 05:59:32 +00003485 // Retrieve the exception object. We may emit multiple blocks but
3486 // nothing can cross this so the value is already in SSA form.
3487 llvm::CallInst *Caught =
3488 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3489 ExceptionData, "caught");
3490 Caught->setDoesNotThrow();
3491
John McCallbd309292010-07-06 01:34:17 +00003492 // Push the exception to rethrow onto the EH value stack for the
3493 // benefit of any @throws in the handlers.
3494 CGF.ObjCEHValueStack.push_back(Caught);
3495
Douglas Gregor96c79492010-04-23 22:50:49 +00003496 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003497
John McCall2dd7d442010-08-04 05:59:32 +00003498 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallbd309292010-07-06 01:34:17 +00003499
John McCall2dd7d442010-08-04 05:59:32 +00003500 llvm::BasicBlock *CatchBlock = 0;
3501 llvm::BasicBlock *CatchHandler = 0;
3502 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00003503 // Save the currently-propagating exception before
3504 // objc_exception_try_enter clears the exception slot.
3505 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
3506 "propagating_exception");
3507 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
3508
John McCall2dd7d442010-08-04 05:59:32 +00003509 // Enter a new exception try block (in case a @catch block
3510 // throws an exception).
3511 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3512 ->setDoesNotThrow();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003513
John McCall2dd7d442010-08-04 05:59:32 +00003514 llvm::CallInst *SetJmpResult =
3515 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3516 "setjmp.result");
3517 SetJmpResult->setDoesNotThrow();
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003518 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003519
John McCall2dd7d442010-08-04 05:59:32 +00003520 llvm::Value *Threw =
3521 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3522
3523 CatchBlock = CGF.createBasicBlock("catch");
3524 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3525 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3526
3527 CGF.EmitBlock(CatchBlock);
3528 }
3529
3530 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003531
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003532 // Handle catch list. As a special case we check if everything is
3533 // matched and avoid generating code for falling off the end if
3534 // so.
3535 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00003536 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3537 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003538
Douglas Gregor46a572b2010-04-26 16:46:50 +00003539 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff7cae42b2009-07-10 23:34:53 +00003540 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar523208f2008-09-27 07:36:24 +00003541
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003542 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003543 if (!CatchParam) {
3544 AllMatched = true;
3545 } else {
John McCall9dd450b2009-09-21 23:43:11 +00003546 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003547
John McCallbd309292010-07-06 01:34:17 +00003548 // catch(id e) always matches under this ABI, since only
3549 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00003550 // FIXME: For the time being we also match id<X>; this should
3551 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00003552 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003553 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003554 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003555
John McCallbd309292010-07-06 01:34:17 +00003556 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003557 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00003558 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3559
Anders Carlsson9396a892008-09-11 09:15:33 +00003560 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00003561 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003562 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00003563
3564 // These types work out because ConvertType(id) == i8*.
Steve Naroff371b8fb2009-03-03 19:52:17 +00003565 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson9396a892008-09-11 09:15:33 +00003566 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003567
Anders Carlsson9396a892008-09-11 09:15:33 +00003568 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003569
3570 // The scope of the catch variable ends right here.
3571 CatchVarCleanups.ForceCleanup();
3572
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003573 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003574 break;
3575 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003576
Steve Naroff7cae42b2009-07-10 23:34:53 +00003577 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00003578 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00003579
3580 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00003581 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3582 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003583
3584 // Check if the @catch block matches the exception object.
John McCall96fa4842010-05-17 21:00:27 +00003585 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003586
John McCallbd309292010-07-06 01:34:17 +00003587 llvm::CallInst *Match =
Chris Lattnerc6406db2009-04-22 02:26:14 +00003588 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3589 Class, Caught, "match");
John McCallbd309292010-07-06 01:34:17 +00003590 Match->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003591
John McCallbd309292010-07-06 01:34:17 +00003592 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3593 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003594
3595 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00003596 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003597
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003598 // Emit the @catch block.
3599 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00003600
3601 // Collect any cleanups for the catch variable. The scope lasts until
3602 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00003603 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00003604
John McCall1c9c3fd2010-10-15 04:57:14 +00003605 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003606 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003607
John McCallbd309292010-07-06 01:34:17 +00003608 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003609 llvm::Value *Tmp =
3610 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00003611 CGF.ConvertType(CatchParam->getType()));
Steve Naroff371b8fb2009-03-03 19:52:17 +00003612 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003613
Anders Carlsson9396a892008-09-11 09:15:33 +00003614 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003615
3616 // We're done with the catch variable.
3617 CatchVarCleanups.ForceCleanup();
3618
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003619 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003620
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003621 CGF.EmitBlock(NextCatchBlock);
3622 }
3623
John McCallbd309292010-07-06 01:34:17 +00003624 CGF.ObjCEHValueStack.pop_back();
3625
John McCall2dd7d442010-08-04 05:59:32 +00003626 // If nothing wanted anything to do with the caught exception,
3627 // kill the extract call.
3628 if (Caught->use_empty())
3629 Caught->eraseFromParent();
3630
3631 if (!AllMatched)
3632 CGF.EmitBranchThroughCleanup(FinallyRethrow);
3633
3634 if (HasFinally) {
3635 // Emit the exception handler for the @catch blocks.
3636 CGF.EmitBlock(CatchHandler);
3637
3638 // In theory we might now need a write hazard, but actually it's
3639 // unnecessary because there's no local-accessing code between
3640 // the try's write hazard and here.
3641 //Hazards.emitWriteHazard();
3642
John McCall9916e3f2010-10-04 23:42:51 +00003643 // Extract the new exception and save it to the
3644 // propagating-exception slot.
3645 assert(PropagatingExnVar);
3646 llvm::CallInst *NewCaught =
3647 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3648 ExceptionData, "caught");
3649 NewCaught->setDoesNotThrow();
3650 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
3651
John McCall2dd7d442010-08-04 05:59:32 +00003652 // Don't pop the catch handler; the throw already did.
3653 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003654 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003655 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003656 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003657
John McCall42227ed2010-07-31 23:20:56 +00003658 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00003659 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003660
John McCallbd309292010-07-06 01:34:17 +00003661 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00003662 CGF.Builder.restoreIP(TryFallthroughIP);
3663 if (CGF.HaveInsertPoint())
3664 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00003665 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00003666 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003667
John McCallbd309292010-07-06 01:34:17 +00003668 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00003669 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00003670 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00003671 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00003672 // If we have a propagating-exception variable, check it.
3673 llvm::Value *PropagatingExn;
3674 if (PropagatingExnVar) {
3675 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00003676
John McCall9916e3f2010-10-04 23:42:51 +00003677 // Otherwise, just look in the buffer for the exception to throw.
3678 } else {
3679 llvm::CallInst *Caught =
3680 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3681 ExceptionData);
3682 Caught->setDoesNotThrow();
3683 PropagatingExn = Caught;
3684 }
3685
3686 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
John McCallbd309292010-07-06 01:34:17 +00003687 ->setDoesNotThrow();
3688 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00003689 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003690
John McCall42227ed2010-07-31 23:20:56 +00003691 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003692}
3693
3694void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003695 const ObjCAtThrowStmt &S) {
Anders Carlssone005aa12008-09-09 16:16:55 +00003696 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003697
Anders Carlssone005aa12008-09-09 16:16:55 +00003698 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00003699 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003700 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00003701 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00003702 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003703 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003704 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00003705 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00003706 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003707
John McCallbd309292010-07-06 01:34:17 +00003708 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3709 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003710 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003711
3712 // Clear the insertion point to indicate we are in unreachable code.
3713 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003714}
3715
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003716/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003717/// object: objc_read_weak (id *src)
3718///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003719llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003720 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003721 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003722 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3723 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3724 ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00003725 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003726 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00003727 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003728 return read_weak;
3729}
3730
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003731/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
3732/// objc_assign_weak (id src, id *dst)
3733///
3734void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003735 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003736 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003737 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00003738 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003739 assert(Size <= 8 && "does not support size > 8");
3740 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003741 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003742 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3743 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003744 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3745 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00003746 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003747 src, dst, "weakassign");
3748 return;
3749}
3750
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003751/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
3752/// objc_assign_global (id src, id *dst)
3753///
3754void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00003755 llvm::Value *src, llvm::Value *dst,
3756 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003757 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003758 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00003759 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003760 assert(Size <= 8 && "does not support size > 8");
3761 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003762 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003763 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3764 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003765 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3766 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00003767 if (!threadlocal)
3768 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
3769 src, dst, "globalassign");
3770 else
3771 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
3772 src, dst, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003773 return;
3774}
3775
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003776/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003777/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003778///
3779void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003780 llvm::Value *src, llvm::Value *dst,
3781 llvm::Value *ivarOffset) {
3782 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00003783 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003784 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00003785 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003786 assert(Size <= 8 && "does not support size > 8");
3787 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003788 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003789 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3790 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003791 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3792 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003793 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3794 src, dst, ivarOffset);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003795 return;
3796}
3797
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003798/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
3799/// objc_assign_strongCast (id src, id *dst)
3800///
3801void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003802 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003803 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003804 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00003805 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003806 assert(Size <= 8 && "does not support size > 8");
3807 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003808 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003809 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3810 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003811 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3812 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00003813 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003814 src, dst, "weakassign");
3815 return;
3816}
3817
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003818void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003819 llvm::Value *DestPtr,
3820 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003821 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003822 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3823 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003824 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003825 DestPtr, SrcPtr, size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003826 return;
3827}
3828
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003829/// EmitObjCValueForIvar - Code Gen for ivar reference.
3830///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003831LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3832 QualType ObjectTy,
3833 llvm::Value *BaseValue,
3834 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003835 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00003836 const ObjCInterfaceDecl *ID =
3837 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003838 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3839 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003840}
3841
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003842llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00003843 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003844 const ObjCIvarDecl *Ivar) {
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003845 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003846 return llvm::ConstantInt::get(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003847 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3848 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003849}
3850
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003851/* *** Private Interface *** */
3852
3853/// EmitImageInfo - Emit the image info marker used to encode some module
3854/// level information.
3855///
3856/// See: <rdr://4810609&4810587&4810587>
3857/// struct IMAGE_INFO {
3858/// unsigned version;
3859/// unsigned flags;
3860/// };
3861enum ImageInfoFlags {
Daniel Dunbar5e639272010-04-25 20:39:01 +00003862 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003863 eImageInfo_GarbageCollected = (1 << 1),
3864 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003865 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
3866
Daniel Dunbar5e639272010-04-25 20:39:01 +00003867 // A flag indicating that the module has no instances of a @synthesize of a
3868 // superclass variable. <rdar://problem/6803242>
Bill Wendling1e60a2c2012-04-24 11:04:57 +00003869 eImageInfo_CorrectedSynthesize = (1 << 4),
3870 eImageInfo_ImageIsSimulated = (1 << 5)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003871};
3872
Daniel Dunbar5e639272010-04-25 20:39:01 +00003873void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003874 unsigned version = 0; // Version is unused?
Bill Wendlingb6f795e2012-02-16 01:13:30 +00003875 const char *Section = (ObjCABI == 1) ?
3876 "__OBJC, __image_info,regular" :
3877 "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003878
Bill Wendlingb6f795e2012-02-16 01:13:30 +00003879 // Generate module-level named metadata to convey this information to the
3880 // linker and code-gen.
3881 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003882
Bill Wendlingb6f795e2012-02-16 01:13:30 +00003883 // Add the ObjC ABI version to the module flags.
3884 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
3885 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
3886 version);
3887 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
3888 llvm::MDString::get(VMContext,Section));
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003889
David Blaikiebbafb8a2012-03-11 07:00:24 +00003890 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00003891 // Non-GC overrides those files which specify GC.
3892 Mod.addModuleFlag(llvm::Module::Override,
3893 "Objective-C Garbage Collection", (uint32_t)0);
3894 } else {
3895 // Add the ObjC garbage collection value.
3896 Mod.addModuleFlag(llvm::Module::Error,
3897 "Objective-C Garbage Collection",
3898 eImageInfo_GarbageCollected);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003899
David Blaikiebbafb8a2012-03-11 07:00:24 +00003900 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00003901 // Add the ObjC GC Only value.
3902 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
3903 eImageInfo_GCOnly);
3904
3905 // Require that GC be specified and set to eImageInfo_GarbageCollected.
3906 llvm::Value *Ops[2] = {
3907 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
3908 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
3909 eImageInfo_GarbageCollected)
3910 };
3911 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
3912 llvm::MDNode::get(VMContext, Ops));
3913 }
3914 }
Bill Wendling1e60a2c2012-04-24 11:04:57 +00003915
3916 // Indicate whether we're compiling this to run on a simulator.
3917 const llvm::Triple &Triple = CGM.getTarget().getTriple();
3918 if (Triple.getOS() == llvm::Triple::IOS &&
3919 (Triple.getArch() == llvm::Triple::x86 ||
3920 Triple.getArch() == llvm::Triple::x86_64))
3921 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
3922 eImageInfo_ImageIsSimulated);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003923}
3924
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003925// struct objc_module {
3926// unsigned long version;
3927// unsigned long size;
3928// const char *name;
3929// Symtab symtab;
3930// };
3931
3932// FIXME: Get from somewhere
3933static const int ModuleVersion = 7;
3934
3935void CGObjCMac::EmitModuleInfo() {
Micah Villmowdd31ca12012-10-08 16:25:52 +00003936 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003937
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003938 llvm::Constant *Values[] = {
3939 llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion),
3940 llvm::ConstantInt::get(ObjCTypes.LongTy, Size),
3941 // This used to be the filename, now it is unused. <rdr://4327263>
3942 GetClassName(&CGM.getContext().Idents.get("")),
3943 EmitModuleSymbols()
3944 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003945 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson0e0189d2009-07-27 22:29:56 +00003946 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003947 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00003948 4, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003949}
3950
3951llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003952 unsigned NumClasses = DefinedClasses.size();
3953 unsigned NumCategories = DefinedCategories.size();
3954
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003955 // Return null if no symbols were defined.
3956 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00003957 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003958
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003959 llvm::Constant *Values[5];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003960 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Anderson0b75f232009-07-31 20:28:54 +00003961 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003962 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3963 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003964
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003965 // The runtime expects exactly the list of defined classes followed
3966 // by the list of defined categories, in a single array.
Chris Lattner3def9ae2012-02-06 22:16:34 +00003967 SmallVector<llvm::Constant*, 8> Symbols(NumClasses + NumCategories);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003968 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00003969 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003970 ObjCTypes.Int8PtrTy);
3971 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003972 Symbols[NumClasses + i] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003973 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003974 ObjCTypes.Int8PtrTy);
3975
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003976 Values[4] =
Owen Anderson9793f0e2009-07-29 22:16:19 +00003977 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00003978 Symbols.size()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003979 Symbols);
3980
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003981 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003982
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003983 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003984 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3985 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003986 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003987 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003988}
3989
John McCall31168b02011-06-15 23:02:42 +00003990llvm::Value *CGObjCMac::EmitClassRefFromId(CGBuilderTy &Builder,
3991 IdentifierInfo *II) {
3992 LazySymbols.insert(II);
3993
3994 llvm::GlobalVariable *&Entry = ClassReferences[II];
3995
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003996 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003997 llvm::Constant *Casted =
John McCall31168b02011-06-15 23:02:42 +00003998 llvm::ConstantExpr::getBitCast(GetClassName(II),
3999 ObjCTypes.ClassPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004000 Entry =
John McCall31168b02011-06-15 23:02:42 +00004001 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
4002 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
4003 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004004 }
John McCall31168b02011-06-15 23:02:42 +00004005
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004006 return Builder.CreateLoad(Entry);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004007}
4008
John McCall31168b02011-06-15 23:02:42 +00004009llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
4010 const ObjCInterfaceDecl *ID) {
4011 return EmitClassRefFromId(Builder, ID->getIdentifier());
4012}
4013
4014llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder) {
4015 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
4016 return EmitClassRefFromId(Builder, II);
4017}
4018
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00004019llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
4020 bool lvalue) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004021 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004022
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004023 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004024 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00004025 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004026 ObjCTypes.SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004027 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004028 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
4029 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00004030 4, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004031 }
4032
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00004033 if (lvalue)
4034 return Entry;
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004035 return Builder.CreateLoad(Entry);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004036}
4037
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004038llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00004039 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004040
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004041 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004042 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004043 llvm::ConstantDataArray::getString(VMContext,
4044 Ident->getNameStart()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004045 ((ObjCABI == 2) ?
4046 "__TEXT,__objc_classname,cstring_literals" :
4047 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004048 1, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004049
Owen Anderson170229f2009-07-14 23:10:40 +00004050 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004051}
4052
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004053llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
4054 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
4055 I = MethodDefinitions.find(MD);
4056 if (I != MethodDefinitions.end())
4057 return I->second;
4058
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004059 return NULL;
4060}
4061
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004062/// GetIvarLayoutName - Returns a unique constant for the given
4063/// ivar layout bitmap.
4064llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004065 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00004066 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004067}
4068
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004069void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004070 unsigned int BytePos,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004071 bool ForStrongLayout,
4072 bool &HasUnion) {
4073 const RecordDecl *RD = RT->getDecl();
4074 // FIXME - Use iterator.
David Blaikie2d7c57e2012-04-30 02:36:29 +00004075 SmallVector<const FieldDecl*, 16> Fields;
4076 for (RecordDecl::field_iterator i = RD->field_begin(),
4077 e = RD->field_end(); i != e; ++i)
David Blaikie40ed2972012-06-06 20:45:41 +00004078 Fields.push_back(*i);
Chris Lattner2192fe52011-07-18 04:24:23 +00004079 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004080 const llvm::StructLayout *RecLayout =
Micah Villmowdd31ca12012-10-08 16:25:52 +00004081 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004082
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004083 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
4084 ForStrongLayout, HasUnion);
4085}
4086
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +00004087void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004088 const llvm::StructLayout *Layout,
4089 const RecordDecl *RD,
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00004090 ArrayRef<const FieldDecl*> RecFields,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004091 unsigned int BytePos, bool ForStrongLayout,
4092 bool &HasUnion) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004093 bool IsUnion = (RD && RD->isUnion());
4094 uint64_t MaxUnionIvarSize = 0;
4095 uint64_t MaxSkippedUnionIvarSize = 0;
Jordy Rosea91768e2011-07-22 02:08:32 +00004096 const FieldDecl *MaxField = 0;
4097 const FieldDecl *MaxSkippedField = 0;
4098 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Daniel Dunbar5b743912009-05-03 23:31:46 +00004099 uint64_t MaxFieldOffset = 0;
4100 uint64_t MaxSkippedFieldOffset = 0;
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004101 uint64_t LastBitfieldOrUnnamedOffset = 0;
John McCall31168b02011-06-15 23:02:42 +00004102 uint64_t FirstFieldDelta = 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004103
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004104 if (RecFields.empty())
4105 return;
Douglas Gregore8bbc122011-09-02 00:18:52 +00004106 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
4107 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
David Blaikiebbafb8a2012-03-11 07:00:24 +00004108 if (!RD && CGM.getLangOpts().ObjCAutoRefCount) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004109 const FieldDecl *FirstField = RecFields[0];
John McCall31168b02011-06-15 23:02:42 +00004110 FirstFieldDelta =
4111 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
4112 }
4113
Chris Lattner5b36ddb2009-03-31 08:48:01 +00004114 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004115 const FieldDecl *Field = RecFields[i];
Daniel Dunbar62b10702009-05-03 23:35:23 +00004116 uint64_t FieldOffset;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00004117 if (RD) {
Daniel Dunbard51c1a62010-04-14 17:02:21 +00004118 // Note that 'i' here is actually the field index inside RD of Field,
4119 // although this dependency is hidden.
4120 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
John McCall31168b02011-06-15 23:02:42 +00004121 FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00004122 } else
John McCall31168b02011-06-15 23:02:42 +00004123 FieldOffset =
4124 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004125
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004126 // Skip over unnamed or bitfields
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004127 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004128 LastFieldBitfieldOrUnnamed = Field;
4129 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004130 continue;
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004131 }
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004132
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004133 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004134 QualType FQT = Field->getType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004135 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004136 if (FQT->isUnionType())
4137 HasUnion = true;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004138
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004139 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004140 BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004141 ForStrongLayout, HasUnion);
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004142 continue;
4143 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004144
Chris Lattner5b36ddb2009-03-31 08:48:01 +00004145 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004146 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004147 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004148 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004149 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004150 FQT = CArray->getElementType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004151 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
4152 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004153 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004154 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004155 FQT = CArray->getElementType();
4156 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004157
4158 assert(!FQT->isUnionType() &&
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004159 "layout for array of unions not supported");
Fariborz Jahanian9a7d57d2011-01-03 19:23:18 +00004160 if (FQT->isRecordType() && ElCount) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004161 int OldIndex = IvarsInfo.size() - 1;
4162 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004163
Ted Kremenekc23c7e62009-07-29 21:53:49 +00004164 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004165 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004166 ForStrongLayout, HasUnion);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004167
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004168 // Replicate layout information for each array element. Note that
4169 // one element is already done.
4170 uint64_t ElIx = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004171 for (int FirstIndex = IvarsInfo.size() - 1,
4172 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004173 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004174 for (int i = OldIndex+1; i <= FirstIndex; ++i)
4175 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
4176 IvarsInfo[i].ivar_size));
4177 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
4178 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
4179 SkipIvars[i].ivar_size));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004180 }
4181 continue;
4182 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004183 }
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004184 // At this point, we are done with Record/Union and array there of.
4185 // For other arrays we are down to its element type.
John McCall8ccfcb52009-09-24 19:53:00 +00004186 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004187
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004188 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall8ccfcb52009-09-24 19:53:00 +00004189 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
4190 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00004191 if (IsUnion) {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004192 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00004193 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004194 MaxUnionIvarSize = UnionIvarSize;
4195 MaxField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00004196 MaxFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004197 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00004198 } else {
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004199 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004200 FieldSize / WordSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004201 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004202 } else if ((ForStrongLayout &&
John McCall8ccfcb52009-09-24 19:53:00 +00004203 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
4204 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00004205 if (IsUnion) {
Mike Stump18bb9282009-05-16 07:57:57 +00004206 // FIXME: Why the asymmetry? We divide by word size in bits on other
4207 // side.
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004208 uint64_t UnionIvarSize = FieldSize;
Daniel Dunbar22007d32009-05-03 13:32:01 +00004209 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004210 MaxSkippedUnionIvarSize = UnionIvarSize;
4211 MaxSkippedField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00004212 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004213 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00004214 } else {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004215 // FIXME: Why the asymmetry, we divide by byte size in bits here?
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004216 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004217 FieldSize / ByteSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004218 }
4219 }
4220 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004221
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004222 if (LastFieldBitfieldOrUnnamed) {
4223 if (LastFieldBitfieldOrUnnamed->isBitField()) {
4224 // Last field was a bitfield. Must update skip info.
Richard Smithcaf33902011-10-10 18:28:20 +00004225 uint64_t BitFieldSize
4226 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004227 GC_IVAR skivar;
4228 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
4229 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
4230 + ((BitFieldSize % ByteSizeInBits) != 0);
4231 SkipIvars.push_back(skivar);
4232 } else {
4233 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
4234 // Last field was unnamed. Must update skip info.
4235 unsigned FieldSize
4236 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
4237 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
4238 FieldSize / ByteSizeInBits));
4239 }
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004240 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004241
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004242 if (MaxField)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004243 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004244 MaxUnionIvarSize));
4245 if (MaxSkippedField)
Daniel Dunbar5b743912009-05-03 23:31:46 +00004246 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004247 MaxSkippedUnionIvarSize));
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004248}
4249
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004250/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
4251/// the computations and returning the layout bitmap (for ivar or blocks) in
4252/// the given argument BitMap string container. Routine reads
4253/// two containers, IvarsInfo and SkipIvars which are assumed to be
4254/// filled already by the caller.
Chris Lattner9c818332012-02-05 02:30:40 +00004255llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004256 unsigned int WordsToScan, WordsToSkip;
Chris Lattnerece04092012-02-07 00:39:47 +00004257 llvm::Type *PtrTy = CGM.Int8PtrTy;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004258
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004259 // Build the string of skip/scan nibbles
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004260 SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004261 unsigned int WordSize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00004262 CGM.getTypes().getDataLayout().getTypeAllocSize(PtrTy);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004263 if (IvarsInfo[0].ivar_bytepos == 0) {
4264 WordsToSkip = 0;
4265 WordsToScan = IvarsInfo[0].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004266 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004267 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
4268 WordsToScan = IvarsInfo[0].ivar_size;
4269 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004270 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004271 unsigned int TailPrevGCObjC =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004272 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004273 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004274 // consecutive 'scanned' object pointers.
4275 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004276 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004277 // Skip over 'gc'able object pointer which lay over each other.
4278 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
4279 continue;
4280 // Must skip over 1 or more words. We save current skip/scan values
4281 // and start a new pair.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004282 SKIP_SCAN SkScan;
4283 SkScan.skip = WordsToSkip;
4284 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004285 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004286
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004287 // Skip the hole.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004288 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
4289 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004290 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004291 WordsToSkip = 0;
4292 WordsToScan = IvarsInfo[i].ivar_size;
4293 }
4294 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004295 if (WordsToScan > 0) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004296 SKIP_SCAN SkScan;
4297 SkScan.skip = WordsToSkip;
4298 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004299 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004300 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004301
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004302 if (!SkipIvars.empty()) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004303 unsigned int LastIndex = SkipIvars.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004304 int LastByteSkipped =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004305 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004306 LastIndex = IvarsInfo.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004307 int LastByteScanned =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004308 IvarsInfo[LastIndex].ivar_bytepos +
4309 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004310 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramerd20ef752009-12-25 15:43:36 +00004311 if (LastByteSkipped > LastByteScanned) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004312 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004313 SKIP_SCAN SkScan;
4314 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
4315 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004316 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004317 }
4318 }
4319 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
4320 // as 0xMN.
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004321 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004322 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004323 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
4324 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
4325 // 0xM0 followed by 0x0N detected.
4326 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
4327 for (int j = i+1; j < SkipScan; j++)
4328 SkipScanIvars[j] = SkipScanIvars[j+1];
4329 --SkipScan;
4330 }
4331 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004332
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004333 // Generate the string.
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004334 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004335 unsigned char byte;
4336 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
4337 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
4338 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
4339 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004340
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004341 // first skip big.
4342 for (unsigned int ix = 0; ix < skip_big; ix++)
4343 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004344
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004345 // next (skip small, scan)
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004346 if (skip_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004347 byte = skip_small << 4;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004348 if (scan_big > 0) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004349 byte |= 0xf;
4350 --scan_big;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004351 } else if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004352 byte |= scan_small;
4353 scan_small = 0;
4354 }
4355 BitMap += byte;
4356 }
4357 // next scan big
4358 for (unsigned int ix = 0; ix < scan_big; ix++)
4359 BitMap += (unsigned char)(0x0f);
4360 // last scan small
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004361 if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004362 byte = scan_small;
4363 BitMap += byte;
4364 }
4365 }
4366 // null terminate string.
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004367 unsigned char zero = 0;
4368 BitMap += zero;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004369
4370 llvm::GlobalVariable * Entry =
4371 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004372 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004373 ((ObjCABI == 2) ?
4374 "__TEXT,__objc_classname,cstring_literals" :
4375 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004376 1, true);
4377 return getConstantGEP(VMContext, Entry, 0, 0);
4378}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004379
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004380/// BuildIvarLayout - Builds ivar layout bitmap for the class
4381/// implementation for the __strong or __weak case.
4382/// The layout map displays which words in ivar list must be skipped
4383/// and which must be scanned by GC (see below). String is built of bytes.
4384/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
4385/// of words to skip and right nibble is count of words to scan. So, each
4386/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
4387/// represented by a 0x00 byte which also ends the string.
4388/// 1. when ForStrongLayout is true, following ivars are scanned:
4389/// - id, Class
4390/// - object *
4391/// - __strong anything
4392///
4393/// 2. When ForStrongLayout is false, following ivars are scanned:
4394/// - __weak anything
4395///
4396llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
4397 const ObjCImplementationDecl *OMD,
4398 bool ForStrongLayout) {
4399 bool hasUnion = false;
4400
Chris Lattnerece04092012-02-07 00:39:47 +00004401 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikiebbafb8a2012-03-11 07:00:24 +00004402 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
4403 !CGM.getLangOpts().ObjCAutoRefCount)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004404 return llvm::Constant::getNullValue(PtrTy);
4405
Jordy Rosea91768e2011-07-22 02:08:32 +00004406 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
4407 SmallVector<const FieldDecl*, 32> RecFields;
David Blaikiebbafb8a2012-03-11 07:00:24 +00004408 if (CGM.getLangOpts().ObjCAutoRefCount) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004409 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004410 IVD; IVD = IVD->getNextIvar())
4411 RecFields.push_back(cast<FieldDecl>(IVD));
4412 }
4413 else {
Jordy Rosea91768e2011-07-22 02:08:32 +00004414 SmallVector<const ObjCIvarDecl*, 32> Ivars;
John McCall31168b02011-06-15 23:02:42 +00004415 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004416
Jordy Rosea91768e2011-07-22 02:08:32 +00004417 // FIXME: This is not ideal; we shouldn't have to do this copy.
4418 RecFields.append(Ivars.begin(), Ivars.end());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004419 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004420
4421 if (RecFields.empty())
4422 return llvm::Constant::getNullValue(PtrTy);
4423
4424 SkipIvars.clear();
4425 IvarsInfo.clear();
4426
4427 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
4428 if (IvarsInfo.empty())
4429 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004430 // Sort on byte position in case we encounterred a union nested in
4431 // the ivar list.
4432 if (hasUnion && !IvarsInfo.empty())
4433 std::sort(IvarsInfo.begin(), IvarsInfo.end());
4434 if (hasUnion && !SkipIvars.empty())
4435 std::sort(SkipIvars.begin(), SkipIvars.end());
4436
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004437 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004438 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004439
David Blaikiebbafb8a2012-03-11 07:00:24 +00004440 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004441 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004442 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar56df9772010-08-17 22:39:59 +00004443 OMD->getClassInterface()->getName().data());
Roman Divackye6377112012-09-06 15:59:27 +00004444 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling53136852012-02-07 09:06:01 +00004445 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004446 if (!(s[i] & 0xf0))
4447 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
4448 else
4449 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
4450 printf("\n");
4451 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004452 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004453}
4454
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004455llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004456 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
4457
Chris Lattner3def9ae2012-02-06 22:16:34 +00004458 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004459 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004460 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004461 llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004462 ((ObjCABI == 2) ?
4463 "__TEXT,__objc_methname,cstring_literals" :
4464 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004465 1, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004466
Owen Anderson170229f2009-07-14 23:10:40 +00004467 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004468}
4469
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004470// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004471llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004472 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
4473}
4474
Daniel Dunbarf5c18462009-04-20 06:54:31 +00004475llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004476 std::string TypeStr;
4477 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
4478
4479 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarb036db82008-08-13 03:21:16 +00004480
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004481 if (!Entry)
4482 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004483 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004484 ((ObjCABI == 2) ?
4485 "__TEXT,__objc_methtype,cstring_literals" :
4486 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004487 1, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004488
Owen Anderson170229f2009-07-14 23:10:40 +00004489 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004490}
4491
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004492llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
4493 bool Extended) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004494 std::string TypeStr;
Bill Wendlinge22bef72012-02-09 22:45:21 +00004495 if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended))
Douglas Gregora9d84932011-05-27 01:19:52 +00004496 return 0;
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004497
4498 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4499
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004500 if (!Entry)
4501 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004502 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004503 ((ObjCABI == 2) ?
4504 "__TEXT,__objc_methtype,cstring_literals" :
4505 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004506 1, true);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004507
Owen Anderson170229f2009-07-14 23:10:40 +00004508 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004509}
4510
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004511// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004512llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004513 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004514
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004515 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004516 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Chris Lattner9c818332012-02-05 02:30:40 +00004517 llvm::ConstantDataArray::getString(VMContext,
4518 Ident->getNameStart()),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004519 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004520 1, true);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004521
Owen Anderson170229f2009-07-14 23:10:40 +00004522 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004523}
4524
4525// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00004526// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004527llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004528CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4529 const Decl *Container) {
Daniel Dunbar4932b362008-08-28 04:38:10 +00004530 std::string TypeStr;
4531 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004532 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4533}
4534
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004535void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004536 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004537 SmallVectorImpl<char> &Name) {
Daniel Dunbard2386812009-10-19 01:21:19 +00004538 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00004539 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00004540 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4541 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004542 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00004543 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer2f569922012-02-07 11:57:45 +00004544 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00004545 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004546}
4547
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004548void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004549 EmitModuleInfo();
4550
Daniel Dunbarc475d422008-10-29 22:36:39 +00004551 // Emit the dummy bodies for any protocols which were referenced but
4552 // never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004553 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerf56501c2009-07-17 23:57:13 +00004554 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4555 if (I->second->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00004556 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004557
Benjamin Kramer22d24c22011-10-15 12:20:02 +00004558 llvm::Constant *Values[5];
Owen Anderson0b75f232009-07-31 20:28:54 +00004559 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004560 Values[1] = GetClassName(I->first);
Owen Anderson0b75f232009-07-31 20:28:54 +00004561 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004562 Values[3] = Values[4] =
Owen Anderson0b75f232009-07-31 20:28:54 +00004563 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004564 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004565 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarc475d422008-10-29 22:36:39 +00004566 Values));
Chris Lattnerf56501c2009-07-17 23:57:13 +00004567 CGM.AddUsedGlobal(I->second);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004568 }
4569
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004570 // Add assembler directives to add lazy undefined symbol references
4571 // for classes which are referenced but not defined. This is
4572 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00004573 //
4574 // FIXME: It would be nice if we had an LLVM construct for this.
4575 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00004576 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00004577 Asm += CGM.getModule().getModuleInlineAsm();
4578 if (!Asm.empty() && Asm.back() != '\n')
4579 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004580
Daniel Dunbard027a922009-09-07 00:20:42 +00004581 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbard027a922009-09-07 00:20:42 +00004582 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4583 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar07d07852009-10-18 21:17:35 +00004584 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4585 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnera299f2c2010-04-17 18:26:20 +00004586 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004587 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnera299f2c2010-04-17 18:26:20 +00004588 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004589 }
4590
Bill Wendling53136852012-02-07 09:06:01 +00004591 for (size_t i = 0, e = DefinedCategoryNames.size(); i < e; ++i) {
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004592 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4593 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4594 }
Chris Lattnera299f2c2010-04-17 18:26:20 +00004595
Daniel Dunbard027a922009-09-07 00:20:42 +00004596 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004597 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004598}
4599
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004600CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004601 : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00004602 ObjCTypes(cgm) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004603 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004604 ObjCABI = 2;
4605}
4606
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004607/* *** */
4608
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004609ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00004610 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(0)
4611{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004612 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4613 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004614
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004615 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004616 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004617 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004618 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Chris Lattnerece04092012-02-07 00:39:47 +00004619 Int8PtrTy = CGM.Int8PtrTy;
4620 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004621
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004622 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004623 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004624 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004625
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004626 // I'm not sure I like this. The implicit coordination is a bit
4627 // gross. We should solve this in a reasonable fashion because this
4628 // is a pretty common task (match some runtime data structure with
4629 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004630
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004631 // FIXME: This is leaked.
4632 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004633
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004634 // struct _objc_super {
4635 // id self;
4636 // Class cls;
4637 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00004638 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00004639 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00004640 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004641 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004642 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00004643 Ctx.getObjCIdType(), 0, 0, false, ICIS_NoInit));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004644 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00004645 Ctx.getObjCClassType(), 0, 0, false,
4646 ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00004647 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004648
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004649 SuperCTy = Ctx.getTagDeclType(RD);
4650 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004651
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004652 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004653 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4654
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004655 // struct _prop_t {
4656 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004657 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004658 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00004659 PropertyTy = llvm::StructType::create("struct._prop_t",
4660 Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004661
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004662 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004663 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004664 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004665 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004666 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004667 PropertyListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004668 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
4669 llvm::ArrayType::get(PropertyTy, 0), NULL);
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004670 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004671 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004672
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004673 // struct _objc_method {
4674 // SEL _cmd;
4675 // char *method_type;
4676 // char *_imp;
4677 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00004678 MethodTy = llvm::StructType::create("struct._objc_method",
4679 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
4680 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004681
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004682 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00004683 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00004684 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00004685
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004686}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004687
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004688ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004689 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004690 // struct _objc_method_description {
4691 // SEL name;
4692 // char *types;
4693 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004694 MethodDescriptionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004695 llvm::StructType::create("struct._objc_method_description",
4696 SelectorPtrTy, Int8PtrTy, NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004697
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004698 // struct _objc_method_description_list {
4699 // int count;
4700 // struct _objc_method_description[1];
4701 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004702 MethodDescriptionListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004703 llvm::StructType::create("struct._objc_method_description_list",
4704 IntTy,
4705 llvm::ArrayType::get(MethodDescriptionTy, 0),NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004706
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004707 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004708 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004709 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004710
Daniel Dunbarb036db82008-08-13 03:21:16 +00004711 // Protocol description structures
4712
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004713 // struct _objc_protocol_extension {
4714 // uint32_t size; // sizeof(struct _objc_protocol_extension)
4715 // struct _objc_method_description_list *optional_instance_methods;
4716 // struct _objc_method_description_list *optional_class_methods;
4717 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004718 // const char ** extendedMethodTypes;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004719 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004720 ProtocolExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004721 llvm::StructType::create("struct._objc_protocol_extension",
4722 IntTy, MethodDescriptionListPtrTy,
4723 MethodDescriptionListPtrTy, PropertyListPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004724 Int8PtrPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004725
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004726 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004727 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004728
Daniel Dunbarc475d422008-10-29 22:36:39 +00004729 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00004730
Chris Lattnera5f58b02011-07-09 17:41:47 +00004731 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004732 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00004733
Chris Lattnera5f58b02011-07-09 17:41:47 +00004734 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004735 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattnera5f58b02011-07-09 17:41:47 +00004736 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004737 LongTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00004738 llvm::ArrayType::get(ProtocolTy, 0),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004739 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004740
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004741 // struct _objc_protocol {
4742 // struct _objc_protocol_extension *isa;
4743 // char *protocol_name;
4744 // struct _objc_protocol **_objc_protocol_list;
4745 // struct _objc_method_description_list *instance_methods;
4746 // struct _objc_method_description_list *class_methods;
4747 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004748 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
4749 llvm::PointerType::getUnqual(ProtocolListTy),
4750 MethodDescriptionListPtrTy,
4751 MethodDescriptionListPtrTy,
4752 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004753
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004754 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004755 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004756
Owen Anderson9793f0e2009-07-29 22:16:19 +00004757 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004758
4759 // Class description structures
4760
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004761 // struct _objc_ivar {
4762 // char *ivar_name;
4763 // char *ivar_type;
4764 // int ivar_offset;
4765 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00004766 IvarTy = llvm::StructType::create("struct._objc_ivar",
4767 Int8PtrTy, Int8PtrTy, IntTy, NULL);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004768
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004769 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00004770 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004771 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00004772 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004773
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004774 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00004775 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004776 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00004777 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004778
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004779 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004780 ClassExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004781 llvm::StructType::create("struct._objc_class_extension",
4782 IntTy, Int8PtrTy, PropertyListPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004783 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004784
Chris Lattner5ec04a52011-08-12 17:43:31 +00004785 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004786
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004787 // struct _objc_class {
4788 // Class isa;
4789 // Class super_class;
4790 // char *name;
4791 // long version;
4792 // long info;
4793 // long instance_size;
4794 // struct _objc_ivar_list *ivars;
4795 // struct _objc_method_list *methods;
4796 // struct _objc_cache *cache;
4797 // struct _objc_protocol_list *protocols;
4798 // char *ivar_layout;
4799 // struct _objc_class_ext *ext;
4800 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00004801 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
4802 llvm::PointerType::getUnqual(ClassTy),
4803 Int8PtrTy,
4804 LongTy,
4805 LongTy,
4806 LongTy,
4807 IvarListPtrTy,
4808 MethodListPtrTy,
4809 CachePtrTy,
4810 ProtocolListPtrTy,
4811 Int8PtrTy,
4812 ClassExtensionPtrTy,
4813 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004814
Owen Anderson9793f0e2009-07-29 22:16:19 +00004815 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004816
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004817 // struct _objc_category {
4818 // char *category_name;
4819 // char *class_name;
4820 // struct _objc_method_list *instance_method;
4821 // struct _objc_method_list *class_method;
4822 // uint32_t size; // sizeof(struct _objc_category)
4823 // struct _objc_property_list *instance_properties;// category's @property
4824 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004825 CategoryTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004826 llvm::StructType::create("struct._objc_category",
4827 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
4828 MethodListPtrTy, ProtocolListPtrTy,
4829 IntTy, PropertyListPtrTy, NULL);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004830
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004831 // Global metadata structures
4832
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004833 // struct _objc_symtab {
4834 // long sel_ref_cnt;
4835 // SEL *refs;
4836 // short cls_def_cnt;
4837 // short cat_def_cnt;
4838 // char *defs[cls_def_cnt + cat_def_cnt];
4839 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004840 SymtabTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004841 llvm::StructType::create("struct._objc_symtab",
4842 LongTy, SelectorPtrTy, ShortTy, ShortTy,
4843 llvm::ArrayType::get(Int8PtrTy, 0), NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004844 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004845
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00004846 // struct _objc_module {
4847 // long version;
4848 // long size; // sizeof(struct _objc_module)
4849 // char *name;
4850 // struct _objc_symtab* symtab;
4851 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004852 ModuleTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004853 llvm::StructType::create("struct._objc_module",
4854 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, NULL);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00004855
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004856
Mike Stump18bb9282009-05-16 07:57:57 +00004857 // FIXME: This is the size of the setjmp buffer and should be target
4858 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00004859 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004860
Anders Carlsson9ff22482008-09-09 10:10:21 +00004861 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00004862 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004863
4864 ExceptionDataTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004865 llvm::StructType::create("struct._objc_exception_data",
Chris Lattnerece04092012-02-07 00:39:47 +00004866 llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
4867 StackPtrTy, NULL);
Anders Carlsson9ff22482008-09-09 10:10:21 +00004868
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00004869}
4870
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004871ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004872 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004873 // struct _method_list_t {
4874 // uint32_t entsize; // sizeof(struct _objc_method)
4875 // uint32_t method_count;
4876 // struct _objc_method method_list[method_count];
4877 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004878 MethodListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004879 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
4880 llvm::ArrayType::get(MethodTy, 0), NULL);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004881 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004882 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004883
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004884 // struct _protocol_t {
4885 // id isa; // NULL
4886 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004887 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004888 // const struct method_list_t * const instance_methods;
4889 // const struct method_list_t * const class_methods;
4890 // const struct method_list_t *optionalInstanceMethods;
4891 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004892 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004893 // const uint32_t size; // sizeof(struct _protocol_t)
4894 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004895 // const char ** extendedMethodTypes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004896 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004897
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004898 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00004899 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004900 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004901
Chris Lattnera5f58b02011-07-09 17:41:47 +00004902 ProtocolnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004903 llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
4904 llvm::PointerType::getUnqual(ProtocolListnfABITy),
4905 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
4906 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004907 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
4908 NULL);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004909
4910 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004911 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004912
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004913 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004914 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004915 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004916 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004917 ProtocolListnfABITy->setBody(LongTy,
4918 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
4919 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004920
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004921 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004922 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004923
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004924 // struct _ivar_t {
4925 // unsigned long int *offset; // pointer to ivar offset location
4926 // char *name;
4927 // char *type;
4928 // uint32_t alignment;
4929 // uint32_t size;
4930 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004931 IvarnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004932 llvm::StructType::create("struct._ivar_t",
4933 llvm::PointerType::getUnqual(LongTy),
4934 Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004935
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004936 // struct _ivar_list_t {
4937 // uint32 entsize; // sizeof(struct _ivar_t)
4938 // uint32 count;
4939 // struct _iver_t list[count];
4940 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004941 IvarListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004942 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
4943 llvm::ArrayType::get(IvarnfABITy, 0), NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004944
Owen Anderson9793f0e2009-07-29 22:16:19 +00004945 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004946
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004947 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004948 // uint32_t const flags;
4949 // uint32_t const instanceStart;
4950 // uint32_t const instanceSize;
4951 // uint32_t const reserved; // only when building for 64bit targets
4952 // const uint8_t * const ivarLayout;
4953 // const char *const name;
4954 // const struct _method_list_t * const baseMethods;
4955 // const struct _objc_protocol_list *const baseProtocols;
4956 // const struct _ivar_list_t *const ivars;
4957 // const uint8_t * const weakIvarLayout;
4958 // const struct _prop_list_t * const properties;
4959 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004960
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004961 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattner5ec04a52011-08-12 17:43:31 +00004962 ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
4963 IntTy, IntTy, IntTy, Int8PtrTy,
4964 Int8PtrTy, MethodListnfABIPtrTy,
4965 ProtocolListnfABIPtrTy,
4966 IvarListnfABIPtrTy,
4967 Int8PtrTy, PropertyListPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004968
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004969 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00004970 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00004971 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
4972 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004973
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004974 // struct _class_t {
4975 // struct _class_t *isa;
4976 // struct _class_t * const superclass;
4977 // void *cache;
4978 // IMP *vtable;
4979 // struct class_ro_t *ro;
4980 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004981
Chris Lattner5ec04a52011-08-12 17:43:31 +00004982 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00004983 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
4984 llvm::PointerType::getUnqual(ClassnfABITy),
4985 CachePtrTy,
4986 llvm::PointerType::getUnqual(ImpnfABITy),
4987 llvm::PointerType::getUnqual(ClassRonfABITy),
4988 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004989
Fariborz Jahanian71394042009-01-23 23:53:38 +00004990 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004991 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004992
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004993 // struct _category_t {
4994 // const char * const name;
4995 // struct _class_t *const cls;
4996 // const struct _method_list_t * const instance_methods;
4997 // const struct _method_list_t * const class_methods;
4998 // const struct _protocol_list_t * const protocols;
4999 // const struct _prop_list_t * const properties;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00005000 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005001 CategorynfABITy = llvm::StructType::create("struct._category_t",
5002 Int8PtrTy, ClassnfABIPtrTy,
5003 MethodListnfABIPtrTy,
5004 MethodListnfABIPtrTy,
5005 ProtocolListnfABIPtrTy,
5006 PropertyListPtrTy,
5007 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005008
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005009 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005010 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5011 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005012
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005013 // MessageRefTy - LLVM for:
5014 // struct _message_ref_t {
5015 // IMP messenger;
5016 // SEL name;
5017 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005018
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005019 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00005020 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005021 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005022 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005023 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005024 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005025 Ctx.VoidPtrTy, 0, 0, false, ICIS_NoInit));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005026 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005027 Ctx.getObjCSelType(), 0, 0, false,
5028 ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005029 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005030
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005031 MessageRefCTy = Ctx.getTagDeclType(RD);
5032 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
5033 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005034
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005035 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005036 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005037
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005038 // SuperMessageRefTy - LLVM for:
5039 // struct _super_message_ref_t {
5040 // SUPER_IMP messenger;
5041 // SEL name;
5042 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005043 SuperMessageRefTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005044 llvm::StructType::create("struct._super_message_ref_t",
5045 ImpnfABITy, SelectorPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005046
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005047 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005048 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005049
Daniel Dunbarb1559a42009-03-01 04:46:24 +00005050
5051 // struct objc_typeinfo {
5052 // const void** vtable; // objc_ehtype_vtable + 2
5053 // const char* name; // c++ typeinfo string
5054 // Class cls;
5055 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005056 EHTypeTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005057 llvm::StructType::create("struct._objc_typeinfo",
5058 llvm::PointerType::getUnqual(Int8PtrTy),
5059 Int8PtrTy, ClassnfABIPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005060 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005061}
5062
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005063llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00005064 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005065
Fariborz Jahanian71394042009-01-23 23:53:38 +00005066 return NULL;
5067}
5068
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00005069void CGObjCNonFragileABIMac::
5070AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
5071 const char *SymbolName,
5072 const char *SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00005073 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005074
Daniel Dunbar19573e72009-05-15 21:48:48 +00005075 if (!NumClasses)
5076 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005077
Chris Lattner3def9ae2012-02-06 22:16:34 +00005078 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005079 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00005080 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00005081 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00005082 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005083 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00005084 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00005085 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005086
Daniel Dunbar19573e72009-05-15 21:48:48 +00005087 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005088 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005089 llvm::GlobalValue::InternalLinkage,
5090 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005091 SymbolName);
Micah Villmowdd31ca12012-10-08 16:25:52 +00005092 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00005093 GV->setSection(SectionName);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005094 CGM.AddUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005095}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005096
Fariborz Jahanian71394042009-01-23 23:53:38 +00005097void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
5098 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005099
Daniel Dunbar19573e72009-05-15 21:48:48 +00005100 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005101 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005102 AddModuleClassList(DefinedClasses,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005103 "\01L_OBJC_LABEL_CLASS_$",
5104 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahanian67260552009-11-17 21:37:35 +00005105
Bill Wendling53136852012-02-07 09:06:01 +00005106 for (unsigned i = 0, e = DefinedClasses.size(); i < e; i++) {
Fariborz Jahanian67260552009-11-17 21:37:35 +00005107 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
5108 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
5109 continue;
5110 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahanian67260552009-11-17 21:37:35 +00005111 }
5112
Bill Wendling53136852012-02-07 09:06:01 +00005113 for (unsigned i = 0, e = DefinedMetaClasses.size(); i < e; i++) {
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005114 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
5115 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
5116 continue;
5117 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
5118 }
Fariborz Jahanian67260552009-11-17 21:37:35 +00005119
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005120 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005121 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
5122 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005123
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005124 // Build list of all implemented category addresses in array
5125 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005126 AddModuleClassList(DefinedCategories,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005127 "\01L_OBJC_LABEL_CATEGORY_$",
5128 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005129 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005130 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
5131 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005132
Daniel Dunbar5e639272010-04-25 20:39:01 +00005133 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005134}
5135
John McCall9e8bb002011-05-14 03:10:52 +00005136/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
5137/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005138/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005139/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00005140bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
5141 // At various points we've experimented with using vtable-based
5142 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005143 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005144 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00005145 return false;
John McCall9e8bb002011-05-14 03:10:52 +00005146 case CodeGenOptions::NonLegacy:
5147 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005148 case CodeGenOptions::Mixed:
5149 break;
5150 }
5151
5152 // If so, see whether this selector is in the white-list of things which must
5153 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00005154 if (VTableDispatchMethods.empty()) {
5155 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
5156 VTableDispatchMethods.insert(GetNullarySelector("class"));
5157 VTableDispatchMethods.insert(GetNullarySelector("self"));
5158 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
5159 VTableDispatchMethods.insert(GetNullarySelector("length"));
5160 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005161
John McCall9e8bb002011-05-14 03:10:52 +00005162 // These are vtable-based if GC is disabled.
5163 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005164 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00005165 VTableDispatchMethods.insert(GetNullarySelector("retain"));
5166 VTableDispatchMethods.insert(GetNullarySelector("release"));
5167 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
5168 }
5169
5170 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
5171 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
5172 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
5173 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
5174 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
5175 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
5176 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
5177
5178 // These are vtable-based if GC is enabled.
5179 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005180 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00005181 VTableDispatchMethods.insert(GetNullarySelector("hash"));
5182 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
5183
5184 // "countByEnumeratingWithState:objects:count"
5185 IdentifierInfo *KeyIdents[] = {
5186 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
5187 &CGM.getContext().Idents.get("objects"),
5188 &CGM.getContext().Idents.get("count")
5189 };
5190 VTableDispatchMethods.insert(
5191 CGM.getContext().Selectors.getSelector(3, KeyIdents));
5192 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005193 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005194
John McCall9e8bb002011-05-14 03:10:52 +00005195 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005196}
5197
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005198/// BuildClassRoTInitializer - generate meta-data for:
5199/// struct _class_ro_t {
5200/// uint32_t const flags;
5201/// uint32_t const instanceStart;
5202/// uint32_t const instanceSize;
5203/// uint32_t const reserved; // only when building for 64bit targets
5204/// const uint8_t * const ivarLayout;
5205/// const char *const name;
5206/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005207/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005208/// const struct _ivar_list_t *const ivars;
5209/// const uint8_t * const weakIvarLayout;
5210/// const struct _prop_list_t * const properties;
5211/// }
5212///
5213llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005214 unsigned flags,
5215 unsigned InstanceStart,
5216 unsigned InstanceSize,
5217 const ObjCImplementationDecl *ID) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005218 std::string ClassName = ID->getNameAsString();
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005219 llvm::Constant *Values[10]; // 11 for 64bit targets!
John McCall31168b02011-06-15 23:02:42 +00005220
David Blaikiebbafb8a2012-03-11 07:00:24 +00005221 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCallef19dbb2012-10-17 04:53:23 +00005222 flags |= NonFragileABI_Class_CompiledByARC;
John McCall31168b02011-06-15 23:02:42 +00005223
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005224 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
5225 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
5226 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005227 // FIXME. For 64bit targets add 0 here.
John McCallef19dbb2012-10-17 04:53:23 +00005228 Values[ 3] = (flags & NonFragileABI_Class_Meta)
5229 ? GetIvarLayoutName(0, ObjCTypes)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005230 : BuildIvarLayout(ID, true);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005231 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005232 // const struct _method_list_t * const baseMethods;
5233 std::vector<llvm::Constant*> Methods;
5234 std::string MethodListName("\01l_OBJC_$_");
John McCallef19dbb2012-10-17 04:53:23 +00005235 if (flags & NonFragileABI_Class_Meta) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005236 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005237 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005238 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005239 // Class methods should always be defined.
5240 Methods.push_back(GetMethodConstant(*i));
5241 }
5242 } else {
5243 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005244 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005245 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005246 // Instance methods should always be defined.
5247 Methods.push_back(GetMethodConstant(*i));
5248 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005249 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005250 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie40ed2972012-06-06 20:45:41 +00005251 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005252
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005253 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
5254 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005255
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005256 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
5257 if (llvm::Constant *C = GetMethodConstant(MD))
5258 Methods.push_back(C);
5259 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
5260 if (llvm::Constant *C = GetMethodConstant(MD))
5261 Methods.push_back(C);
5262 }
5263 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005264 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005265 Values[ 5] = EmitMethodList(MethodListName,
5266 "__DATA, __objc_const", Methods);
5267
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005268 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5269 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005270 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005271 + OID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00005272 OID->all_referenced_protocol_begin(),
5273 OID->all_referenced_protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005274
John McCallef19dbb2012-10-17 04:53:23 +00005275 if (flags & NonFragileABI_Class_Meta) {
Owen Anderson0b75f232009-07-31 20:28:54 +00005276 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCallef19dbb2012-10-17 04:53:23 +00005277 Values[ 8] = GetIvarLayoutName(0, ObjCTypes);
Owen Anderson0b75f232009-07-31 20:28:54 +00005278 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
John McCallef19dbb2012-10-17 04:53:23 +00005279 } else {
5280 Values[ 7] = EmitIvarList(ID);
5281 Values[ 8] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005282 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
5283 ID, ID->getClassInterface(), ObjCTypes);
John McCallef19dbb2012-10-17 04:53:23 +00005284 }
Owen Anderson0e0189d2009-07-27 22:29:56 +00005285 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005286 Values);
5287 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005288 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
5289 llvm::GlobalValue::InternalLinkage,
5290 Init,
John McCallef19dbb2012-10-17 04:53:23 +00005291 (flags & NonFragileABI_Class_Meta) ?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005292 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
5293 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005294 CLASS_RO_GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005295 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005296 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005297 return CLASS_RO_GV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005298
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005299}
5300
5301/// BuildClassMetaData - This routine defines that to-level meta-data
5302/// for the given ClassName for:
5303/// struct _class_t {
5304/// struct _class_t *isa;
5305/// struct _class_t * const superclass;
5306/// void *cache;
5307/// IMP *vtable;
5308/// struct class_ro_t *ro;
5309/// }
5310///
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005311llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005312 std::string &ClassName,
5313 llvm::Constant *IsAGV,
5314 llvm::Constant *SuperClassGV,
5315 llvm::Constant *ClassRoGV,
5316 bool HiddenVisibility) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005317 llvm::Constant *Values[] = {
5318 IsAGV,
5319 SuperClassGV,
5320 ObjCEmptyCacheVar, // &ObjCEmptyCacheVar
5321 ObjCEmptyVtableVar, // &ObjCEmptyVtableVar
5322 ClassRoGV // &CLASS_RO_GV
5323 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005324 if (!Values[1])
5325 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005326 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005327 Values);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005328 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
5329 GV->setInitializer(Init);
Fariborz Jahanian04087232009-01-31 01:07:39 +00005330 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005331 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005332 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian82208252009-01-31 00:59:10 +00005333 if (HiddenVisibility)
5334 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005335 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005336}
5337
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005338bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00005339CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005340 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005341}
5342
Daniel Dunbar961202372009-05-03 12:57:56 +00005343void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00005344 uint32_t &InstanceStart,
5345 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005346 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00005347 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005348
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005349 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00005350 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005351
5352 // If there are no fields, the start is the same as the end.
5353 if (!RL.getFieldCount())
5354 InstanceStart = InstanceSize;
5355 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00005356 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00005357}
5358
Fariborz Jahanian71394042009-01-23 23:53:38 +00005359void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
5360 std::string ClassName = ID->getNameAsString();
5361 if (!ObjCEmptyCacheVar) {
5362 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005363 CGM.getModule(),
5364 ObjCTypes.CacheTy,
5365 false,
5366 llvm::GlobalValue::ExternalLinkage,
5367 0,
5368 "_objc_empty_cache");
5369
Fariborz Jahanian71394042009-01-23 23:53:38 +00005370 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005371 CGM.getModule(),
5372 ObjCTypes.ImpnfABITy,
5373 false,
5374 llvm::GlobalValue::ExternalLinkage,
5375 0,
5376 "_objc_empty_vtable");
Fariborz Jahanian71394042009-01-23 23:53:38 +00005377 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005378 assert(ID->getClassInterface() &&
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005379 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00005380 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005381 uint32_t InstanceStart =
Micah Villmowdd31ca12012-10-08 16:25:52 +00005382 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005383 uint32_t InstanceSize = InstanceStart;
John McCallef19dbb2012-10-17 04:53:23 +00005384 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar15894b72009-04-07 05:48:37 +00005385 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
5386 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005387
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005388 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005389
John McCall0d54a172012-10-17 04:53:31 +00005390 // Build the flags for the metaclass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005391 bool classIsHidden =
John McCall457a04e2010-10-22 21:05:15 +00005392 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005393 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00005394 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00005395
5396 // FIXME: why is this flag set on the metaclass?
5397 // ObjC metaclasses have no fields and don't really get constructed.
5398 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00005399 flags |= NonFragileABI_Class_HasCXXStructors;
John McCall0d54a172012-10-17 04:53:31 +00005400 if (!ID->hasNonZeroConstructors())
5401 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5402 }
5403
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005404 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005405 // class is root
John McCallef19dbb2012-10-17 04:53:23 +00005406 flags |= NonFragileABI_Class_Root;
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005407 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005408 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005409 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005410 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005411 const ObjCInterfaceDecl *Root = ID->getClassInterface();
5412 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
5413 Root = Super;
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005414 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005415 if (Root->isWeakImported())
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005416 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005417 // work on super class metadata symbol.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005418 std::string SuperClassName =
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005419 ObjCMetaClassName +
5420 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005421 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005422 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00005423 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005424 }
5425 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
5426 InstanceStart,
5427 InstanceSize,ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005428 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005429 llvm::GlobalVariable *MetaTClass =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005430 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
5431 classIsHidden);
Fariborz Jahanian67260552009-11-17 21:37:35 +00005432 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00005433
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005434 // Metadata for the class
John McCallef19dbb2012-10-17 04:53:23 +00005435 flags = 0;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005436 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00005437 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00005438
5439 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00005440 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005441
John McCall0d54a172012-10-17 04:53:31 +00005442 // Set a flag to enable a runtime optimization when a class has
5443 // fields that require destruction but which don't require
5444 // anything except zero-initialization during construction. This
5445 // is most notably true of __strong and __weak types, but you can
5446 // also imagine there being C++ types with non-trivial default
5447 // constructors that merely set all fields to null.
5448 if (!ID->hasNonZeroConstructors())
5449 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5450 }
5451
Douglas Gregor78bd61f2009-06-18 16:11:24 +00005452 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
John McCallef19dbb2012-10-17 04:53:23 +00005453 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005454
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005455 if (!ID->getClassInterface()->getSuperClass()) {
John McCallef19dbb2012-10-17 04:53:23 +00005456 flags |= NonFragileABI_Class_Root;
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005457 SuperClassGV = 0;
Chris Lattnerb433b272009-04-19 06:02:28 +00005458 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005459 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005460 std::string RootClassName =
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005461 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005462 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005463 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00005464 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005465 }
Daniel Dunbar961202372009-05-03 12:57:56 +00005466 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005467 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005468 InstanceStart,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005469 InstanceSize,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005470 ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005471
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005472 TClassName = ObjCClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005473 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005474 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5475 classIsHidden);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005476 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005477
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005478 // Determine if this class is also "non-lazy".
5479 if (ImplementationIsNonLazy(ID))
5480 DefinedNonLazyClasses.push_back(ClassMD);
5481
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005482 // Force the definition of the EHType if necessary.
John McCallef19dbb2012-10-17 04:53:23 +00005483 if (flags & NonFragileABI_Class_Exception)
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005484 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005485 // Make sure method definition entries are all clear for next implementation.
5486 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005487}
5488
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005489/// GenerateProtocolRef - This routine is called to generate code for
5490/// a protocol reference expression; as in:
5491/// @code
5492/// @protocol(Proto1);
5493/// @endcode
5494/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5495/// which will hold address of the protocol meta-data.
5496///
5497llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005498 const ObjCProtocolDecl *PD) {
5499
Fariborz Jahanian464423d2009-04-10 18:47:34 +00005500 // This routine is called for @protocol only. So, we must build definition
5501 // of protocol's meta-data (not a reference to it!)
5502 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005503 llvm::Constant *Init =
5504 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00005505 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005506
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005507 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar56df9772010-08-17 22:39:59 +00005508 ProtocolName += PD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005509
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005510 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5511 if (PTGV)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005512 return Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005513 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005514 CGM.getModule(),
5515 Init->getType(), false,
5516 llvm::GlobalValue::WeakAnyLinkage,
5517 Init,
5518 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005519 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5520 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005521 CGM.AddUsedGlobal(PTGV);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005522 return Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005523}
5524
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005525/// GenerateCategory - Build metadata for a category implementation.
5526/// struct _category_t {
5527/// const char * const name;
5528/// struct _class_t *const cls;
5529/// const struct _method_list_t * const instance_methods;
5530/// const struct _method_list_t * const class_methods;
5531/// const struct _protocol_list_t * const protocols;
5532/// const struct _prop_list_t * const properties;
5533/// }
5534///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005535void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005536 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005537 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005538 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5539 "_$_" + OCD->getNameAsString());
5540 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar15894b72009-04-07 05:48:37 +00005541 Interface->getNameAsString());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005542
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005543 llvm::Constant *Values[6];
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005544 Values[0] = GetClassName(OCD->getIdentifier());
5545 // meta-class entry symbol
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005546 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005547 if (Interface->isWeakImported())
Fariborz Jahanian3ad8dcf2009-11-17 22:02:21 +00005548 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5549
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005550 Values[1] = ClassGV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005551 std::vector<llvm::Constant*> Methods;
5552 std::string MethodListName(Prefix);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005553 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005554 "_$_" + OCD->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005555
5556 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005557 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005558 // Instance methods should always be defined.
5559 Methods.push_back(GetMethodConstant(*i));
5560 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005561
5562 Values[2] = EmitMethodList(MethodListName,
5563 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005564 Methods);
5565
5566 MethodListName = Prefix;
5567 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5568 OCD->getNameAsString();
5569 Methods.clear();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005570 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005571 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005572 // Class methods should always be defined.
5573 Methods.push_back(GetMethodConstant(*i));
5574 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005575
5576 Values[3] = EmitMethodList(MethodListName,
5577 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005578 Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005579 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00005580 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005581 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005582 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005583 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5584 << OCD->getName();
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005585 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005586 + Interface->getName() + "_$_"
5587 + Category->getName(),
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005588 Category->protocol_begin(),
5589 Category->protocol_end());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005590 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5591 OCD, Category, ObjCTypes);
Mike Stump658fe022009-07-30 22:28:39 +00005592 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00005593 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5594 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005595 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005596
5597 llvm::Constant *Init =
5598 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005599 Values);
5600 llvm::GlobalVariable *GCATV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005601 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005602 false,
5603 llvm::GlobalValue::InternalLinkage,
5604 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005605 ExtCatName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005606 GCATV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005607 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005608 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005609 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005610 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005611
5612 // Determine if this category is also "non-lazy".
5613 if (ImplementationIsNonLazy(OCD))
5614 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005615 // method definition entries must be clear for next implementation.
5616 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005617}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005618
5619/// GetMethodConstant - Return a struct objc_method constant for the
5620/// given method if it has been defined. The result is null if the
5621/// method has not been defined. The return value has type MethodPtrTy.
5622llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005623 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005624 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005625 if (!Fn)
5626 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005627
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005628 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00005629 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005630 ObjCTypes.SelectorPtrTy),
5631 GetMethodVarType(MD),
5632 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
5633 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00005634 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005635}
5636
5637/// EmitMethodList - Build meta-data for method declarations
5638/// struct _method_list_t {
5639/// uint32_t entsize; // sizeof(struct _objc_method)
5640/// uint32_t method_count;
5641/// struct _objc_method method_list[method_count];
5642/// }
5643///
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00005644llvm::Constant *
5645CGObjCNonFragileABIMac::EmitMethodList(Twine Name,
5646 const char *Section,
5647 ArrayRef<llvm::Constant*> Methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005648 // Return null for empty list.
5649 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005650 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005651
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005652 llvm::Constant *Values[3];
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005653 // sizeof(struct _objc_method)
Micah Villmowdd31ca12012-10-08 16:25:52 +00005654 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005655 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005656 // method_count
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005657 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005658 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005659 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005660 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005661 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005662
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005663 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005664 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005665 llvm::GlobalValue::InternalLinkage, Init, Name);
Micah Villmowdd31ca12012-10-08 16:25:52 +00005666 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005667 GV->setSection(Section);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005668 CGM.AddUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005669 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005670}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005671
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005672/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5673/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005674llvm::GlobalVariable *
5675CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5676 const ObjCIvarDecl *Ivar) {
5677 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar3f86b9c2009-05-05 00:36:57 +00005678 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregorbcced4e2009-04-09 21:40:53 +00005679 '.' + Ivar->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005680 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005681 CGM.getModule().getGlobalVariable(Name);
5682 if (!IvarOffsetGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005683 IvarOffsetGV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005684 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005685 false,
5686 llvm::GlobalValue::ExternalLinkage,
5687 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005688 Name);
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005689 return IvarOffsetGV;
5690}
5691
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005692llvm::Constant *
5693CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5694 const ObjCIvarDecl *Ivar,
5695 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005696 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005697 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005698 Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005699 IvarOffsetGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005700 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005701
Mike Stump18bb9282009-05-16 07:57:57 +00005702 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
5703 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005704 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5705 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall457a04e2010-10-22 21:05:15 +00005706 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00005707 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00005708 else
Fariborz Jahanianbc3c77b2009-04-06 18:30:00 +00005709 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendlingf7d45982011-05-04 21:37:25 +00005710 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005711 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005712}
5713
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005714/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005715/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005716/// IvarListnfABIPtrTy.
5717/// struct _ivar_t {
5718/// unsigned long int *offset; // pointer to ivar offset location
5719/// char *name;
5720/// char *type;
5721/// uint32_t alignment;
5722/// uint32_t size;
5723/// }
5724/// struct _ivar_list_t {
5725/// uint32 entsize; // sizeof(struct _ivar_t)
5726/// uint32 count;
5727/// struct _iver_t list[count];
5728/// }
5729///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005730
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005731llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005732 const ObjCImplementationDecl *ID) {
5733
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005734 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005735
Jordy Rosea91768e2011-07-22 02:08:32 +00005736 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005737 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005738
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005739 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005740
Jordy Rosea91768e2011-07-22 02:08:32 +00005741 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005742 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00005743 // Ignore unnamed bit-fields.
5744 if (!IVD->getDeclName())
5745 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005746 llvm::Constant *Ivar[5];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005747 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar961202372009-05-03 12:57:56 +00005748 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005749 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5750 Ivar[2] = GetMethodVarType(IVD);
Chris Lattner2192fe52011-07-18 04:24:23 +00005751 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005752 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmowdd31ca12012-10-08 16:25:52 +00005753 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005754 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005755 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005756 Align = llvm::Log2_32(Align);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005757 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00005758 // NOTE. Size of a bitfield does not match gcc's, because of the
5759 // way bitfields are treated special in each. But I am told that
5760 // 'size' for bitfield ivars is ignored by the runtime so it does
5761 // not matter. If it matters, there is enough info to get the
5762 // bitfield right!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005763 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005764 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005765 }
5766 // Return null for empty list.
5767 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005768 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005769
5770 llvm::Constant *Values[3];
Micah Villmowdd31ca12012-10-08 16:25:52 +00005771 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005772 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5773 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005774 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005775 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005776 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005777 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005778 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5779 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005780 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005781 llvm::GlobalValue::InternalLinkage,
5782 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005783 Prefix + OID->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005784 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005785 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005786 GV->setSection("__DATA, __objc_const");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005787
Chris Lattnerf56501c2009-07-17 23:57:13 +00005788 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00005789 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005790}
5791
5792llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005793 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005794 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005795
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005796 if (!Entry) {
5797 // We use the initializer as a marker of whether this is a forward
5798 // reference or not. At module finalization we add the empty
5799 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005800 Entry =
5801 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5802 llvm::GlobalValue::ExternalLinkage,
5803 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005804 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005805 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005806 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005807
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005808 return Entry;
5809}
5810
5811/// GetOrEmitProtocol - Generate the protocol meta-data:
5812/// @code
5813/// struct _protocol_t {
5814/// id isa; // NULL
5815/// const char * const protocol_name;
5816/// const struct _protocol_list_t * protocol_list; // super protocols
5817/// const struct method_list_t * const instance_methods;
5818/// const struct method_list_t * const class_methods;
5819/// const struct method_list_t *optionalInstanceMethods;
5820/// const struct method_list_t *optionalClassMethods;
5821/// const struct _prop_list_t * properties;
5822/// const uint32_t size; // sizeof(struct _protocol_t)
5823/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005824/// const char ** extendedMethodTypes;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005825/// }
5826/// @endcode
5827///
5828
5829llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005830 const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00005831 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005832
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005833 // Early exit if a defining object has already been generated.
5834 if (Entry && Entry->hasInitializer())
5835 return Entry;
5836
Douglas Gregora715bff2012-01-01 19:51:50 +00005837 // Use the protocol definition, if there is one.
5838 if (const ObjCProtocolDecl *Def = PD->getDefinition())
5839 PD = Def;
5840
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005841 // Construct method lists.
5842 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5843 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005844 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005845 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005846 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005847 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005848 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00005849 if (!C)
5850 return GetOrEmitProtocolRef(PD);
5851
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005852 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5853 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005854 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005855 } else {
5856 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005857 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005858 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005859 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005860
5861 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005862 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005863 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005864 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00005865 if (!C)
5866 return GetOrEmitProtocolRef(PD);
5867
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005868 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5869 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005870 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005871 } else {
5872 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005873 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005874 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005875 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005876
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005877 MethodTypesExt.insert(MethodTypesExt.end(),
5878 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
5879
5880 llvm::Constant *Values[11];
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005881 // isa is NULL
Owen Anderson0b75f232009-07-31 20:28:54 +00005882 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005883 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005884 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5885 PD->protocol_begin(),
5886 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005887
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005888 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005889 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005890 "__DATA, __objc_const",
5891 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005892 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005893 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005894 "__DATA, __objc_const",
5895 ClassMethods);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005896 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005897 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005898 "__DATA, __objc_const",
5899 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005900 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005901 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005902 "__DATA, __objc_const",
5903 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005904 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005905 0, PD, ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005906 uint32_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00005907 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005908 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0b75f232009-07-31 20:28:54 +00005909 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005910 Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
5911 + PD->getName(),
5912 MethodTypesExt, ObjCTypes);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005913 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005914 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005915
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005916 if (Entry) {
5917 // Already created, fix the linkage and update the initializer.
Mike Stumpa6ca3342009-03-07 16:33:28 +00005918 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005919 Entry->setInitializer(Init);
5920 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005921 Entry =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005922 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
5923 false, llvm::GlobalValue::WeakAnyLinkage, Init,
5924 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005925 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005926 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005927 Entry->setSection("__DATA,__datacoal_nt,coalesced");
John McCallf9582a72012-03-30 21:29:05 +00005928
5929 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005930 }
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005931 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005932 CGM.AddUsedGlobal(Entry);
5933
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005934 // Use this protocol meta-data to build protocol list table in section
5935 // __DATA, __objc_protolist
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005936 llvm::GlobalVariable *PTGV =
5937 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
5938 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
5939 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005940 PTGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005941 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbarb25452a2009-04-15 02:56:18 +00005942 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005943 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005944 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005945 return Entry;
5946}
5947
5948/// EmitProtocolList - Generate protocol list meta-data:
5949/// @code
5950/// struct _protocol_list_t {
5951/// long protocol_count; // Note, this is 32/64 bit
5952/// struct _protocol_t[protocol_count];
5953/// }
5954/// @endcode
5955///
5956llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005957CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005958 ObjCProtocolDecl::protocol_iterator begin,
5959 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendlinga515b582012-02-09 22:16:49 +00005960 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005961
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005962 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005963 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00005964 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005965
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005966 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005967 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005968 Name.toVector(TmpName);
5969 llvm::GlobalVariable *GV =
5970 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005971 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005972 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005973
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005974 for (; begin != end; ++begin)
5975 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
5976
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005977 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00005978 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005979 ObjCTypes.ProtocolnfABIPtrTy));
5980
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005981 llvm::Constant *Values[2];
Owen Anderson170229f2009-07-14 23:10:40 +00005982 Values[0] =
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005983 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005984 Values[1] =
Bill Wendlinga515b582012-02-09 22:16:49 +00005985 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
5986 ProtocolRefs.size()),
5987 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005988
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005989 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Owen Andersonc10c8d32009-07-08 19:05:04 +00005990 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005991 llvm::GlobalValue::InternalLinkage,
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005992 Init, Name);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005993 GV->setSection("__DATA, __objc_const");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005994 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005995 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Chris Lattnerf56501c2009-07-17 23:57:13 +00005996 CGM.AddUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005997 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005998 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005999}
6000
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006001/// GetMethodDescriptionConstant - This routine build following meta-data:
6002/// struct _objc_method {
6003/// SEL _cmd;
6004/// char *method_type;
6005/// char *_imp;
6006/// }
6007
6008llvm::Constant *
6009CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006010 llvm::Constant *Desc[3];
Owen Anderson170229f2009-07-14 23:10:40 +00006011 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006012 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
6013 ObjCTypes.SelectorPtrTy);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006014 Desc[1] = GetMethodVarType(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006015 if (!Desc[1])
6016 return 0;
6017
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006018 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00006019 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006020 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006021}
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006022
6023/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
6024/// This code gen. amounts to generating code for:
6025/// @code
6026/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
6027/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006028///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00006029LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00006030 CodeGen::CodeGenFunction &CGF,
6031 QualType ObjectTy,
6032 llvm::Value *BaseValue,
6033 const ObjCIvarDecl *Ivar,
6034 unsigned CVRQualifiers) {
6035 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006036 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
6037 if (llvm::LoadInst *LI = dyn_cast<llvm::LoadInst>(Offset))
6038 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6039 llvm::MDNode::get(VMContext,
6040 ArrayRef<llvm::Value*>()));
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00006041 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006042 Offset);
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006043}
6044
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006045llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006046 CodeGen::CodeGenFunction &CGF,
6047 const ObjCInterfaceDecl *Interface,
6048 const ObjCIvarDecl *Ivar) {
Daniel Dunbarc76493a2009-11-29 21:23:36 +00006049 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006050}
6051
John McCall234eac82011-05-13 23:16:18 +00006052static void appendSelectorForMessageRefTable(std::string &buffer,
6053 Selector selector) {
6054 if (selector.isUnarySelector()) {
6055 buffer += selector.getNameForSlot(0);
6056 return;
6057 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006058
John McCall234eac82011-05-13 23:16:18 +00006059 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
6060 buffer += selector.getNameForSlot(i);
6061 buffer += '_';
6062 }
6063}
6064
John McCall9e8bb002011-05-14 03:10:52 +00006065/// Emit a "v-table" message send. We emit a weak hidden-visibility
6066/// struct, initially containing the selector pointer and a pointer to
6067/// a "fixup" variant of the appropriate objc_msgSend. To call, we
6068/// load and call the function pointer, passing the address of the
6069/// struct as the second parameter. The runtime determines whether
6070/// the selector is currently emitted using vtable dispatch; if so, it
6071/// substitutes a stub function which simply tail-calls through the
6072/// appropriate vtable slot, and if not, it substitues a stub function
6073/// which tail-calls objc_msgSend. Both stubs adjust the selector
6074/// argument to correctly point to the selector.
6075RValue
6076CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
6077 ReturnValueSlot returnSlot,
6078 QualType resultType,
6079 Selector selector,
6080 llvm::Value *arg0,
6081 QualType arg0Type,
6082 bool isSuper,
6083 const CallArgList &formalArgs,
6084 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00006085 // Compute the actual arguments.
6086 CallArgList args;
6087
John McCall9e8bb002011-05-14 03:10:52 +00006088 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00006089 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00006090 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
6091 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00006092
John McCall9e8bb002011-05-14 03:10:52 +00006093 // Second argument: a pointer to the message ref structure. Leave
6094 // the actual argument value blank for now.
John McCall234eac82011-05-13 23:16:18 +00006095 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
6096
6097 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
6098
John McCalla729c622012-02-17 03:33:10 +00006099 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCall234eac82011-05-13 23:16:18 +00006100
John McCall5880fb82011-05-14 21:12:11 +00006101 NullReturnState nullReturn;
6102
John McCall9e8bb002011-05-14 03:10:52 +00006103 // Find the function to call and the mangled name for the message
6104 // ref structure. Using a different mangled name wouldn't actually
6105 // be a problem; it would just be a waste.
6106 //
6107 // The runtime currently never uses vtable dispatch for anything
6108 // except normal, non-super message-sends.
6109 // FIXME: don't use this for that.
John McCall234eac82011-05-13 23:16:18 +00006110 llvm::Constant *fn = 0;
6111 std::string messageRefName("\01l_");
John McCalla729c622012-02-17 03:33:10 +00006112 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
John McCall234eac82011-05-13 23:16:18 +00006113 if (isSuper) {
6114 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
6115 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006116 } else {
John McCall5880fb82011-05-14 21:12:11 +00006117 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00006118 fn = ObjCTypes.getMessageSendStretFixupFn();
6119 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006120 }
John McCall234eac82011-05-13 23:16:18 +00006121 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
6122 fn = ObjCTypes.getMessageSendFpretFixupFn();
6123 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00006124 } else {
John McCall234eac82011-05-13 23:16:18 +00006125 if (isSuper) {
6126 fn = ObjCTypes.getMessageSendSuper2FixupFn();
6127 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006128 } else {
John McCall234eac82011-05-13 23:16:18 +00006129 fn = ObjCTypes.getMessageSendFixupFn();
6130 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006131 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006132 }
John McCall234eac82011-05-13 23:16:18 +00006133 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
6134 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006135
John McCall234eac82011-05-13 23:16:18 +00006136 // Append the selector name, except use underscores anywhere we
6137 // would have used colons.
6138 appendSelectorForMessageRefTable(messageRefName, selector);
6139
6140 llvm::GlobalVariable *messageRef
6141 = CGM.getModule().getGlobalVariable(messageRefName);
6142 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00006143 // Build the message ref structure.
John McCall234eac82011-05-13 23:16:18 +00006144 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006145 llvm::Constant *init = llvm::ConstantStruct::getAnon(values);
John McCall234eac82011-05-13 23:16:18 +00006146 messageRef = new llvm::GlobalVariable(CGM.getModule(),
6147 init->getType(),
6148 /*constant*/ false,
6149 llvm::GlobalValue::WeakAnyLinkage,
6150 init,
6151 messageRefName);
6152 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
6153 messageRef->setAlignment(16);
6154 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
6155 }
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006156
6157 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00006158 if (CGM.getLangOpts().ObjCAutoRefCount && method)
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006159 for (ObjCMethodDecl::param_const_iterator i = method->param_begin(),
6160 e = method->param_end(); i != e; ++i) {
6161 const ParmVarDecl *ParamDecl = (*i);
6162 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
6163 if (!nullReturn.NullBB)
6164 nullReturn.init(CGF, arg0);
6165 requiresnullCheck = true;
6166 break;
6167 }
6168 }
6169
John McCall234eac82011-05-13 23:16:18 +00006170 llvm::Value *mref =
6171 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
6172
John McCall9e8bb002011-05-14 03:10:52 +00006173 // Update the message ref argument.
John McCall234eac82011-05-13 23:16:18 +00006174 args[1].RV = RValue::get(mref);
6175
6176 // Load the function to call from the message ref table.
6177 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
6178 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
6179
John McCalla729c622012-02-17 03:33:10 +00006180 callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
John McCall234eac82011-05-13 23:16:18 +00006181
John McCalla729c622012-02-17 03:33:10 +00006182 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006183 return nullReturn.complete(CGF, result, resultType, formalArgs,
6184 requiresnullCheck ? method : 0);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00006185}
6186
6187/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006188CodeGen::RValue
6189CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00006190 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006191 QualType ResultType,
6192 Selector Sel,
6193 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006194 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00006195 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006196 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00006197 return isVTableDispatchedSelector(Sel)
6198 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006199 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00006200 false, CallArgs, Method)
6201 : EmitMessageSend(CGF, Return, ResultType,
6202 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006203 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00006204 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00006205}
6206
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006207llvm::GlobalVariable *
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006208CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006209 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
6210
Daniel Dunbara6468342009-03-02 05:18:14 +00006211 if (!GV) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006212 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006213 false, llvm::GlobalValue::ExternalLinkage,
6214 0, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006215 }
6216
6217 return GV;
6218}
6219
John McCall31168b02011-06-15 23:02:42 +00006220llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CGBuilderTy &Builder,
6221 IdentifierInfo *II) {
6222 llvm::GlobalVariable *&Entry = ClassReferences[II];
6223
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006224 if (!Entry) {
John McCall31168b02011-06-15 23:02:42 +00006225 std::string ClassName(getClassSymbolPrefix() + II->getName().str());
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006226 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006227 Entry =
John McCall31168b02011-06-15 23:02:42 +00006228 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
6229 false, llvm::GlobalValue::InternalLinkage,
6230 ClassGV,
6231 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006232 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006233 CGM.getDataLayout().getABITypeAlignment(
John McCall31168b02011-06-15 23:02:42 +00006234 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006235 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006236 CGM.AddUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006237 }
John McCall31168b02011-06-15 23:02:42 +00006238
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006239 return Builder.CreateLoad(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006240}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006241
John McCall31168b02011-06-15 23:02:42 +00006242llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
6243 const ObjCInterfaceDecl *ID) {
6244 return EmitClassRefFromId(Builder, ID->getIdentifier());
6245}
6246
6247llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
6248 CGBuilderTy &Builder) {
6249 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
6250 return EmitClassRefFromId(Builder, II);
6251}
6252
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006253llvm::Value *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006254CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006255 const ObjCInterfaceDecl *ID) {
6256 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006257
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006258 if (!Entry) {
6259 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6260 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006261 Entry =
6262 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006263 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006264 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006265 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006266 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006267 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006268 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006269 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006270 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006271 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006272
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006273 return Builder.CreateLoad(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006274}
6275
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006276/// EmitMetaClassRef - Return a Value * of the address of _class_t
6277/// meta-data
6278///
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006279llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
6280 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006281 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
6282 if (Entry)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006283 return Builder.CreateLoad(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006284
Daniel Dunbar15894b72009-04-07 05:48:37 +00006285 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006286 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006287 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006288 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006289 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006290 MetaClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006291 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006292 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006293 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006294 ObjCTypes.ClassnfABIPtrTy));
6295
Daniel Dunbare60aa052009-04-15 19:03:14 +00006296 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006297 CGM.AddUsedGlobal(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006298
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006299 return Builder.CreateLoad(Entry);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006300}
6301
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006302/// GetClass - Return a reference to the class for the given interface
6303/// decl.
6304llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
6305 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00006306 if (ID->isWeakImported()) {
Fariborz Jahanian95ace552009-11-17 22:42:00 +00006307 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6308 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
6309 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
6310 }
6311
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006312 return EmitClassRef(Builder, ID);
6313}
6314
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006315/// Generates a message send where the super is the receiver. This is
6316/// a message send to self with special delivery semantics indicating
6317/// which class's method should be called.
6318CodeGen::RValue
6319CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00006320 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006321 QualType ResultType,
6322 Selector Sel,
6323 const ObjCInterfaceDecl *Class,
6324 bool isCategoryImpl,
6325 llvm::Value *Receiver,
6326 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006327 const CodeGen::CallArgList &CallArgs,
6328 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006329 // ...
6330 // Create and init a super structure; this is a (receiver, class)
6331 // pair we will pass to objc_msgSendSuper.
6332 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00006333 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006334
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006335 llvm::Value *ReceiverAsObject =
6336 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
6337 CGF.Builder.CreateStore(ReceiverAsObject,
6338 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006339
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006340 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00006341 llvm::Value *Target;
Fariborz Jahanian27678b02012-10-10 23:11:18 +00006342 if (IsClassMessage)
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00006343 Target = EmitMetaClassRef(CGF.Builder, Class);
Fariborz Jahanian27678b02012-10-10 23:11:18 +00006344 else
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006345 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006346
Mike Stump18bb9282009-05-16 07:57:57 +00006347 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
6348 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00006349 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006350 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
6351 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
6352 CGF.Builder.CreateStore(Target,
6353 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006354
John McCall9e8bb002011-05-14 03:10:52 +00006355 return (isVTableDispatchedSelector(Sel))
6356 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006357 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006358 true, CallArgs, Method)
6359 : EmitMessageSend(CGF, Return, ResultType,
6360 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006361 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006362 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006363}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006364
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006365llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006366 Selector Sel, bool lval) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006367 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006368
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006369 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006370 llvm::Constant *Casted =
6371 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
6372 ObjCTypes.SelectorPtrTy);
6373 Entry =
6374 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
6375 llvm::GlobalValue::InternalLinkage,
6376 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006377 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006378 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006379 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006380
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006381 if (lval)
6382 return Entry;
Pete Cooper9d605512011-11-10 21:45:06 +00006383 llvm::LoadInst* LI = Builder.CreateLoad(Entry);
6384
6385 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6386 llvm::MDNode::get(VMContext,
6387 ArrayRef<llvm::Value*>()));
6388 return LI;
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006389}
Fariborz Jahanian06292952009-02-16 22:52:32 +00006390/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006391/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00006392///
6393void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006394 llvm::Value *src,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006395 llvm::Value *dst,
6396 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006397 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006398 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006399 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006400 assert(Size <= 8 && "does not support size > 8");
6401 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6402 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006403 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6404 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006405 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6406 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006407 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
6408 src, dst, ivarOffset);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006409 return;
6410}
6411
6412/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
6413/// objc_assign_strongCast (id src, id *dst)
6414///
6415void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006416 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006417 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006418 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006419 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006420 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006421 assert(Size <= 8 && "does not support size > 8");
6422 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006423 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006424 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6425 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006426 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6427 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00006428 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006429 src, dst, "weakassign");
6430 return;
6431}
6432
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006433void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006434 CodeGen::CodeGenFunction &CGF,
6435 llvm::Value *DestPtr,
6436 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00006437 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006438 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
6439 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006440 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00006441 DestPtr, SrcPtr, Size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006442 return;
6443}
6444
Fariborz Jahanian06292952009-02-16 22:52:32 +00006445/// EmitObjCWeakRead - Code gen for loading value of a __weak
6446/// object: objc_read_weak (id *src)
6447///
6448llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006449 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006450 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006451 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006452 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
6453 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00006454 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006455 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00006456 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006457 return read_weak;
6458}
6459
6460/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
6461/// objc_assign_weak (id src, id *dst)
6462///
6463void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006464 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006465 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006466 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006467 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006468 assert(Size <= 8 && "does not support size > 8");
6469 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6470 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006471 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6472 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006473 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6474 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00006475 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006476 src, dst, "weakassign");
6477 return;
6478}
6479
6480/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
6481/// objc_assign_global (id src, id *dst)
6482///
6483void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00006484 llvm::Value *src, llvm::Value *dst,
6485 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006486 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006487 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006488 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006489 assert(Size <= 8 && "does not support size > 8");
6490 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6491 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006492 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6493 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006494 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6495 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00006496 if (!threadlocal)
6497 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
6498 src, dst, "globalassign");
6499 else
6500 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
6501 src, dst, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00006502 return;
6503}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006504
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006505void
John McCallbd309292010-07-06 01:34:17 +00006506CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6507 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006508 EmitAtSynchronizedStmt(CGF, S,
6509 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6510 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00006511}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006512
John McCall2ca705e2010-07-24 00:37:23 +00006513llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00006514CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00006515 // There's a particular fixed type info for 'id'.
6516 if (T->isObjCIdType() ||
6517 T->isObjCQualifiedIdType()) {
6518 llvm::Constant *IDEHType =
6519 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6520 if (!IDEHType)
6521 IDEHType =
6522 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6523 false,
6524 llvm::GlobalValue::ExternalLinkage,
6525 0, "OBJC_EHTYPE_id");
6526 return IDEHType;
6527 }
6528
6529 // All other types should be Objective-C interface pointer types.
6530 const ObjCObjectPointerType *PT =
6531 T->getAs<ObjCObjectPointerType>();
6532 assert(PT && "Invalid @catch type.");
6533 const ObjCInterfaceType *IT = PT->getInterfaceType();
6534 assert(IT && "Invalid @catch type.");
6535 return GetInterfaceEHType(IT->getDecl(), false);
6536}
6537
John McCallbd309292010-07-06 01:34:17 +00006538void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6539 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006540 EmitTryCatchStmt(CGF, S,
6541 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6542 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6543 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006544}
6545
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006546/// EmitThrowStmt - Generate code for a throw statement.
6547void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6548 const ObjCAtThrowStmt &S) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006549 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00006550 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006551 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Jay Foad5bd375a2011-07-15 08:37:34 +00006552 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall17afe452010-10-16 08:21:07 +00006553 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006554 } else {
Jay Foad5bd375a2011-07-15 08:37:34 +00006555 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall17afe452010-10-16 08:21:07 +00006556 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006557 }
6558
John McCall17afe452010-10-16 08:21:07 +00006559 CGF.Builder.CreateUnreachable();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006560 CGF.Builder.ClearInsertionPoint();
6561}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006562
John McCall2ca705e2010-07-24 00:37:23 +00006563llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006564CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006565 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006566 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006567
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006568 // If we don't need a definition, return the entry if found or check
6569 // if we use an external reference.
6570 if (!ForDefinition) {
6571 if (Entry)
6572 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00006573
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006574 // If this type (or a super class) has the __objc_exception__
6575 // attribute, emit an external reference.
Douglas Gregor78bd61f2009-06-18 16:11:24 +00006576 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006577 return Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006578 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006579 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006580 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006581 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006582 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006583 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006584
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006585 // Otherwise we need to either make a new entry or fill in the
6586 // initializer.
6587 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar15894b72009-04-07 05:48:37 +00006588 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006589 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006590 llvm::GlobalVariable *VTableGV =
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006591 CGM.getModule().getGlobalVariable(VTableName);
6592 if (!VTableGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006593 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6594 false,
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006595 llvm::GlobalValue::ExternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006596 0, VTableName);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006597
Chris Lattnerece04092012-02-07 00:39:47 +00006598 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006599
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006600 llvm::Constant *Values[] = {
6601 llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
6602 GetClassName(ID->getIdentifier()),
6603 GetClassGlobal(ClassName)
6604 };
Owen Anderson170229f2009-07-14 23:10:40 +00006605 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00006606 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006607
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006608 if (Entry) {
6609 Entry->setInitializer(Init);
6610 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00006611 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006612 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006613 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006614 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006615 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006616 }
6617
David Blaikiebbafb8a2012-03-11 07:00:24 +00006618 if (CGM.getLangOpts().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar15894b72009-04-07 05:48:37 +00006619 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Micah Villmowdd31ca12012-10-08 16:25:52 +00006620 Entry->setAlignment(CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00006621 ObjCTypes.EHTypeTy));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006622
6623 if (ForDefinition) {
6624 Entry->setSection("__DATA,__objc_const");
6625 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6626 } else {
6627 Entry->setSection("__DATA,__datacoal_nt,coalesced");
6628 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006629
6630 return Entry;
6631}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006632
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00006633/* *** */
6634
Daniel Dunbarb036db82008-08-13 03:21:16 +00006635CodeGen::CGObjCRuntime *
6636CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall5fb5df92012-06-20 06:18:46 +00006637 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
6638 case ObjCRuntime::FragileMacOSX:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00006639 return new CGObjCMac(CGM);
John McCall5fb5df92012-06-20 06:18:46 +00006640
6641 case ObjCRuntime::MacOSX:
6642 case ObjCRuntime::iOS:
6643 return new CGObjCNonFragileABIMac(CGM);
6644
David Chisnallb601c962012-07-03 20:49:52 +00006645 case ObjCRuntime::GNUstep:
6646 case ObjCRuntime::GCC:
John McCall775086e2012-07-12 02:07:58 +00006647 case ObjCRuntime::ObjFW:
John McCall5fb5df92012-06-20 06:18:46 +00006648 llvm_unreachable("these runtimes are not Mac runtimes");
6649 }
6650 llvm_unreachable("bad runtime");
Daniel Dunbar303e2c22008-08-11 02:45:11 +00006651}