blob: 7219592fffcd71a3e418e965397b0dc36ef023dc [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
John McCallad7c5c12011-02-08 08:22:06 +000014#include "CGBlocks.h"
John McCalled1ae862011-01-28 11:13:47 +000015#include "CGCleanup.h"
Justin Lebar5e83dfe2016-10-21 21:45:01 +000016#include "CGObjCRuntime.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000017#include "CGRecordLayout.h"
18#include "CodeGenFunction.h"
19#include "CodeGenModule.h"
John McCall176f8922016-11-30 02:39:18 +000020#include "ConstantBuilder.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"
Mark Laceya8e7df32013-10-30 21:53:58 +000027#include "clang/CodeGen/CGFunctionInfo.h"
Saleem Abdulrasool10a49722016-04-08 16:52:00 +000028#include "clang/Frontend/CodeGenOptions.h"
Justin Lebar5e83dfe2016-10-21 21:45:01 +000029#include "llvm/ADT/CachedHashString.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000030#include "llvm/ADT/DenseSet.h"
31#include "llvm/ADT/SetVector.h"
32#include "llvm/ADT/SmallPtrSet.h"
33#include "llvm/ADT/SmallString.h"
Chandler Carruthc80ceea2014-03-04 11:02:08 +000034#include "llvm/IR/CallSite.h"
Chandler Carruthffd55512013-01-02 11:45:17 +000035#include "llvm/IR/DataLayout.h"
36#include "llvm/IR/InlineAsm.h"
37#include "llvm/IR/IntrinsicInst.h"
38#include "llvm/IR/LLVMContext.h"
39#include "llvm/IR/Module.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000040#include "llvm/Support/raw_ostream.h"
Torok Edwindb714922009-08-24 13:25:12 +000041#include <cstdio>
Daniel Dunbar303e2c22008-08-11 02:45:11 +000042
43using namespace clang;
Daniel Dunbar41cf9de2008-09-09 01:06:48 +000044using namespace CodeGen;
Daniel Dunbar303e2c22008-08-11 02:45:11 +000045
46namespace {
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000047
Daniel Dunbar59e476b2009-08-03 17:06:42 +000048// FIXME: We should find a nicer way to make the labels for metadata, string
49// concatenation is lame.
Daniel Dunbarb036db82008-08-13 03:21:16 +000050
Fariborz Jahanian279eda62009-01-21 22:04:16 +000051class ObjCCommonTypesHelper {
Owen Anderson170229f2009-07-14 23:10:40 +000052protected:
53 llvm::LLVMContext &VMContext;
Daniel Dunbar59e476b2009-08-03 17:06:42 +000054
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000055private:
John McCall9dc0db22011-05-15 01:53:33 +000056 // The types of these functions don't really matter because we
57 // should always bitcast before calling them.
58
59 /// id objc_msgSend (id, SEL, ...)
60 ///
61 /// The default messenger, used for sends whose ABI is unchanged from
62 /// the all-integer/pointer case.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000063 llvm::Constant *getMessageSendFn() const {
John McCall31168b02011-06-15 23:02:42 +000064 // Add the non-lazy-bind attribute, since objc_msgSend is likely to
65 // be called a lot.
Chris Lattnera5f58b02011-07-09 17:41:47 +000066 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Bill Wendling8594fcb2013-01-31 00:30:05 +000067 return
68 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
69 params, true),
70 "objc_msgSend",
71 llvm::AttributeSet::get(CGM.getLLVMContext(),
72 llvm::AttributeSet::FunctionIndex,
73 llvm::Attribute::NonLazyBind));
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000074 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000075
John McCall9dc0db22011-05-15 01:53:33 +000076 /// void objc_msgSend_stret (id, SEL, ...)
77 ///
78 /// The messenger used when the return value is an aggregate returned
79 /// by indirect reference in the first argument, and therefore the
80 /// self and selector parameters are shifted over by one.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000081 llvm::Constant *getMessageSendStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000082 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +000083 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
84 params, true),
85 "objc_msgSend_stret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000086
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000087 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000088
John McCall9dc0db22011-05-15 01:53:33 +000089 /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
90 ///
91 /// The messenger used when the return value is returned on the x87
92 /// floating-point stack; without a special entrypoint, the nil case
93 /// would be unbalanced.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000094 llvm::Constant *getMessageSendFpretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000095 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Chris Lattnerece04092012-02-07 00:39:47 +000096 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
97 params, true),
John McCall9dc0db22011-05-15 01:53:33 +000098 "objc_msgSend_fpret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000099
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000100 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000101
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000102 /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
103 ///
104 /// The messenger used when the return value is returned in two values on the
105 /// x87 floating point stack; without a special entrypoint, the nil case
106 /// would be unbalanced. Only used on 64-bit X86.
107 llvm::Constant *getMessageSendFp2retFn() const {
108 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
109 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
110 llvm::Type *resultType =
Reid Kleckneree7cf842014-12-01 22:02:27 +0000111 llvm::StructType::get(longDoubleType, longDoubleType, nullptr);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000112
113 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
114 params, true),
115 "objc_msgSend_fp2ret");
116 }
117
John McCall9dc0db22011-05-15 01:53:33 +0000118 /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
119 ///
120 /// The messenger used for super calls, which have different dispatch
121 /// semantics. The class passed is the superclass of the current
122 /// class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000123 llvm::Constant *getMessageSendSuperFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000124 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000125 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000126 params, true),
127 "objc_msgSendSuper");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000128 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000129
John McCall9dc0db22011-05-15 01:53:33 +0000130 /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
131 ///
132 /// A slightly different messenger used for super calls. The class
133 /// passed is the current class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000134 llvm::Constant *getMessageSendSuperFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000135 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000136 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000137 params, true),
138 "objc_msgSendSuper2");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000139 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000140
John McCall9dc0db22011-05-15 01:53:33 +0000141 /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
142 /// SEL op, ...)
143 ///
144 /// The messenger used for super calls which return an aggregate indirectly.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000145 llvm::Constant *getMessageSendSuperStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000146 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000147 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000148 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000149 "objc_msgSendSuper_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000150 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000151
John McCall9dc0db22011-05-15 01:53:33 +0000152 /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
153 /// SEL op, ...)
154 ///
155 /// objc_msgSendSuper_stret with the super2 semantics.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000156 llvm::Constant *getMessageSendSuperStretFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000157 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000158 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000159 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000160 "objc_msgSendSuper2_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000161 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000162
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000163 llvm::Constant *getMessageSendSuperFpretFn() const {
164 // There is no objc_msgSendSuper_fpret? How can that work?
165 return getMessageSendSuperFn();
166 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000167
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000168 llvm::Constant *getMessageSendSuperFpretFn2() const {
169 // There is no objc_msgSendSuper_fpret? How can that work?
170 return getMessageSendSuperFn2();
171 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000172
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000173protected:
174 CodeGen::CodeGenModule &CGM;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000175
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000176public:
John McCall176f8922016-11-30 02:39:18 +0000177 llvm::IntegerType *ShortTy, *IntTy, *LongTy;
178 llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
Tim Northover238b5082014-03-29 13:42:40 +0000179 llvm::Type *IvarOffsetVarTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000180
Daniel Dunbar5d715592008-08-12 05:28:47 +0000181 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
John McCall176f8922016-11-30 02:39:18 +0000182 llvm::PointerType *ObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000183
Fariborz Jahanian406b1172008-11-18 20:18:11 +0000184 /// PtrObjectPtrTy - LLVM type for id *
John McCall176f8922016-11-30 02:39:18 +0000185 llvm::PointerType *PtrObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000186
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000187 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
John McCall176f8922016-11-30 02:39:18 +0000188 llvm::PointerType *SelectorPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000189
190private:
Daniel Dunbarb036db82008-08-13 03:21:16 +0000191 /// ProtocolPtrTy - LLVM type for external protocol handles
192 /// (typeof(Protocol))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000193 llvm::Type *ExternalProtocolPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000194
195public:
196 llvm::Type *getExternalProtocolPtrTy() {
197 if (!ExternalProtocolPtrTy) {
198 // FIXME: It would be nice to unify this with the opaque type, so that the
199 // IR comes out a bit cleaner.
200 CodeGen::CodeGenTypes &Types = CGM.getTypes();
201 ASTContext &Ctx = CGM.getContext();
202 llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
203 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
204 }
205
206 return ExternalProtocolPtrTy;
207 }
208
Daniel Dunbarc722b852008-08-30 03:02:31 +0000209 // SuperCTy - clang type for struct objc_super.
210 QualType SuperCTy;
211 // SuperPtrCTy - clang type for struct objc_super *.
212 QualType SuperPtrCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000213
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000214 /// SuperTy - LLVM type for struct objc_super.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000215 llvm::StructType *SuperTy;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +0000216 /// SuperPtrTy - LLVM type for struct objc_super *.
John McCall176f8922016-11-30 02:39:18 +0000217 llvm::PointerType *SuperPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000218
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000219 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
220 /// in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000221 llvm::StructType *PropertyTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000222
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000223 /// PropertyListTy - LLVM type for struct objc_property_list
224 /// (_prop_list_t in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000225 llvm::StructType *PropertyListTy;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000226 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
John McCall176f8922016-11-30 02:39:18 +0000227 llvm::PointerType *PropertyListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000228
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000229 // MethodTy - LLVM type for struct objc_method.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000230 llvm::StructType *MethodTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000231
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000232 /// CacheTy - LLVM type for struct objc_cache.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000233 llvm::Type *CacheTy;
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000234 /// CachePtrTy - LLVM type for struct objc_cache *.
John McCall176f8922016-11-30 02:39:18 +0000235 llvm::PointerType *CachePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000236
Chris Lattnerce8754e2009-04-22 02:44:54 +0000237 llvm::Constant *getGetPropertyFn() {
238 CodeGen::CodeGenTypes &Types = CGM.getTypes();
239 ASTContext &Ctx = CGM.getContext();
240 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
John McCall2da83a32010-02-26 00:48:12 +0000241 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
242 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Benjamin Kramer30934732016-07-02 11:41:41 +0000243 CanQualType Params[] = {
244 IdType, SelType,
245 Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), Ctx.BoolTy};
Chris Lattner2192fe52011-07-18 04:24:23 +0000246 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000247 Types.GetFunctionType(
248 Types.arrangeBuiltinFunctionDeclaration(IdType, Params));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000249 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
250 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000251
Chris Lattnerce8754e2009-04-22 02:44:54 +0000252 llvm::Constant *getSetPropertyFn() {
253 CodeGen::CodeGenTypes &Types = CGM.getTypes();
254 ASTContext &Ctx = CGM.getContext();
255 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
John McCall2da83a32010-02-26 00:48:12 +0000256 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
257 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Benjamin Kramer30934732016-07-02 11:41:41 +0000258 CanQualType Params[] = {
259 IdType,
260 SelType,
261 Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(),
262 IdType,
263 Ctx.BoolTy,
264 Ctx.BoolTy};
Chris Lattner2192fe52011-07-18 04:24:23 +0000265 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000266 Types.GetFunctionType(
267 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
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 McCallc56a8b32016-03-11 04:30:31 +0000291 Types.GetFunctionType(
292 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Ted Kremeneke65b0862012-03-06 20:05:56 +0000293 const char *name;
294 if (atomic && copy)
295 name = "objc_setProperty_atomic_copy";
296 else if (atomic && !copy)
297 name = "objc_setProperty_atomic";
298 else if (!atomic && copy)
299 name = "objc_setProperty_nonatomic_copy";
300 else
301 name = "objc_setProperty_nonatomic";
302
303 return CGM.CreateRuntimeFunction(FTy, name);
304 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000305
306 llvm::Constant *getCopyStructFn() {
307 CodeGen::CodeGenTypes &Types = CGM.getTypes();
308 ASTContext &Ctx = CGM.getContext();
309 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000310 SmallVector<CanQualType,5> Params;
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000311 Params.push_back(Ctx.VoidPtrTy);
312 Params.push_back(Ctx.VoidPtrTy);
313 Params.push_back(Ctx.LongTy);
314 Params.push_back(Ctx.BoolTy);
315 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000316 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000317 Types.GetFunctionType(
318 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000319 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
320 }
321
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000322 /// This routine declares and returns address of:
323 /// void objc_copyCppObjectAtomic(
324 /// void *dest, const void *src,
325 /// void (*copyHelper) (void *dest, const void *source));
326 llvm::Constant *getCppAtomicObjectFunction() {
327 CodeGen::CodeGenTypes &Types = CGM.getTypes();
328 ASTContext &Ctx = CGM.getContext();
329 /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
330 SmallVector<CanQualType,3> Params;
331 Params.push_back(Ctx.VoidPtrTy);
332 Params.push_back(Ctx.VoidPtrTy);
333 Params.push_back(Ctx.VoidPtrTy);
334 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000335 Types.GetFunctionType(
336 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000337 return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
338 }
339
Chris Lattnerce8754e2009-04-22 02:44:54 +0000340 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000341 CodeGen::CodeGenTypes &Types = CGM.getTypes();
342 ASTContext &Ctx = CGM.getContext();
Chris Lattnerce8754e2009-04-22 02:44:54 +0000343 // void objc_enumerationMutation (id)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000344 SmallVector<CanQualType,1> Params;
John McCall2da83a32010-02-26 00:48:12 +0000345 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Chris Lattner2192fe52011-07-18 04:24:23 +0000346 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000347 Types.GetFunctionType(
348 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000349 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
350 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000351
Douglas Gregor24ae22c2016-04-01 23:23:52 +0000352 llvm::Constant *getLookUpClassFn() {
353 CodeGen::CodeGenTypes &Types = CGM.getTypes();
354 ASTContext &Ctx = CGM.getContext();
355 // Class objc_lookUpClass (const char *)
356 SmallVector<CanQualType,1> Params;
357 Params.push_back(
358 Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst())));
359 llvm::FunctionType *FTy =
360 Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration(
361 Ctx.getCanonicalType(Ctx.getObjCClassType()),
362 Params));
363 return CGM.CreateRuntimeFunction(FTy, "objc_lookUpClass");
364 }
365
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000366 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattnerce8754e2009-04-22 02:44:54 +0000367 llvm::Constant *getGcReadWeakFn() {
368 // id objc_read_weak (id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000369 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000370 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000371 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000372 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000373 }
374
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000375 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000376 llvm::Constant *getGcAssignWeakFn() {
377 // id objc_assign_weak (id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000378 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000379 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000380 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000381 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
382 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000383
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000384 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000385 llvm::Constant *getGcAssignGlobalFn() {
386 // id objc_assign_global(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000387 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000388 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000389 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000390 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
391 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000392
Fariborz Jahanian217af242010-07-20 20:30:03 +0000393 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
394 llvm::Constant *getGcAssignThreadLocalFn() {
395 // id objc_assign_threadlocal(id src, id * dest)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000396 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian217af242010-07-20 20:30:03 +0000397 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000398 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian217af242010-07-20 20:30:03 +0000399 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
400 }
401
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000402 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000403 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000404 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000405 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
406 CGM.PtrDiffTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000407 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000408 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000409 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
410 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000411
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000412 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
413 llvm::Constant *GcMemmoveCollectableFn() {
414 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000415 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
John McCall9dc0db22011-05-15 01:53:33 +0000416 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000417 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
418 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000419
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000420 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000421 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000422 // id objc_assign_strongCast(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000423 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000424 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000425 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000426 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
427 }
Anders Carlsson9ab53d12009-02-16 22:59:18 +0000428
429 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000430 llvm::Constant *getExceptionThrowFn() {
431 // void objc_exception_throw(id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000432 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000433 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000434 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000435 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
436 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000437
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000438 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
439 llvm::Constant *getExceptionRethrowFn() {
440 // void objc_exception_rethrow(void)
John McCall9dc0db22011-05-15 01:53:33 +0000441 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000442 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
443 }
444
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000445 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerdcceee72009-04-06 16:53:45 +0000446 llvm::Constant *getSyncEnterFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000447 // int objc_sync_enter (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000448 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerdcceee72009-04-06 16:53:45 +0000449 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000450 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000451 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
452 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000453
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000454 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000455 llvm::Constant *getSyncExitFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000456 // int objc_sync_exit (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000457 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000458 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000459 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000460 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
461 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000462
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000463 llvm::Constant *getSendFn(bool IsSuper) const {
464 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
465 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000466
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000467 llvm::Constant *getSendFn2(bool IsSuper) const {
468 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
469 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000470
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000471 llvm::Constant *getSendStretFn(bool IsSuper) const {
472 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
473 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000474
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000475 llvm::Constant *getSendStretFn2(bool IsSuper) const {
476 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
477 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000478
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000479 llvm::Constant *getSendFpretFn(bool IsSuper) const {
480 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
481 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000482
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000483 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
484 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
485 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000486
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000487 llvm::Constant *getSendFp2retFn(bool IsSuper) const {
488 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
489 }
490
491 llvm::Constant *getSendFp2RetFn2(bool IsSuper) const {
492 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
493 }
494
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000495 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000496};
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000497
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000498/// ObjCTypesHelper - Helper class that encapsulates lazy
499/// construction of varies types used during ObjC generation.
500class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000501public:
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000502 /// SymtabTy - LLVM type for struct objc_symtab.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000503 llvm::StructType *SymtabTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000504 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
John McCall176f8922016-11-30 02:39:18 +0000505 llvm::PointerType *SymtabPtrTy;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000506 /// ModuleTy - LLVM type for struct objc_module.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000507 llvm::StructType *ModuleTy;
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000508
Daniel Dunbarb036db82008-08-13 03:21:16 +0000509 /// ProtocolTy - LLVM type for struct objc_protocol.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000510 llvm::StructType *ProtocolTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000511 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
John McCall176f8922016-11-30 02:39:18 +0000512 llvm::PointerType *ProtocolPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000513 /// ProtocolExtensionTy - LLVM type for struct
514 /// objc_protocol_extension.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000515 llvm::StructType *ProtocolExtensionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000516 /// ProtocolExtensionTy - LLVM type for struct
517 /// objc_protocol_extension *.
John McCall176f8922016-11-30 02:39:18 +0000518 llvm::PointerType *ProtocolExtensionPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000519 /// MethodDescriptionTy - LLVM type for struct
520 /// objc_method_description.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000521 llvm::StructType *MethodDescriptionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000522 /// MethodDescriptionListTy - LLVM type for struct
523 /// objc_method_description_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000524 llvm::StructType *MethodDescriptionListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000525 /// MethodDescriptionListPtrTy - LLVM type for struct
526 /// objc_method_description_list *.
John McCall176f8922016-11-30 02:39:18 +0000527 llvm::PointerType *MethodDescriptionListPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000528 /// ProtocolListTy - LLVM type for struct objc_property_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000529 llvm::StructType *ProtocolListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000530 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
John McCall176f8922016-11-30 02:39:18 +0000531 llvm::PointerType *ProtocolListPtrTy;
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000532 /// CategoryTy - LLVM type for struct objc_category.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000533 llvm::StructType *CategoryTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000534 /// ClassTy - LLVM type for struct objc_class.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000535 llvm::StructType *ClassTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000536 /// ClassPtrTy - LLVM type for struct objc_class *.
John McCall176f8922016-11-30 02:39:18 +0000537 llvm::PointerType *ClassPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000538 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000539 llvm::StructType *ClassExtensionTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000540 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
John McCall176f8922016-11-30 02:39:18 +0000541 llvm::PointerType *ClassExtensionPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000542 // IvarTy - LLVM type for struct objc_ivar.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000543 llvm::StructType *IvarTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000544 /// IvarListTy - LLVM type for struct objc_ivar_list.
John McCall176f8922016-11-30 02:39:18 +0000545 llvm::StructType *IvarListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000546 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
John McCall176f8922016-11-30 02:39:18 +0000547 llvm::PointerType *IvarListPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000548 /// MethodListTy - LLVM type for struct objc_method_list.
John McCall176f8922016-11-30 02:39:18 +0000549 llvm::StructType *MethodListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000550 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
John McCall176f8922016-11-30 02:39:18 +0000551 llvm::PointerType *MethodListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000552
Anders Carlsson9ff22482008-09-09 10:10:21 +0000553 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
John McCall176f8922016-11-30 02:39:18 +0000554 llvm::StructType *ExceptionDataTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000555
Anders Carlsson9ff22482008-09-09 10:10:21 +0000556 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000557 llvm::Constant *getExceptionTryEnterFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000558 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000559 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000560 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000561 "objc_exception_try_enter");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000562 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000563
564 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000565 llvm::Constant *getExceptionTryExitFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000566 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000567 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000568 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000569 "objc_exception_try_exit");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000570 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000571
572 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000573 llvm::Constant *getExceptionExtractFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000574 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000575 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000576 params, false),
Chris Lattnerc6406db2009-04-22 02:26:14 +0000577 "objc_exception_extract");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000578 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000579
Anders Carlsson9ff22482008-09-09 10:10:21 +0000580 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000581 llvm::Constant *getExceptionMatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000582 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000583 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000584 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000585 "objc_exception_match");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000586 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000587
Anders Carlsson9ff22482008-09-09 10:10:21 +0000588 /// SetJmpFn - LLVM _setjmp function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000589 llvm::Constant *getSetJmpFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000590 // This is specifically the prototype for x86.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000591 llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
Bill Wendling8594fcb2013-01-31 00:30:05 +0000592 return
593 CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty,
594 params, false),
595 "_setjmp",
596 llvm::AttributeSet::get(CGM.getLLVMContext(),
597 llvm::AttributeSet::FunctionIndex,
598 llvm::Attribute::NonLazyBind));
Chris Lattnerc6406db2009-04-22 02:26:14 +0000599 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000600
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000601public:
602 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000603};
604
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000605/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000606/// modern abi
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000607class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000608public:
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000609 // MethodListnfABITy - LLVM for struct _method_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000610 llvm::StructType *MethodListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000611
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000612 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
John McCall176f8922016-11-30 02:39:18 +0000613 llvm::PointerType *MethodListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000614
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000615 // ProtocolnfABITy = LLVM for struct _protocol_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000616 llvm::StructType *ProtocolnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000617
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000618 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
John McCall176f8922016-11-30 02:39:18 +0000619 llvm::PointerType *ProtocolnfABIPtrTy;
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000620
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000621 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
Chris Lattnera5f58b02011-07-09 17:41:47 +0000622 llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000623
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000624 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
John McCall176f8922016-11-30 02:39:18 +0000625 llvm::PointerType *ProtocolListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000626
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000627 // ClassnfABITy - LLVM for struct _class_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000628 llvm::StructType *ClassnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000629
Fariborz Jahanian71394042009-01-23 23:53:38 +0000630 // ClassnfABIPtrTy - LLVM for struct _class_t*
John McCall176f8922016-11-30 02:39:18 +0000631 llvm::PointerType *ClassnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000632
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000633 // IvarnfABITy - LLVM for struct _ivar_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000634 llvm::StructType *IvarnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000635
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000636 // IvarListnfABITy - LLVM for struct _ivar_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000637 llvm::StructType *IvarListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000638
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000639 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
John McCall176f8922016-11-30 02:39:18 +0000640 llvm::PointerType *IvarListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000641
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000642 // ClassRonfABITy - LLVM for struct _class_ro_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000643 llvm::StructType *ClassRonfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000644
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000645 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
John McCall176f8922016-11-30 02:39:18 +0000646 llvm::PointerType *ImpnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000647
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000648 // CategorynfABITy - LLVM for struct _category_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000649 llvm::StructType *CategorynfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000650
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000651 // New types for nonfragile abi messaging.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000652
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000653 // MessageRefTy - LLVM for:
654 // struct _message_ref_t {
655 // IMP messenger;
656 // SEL name;
657 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000658 llvm::StructType *MessageRefTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000659 // MessageRefCTy - clang type for struct _message_ref_t
660 QualType MessageRefCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000661
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000662 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000663 llvm::Type *MessageRefPtrTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000664 // MessageRefCPtrTy - clang type for struct _message_ref_t*
665 QualType MessageRefCPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000666
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000667 // SuperMessageRefTy - LLVM for:
668 // struct _super_message_ref_t {
669 // SUPER_IMP messenger;
670 // SEL name;
671 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000672 llvm::StructType *SuperMessageRefTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000673
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000674 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
John McCall176f8922016-11-30 02:39:18 +0000675 llvm::PointerType *SuperMessageRefPtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000676
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000677 llvm::Constant *getMessageSendFixupFn() {
678 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000679 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000680 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000681 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000682 "objc_msgSend_fixup");
683 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000684
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000685 llvm::Constant *getMessageSendFpretFixupFn() {
686 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000687 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000688 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000689 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000690 "objc_msgSend_fpret_fixup");
691 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000692
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000693 llvm::Constant *getMessageSendStretFixupFn() {
694 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000695 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000696 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000697 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000698 "objc_msgSend_stret_fixup");
699 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000700
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000701 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000702 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000703 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000704 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000705 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000706 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000707 "objc_msgSendSuper2_fixup");
708 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000709
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000710 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000711 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000712 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000713 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000714 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000715 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000716 "objc_msgSendSuper2_stret_fixup");
717 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000718
Chris Lattnera7c00b42009-04-22 02:15:23 +0000719 llvm::Constant *getObjCEndCatchFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000720 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000721 "objc_end_catch");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000722
Chris Lattnera7c00b42009-04-22 02:15:23 +0000723 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000724
Chris Lattnera7c00b42009-04-22 02:15:23 +0000725 llvm::Constant *getObjCBeginCatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000726 llvm::Type *params[] = { Int8PtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000727 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000728 params, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000729 "objc_begin_catch");
730 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +0000731
Chris Lattnera5f58b02011-07-09 17:41:47 +0000732 llvm::StructType *EHTypeTy;
733 llvm::Type *EHTypePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000734
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000735 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000736};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000737
Saleem Abdulrasool271106c2016-09-16 23:41:13 +0000738enum class ObjCLabelType {
739 ClassName,
740 MethodVarName,
741 MethodVarType,
742 PropertyName,
743};
744
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000745class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000746public:
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000747 class SKIP_SCAN {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000748 public:
749 unsigned skip;
750 unsigned scan;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000751 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000752 : skip(_skip), scan(_scan) {}
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000753 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000754
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000755 /// opcode for captured block variables layout 'instructions'.
756 /// In the following descriptions, 'I' is the value of the immediate field.
757 /// (field following the opcode).
758 ///
759 enum BLOCK_LAYOUT_OPCODE {
760 /// An operator which affects how the following layout should be
761 /// interpreted.
762 /// I == 0: Halt interpretation and treat everything else as
763 /// a non-pointer. Note that this instruction is equal
764 /// to '\0'.
765 /// I != 0: Currently unused.
766 BLOCK_LAYOUT_OPERATOR = 0,
767
768 /// The next I+1 bytes do not contain a value of object pointer type.
769 /// Note that this can leave the stream unaligned, meaning that
770 /// subsequent word-size instructions do not begin at a multiple of
771 /// the pointer size.
772 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
773
774 /// The next I+1 words do not contain a value of object pointer type.
775 /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
776 /// when the required skip quantity is a multiple of the pointer size.
777 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
778
779 /// The next I+1 words are __strong pointers to Objective-C
780 /// objects or blocks.
781 BLOCK_LAYOUT_STRONG = 3,
782
783 /// The next I+1 words are pointers to __block variables.
784 BLOCK_LAYOUT_BYREF = 4,
785
786 /// The next I+1 words are __weak pointers to Objective-C
787 /// objects or blocks.
788 BLOCK_LAYOUT_WEAK = 5,
789
790 /// The next I+1 words are __unsafe_unretained pointers to
791 /// Objective-C objects or blocks.
792 BLOCK_LAYOUT_UNRETAINED = 6
793
794 /// The next I+1 words are block or object pointers with some
795 /// as-yet-unspecified ownership semantics. If we add more
796 /// flavors of ownership semantics, values will be taken from
797 /// this range.
798 ///
799 /// This is included so that older tools can at least continue
800 /// processing the layout past such things.
801 //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
802
803 /// All other opcodes are reserved. Halt interpretation and
804 /// treat everything else as opaque.
805 };
806
807 class RUN_SKIP {
808 public:
809 enum BLOCK_LAYOUT_OPCODE opcode;
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000810 CharUnits block_var_bytepos;
811 CharUnits block_var_size;
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000812 RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000813 CharUnits BytePos = CharUnits::Zero(),
814 CharUnits Size = CharUnits::Zero())
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +0000815 : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000816
817 // Allow sorting based on byte pos.
818 bool operator<(const RUN_SKIP &b) const {
819 return block_var_bytepos < b.block_var_bytepos;
820 }
821 };
822
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000823protected:
Owen Andersonae86c192009-07-13 04:10:07 +0000824 llvm::LLVMContext &VMContext;
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000825 // FIXME! May not be needing this after all.
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000826 unsigned ObjCABI;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000827
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000828 // arc/mrr layout of captured block literal variables.
829 SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000830
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000831 /// LazySymbols - Symbols to generate a lazy reference for. See
832 /// DefinedSymbols and FinishModule().
Daniel Dunbard027a922009-09-07 00:20:42 +0000833 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000834
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000835 /// DefinedSymbols - External symbols which are defined by this
836 /// module. The symbols in this list and LazySymbols are used to add
837 /// special linker symbols which ensure that Objective-C modules are
838 /// linked properly.
Daniel Dunbard027a922009-09-07 00:20:42 +0000839 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000840
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000841 /// ClassNames - uniqued class names.
Fariborz Jahanian451b92a2014-07-16 16:16:04 +0000842 llvm::StringMap<llvm::GlobalVariable*> ClassNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000843
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000844 /// MethodVarNames - uniqued method variable names.
845 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000846
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000847 /// DefinedCategoryNames - list of category names in form Class_Category.
Justin Lebar5e83dfe2016-10-21 21:45:01 +0000848 llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames;
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000849
Daniel Dunbarb036db82008-08-13 03:21:16 +0000850 /// MethodVarTypes - uniqued method type signatures. We have to use
851 /// a StringMap here because have no other unique reference.
852 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000853
Daniel Dunbar3c76cb52008-08-26 21:51:14 +0000854 /// MethodDefinitions - map of methods which have been defined in
855 /// this translation unit.
856 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000857
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000858 /// PropertyNames - uniqued method variable names.
859 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000860
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000861 /// ClassReferences - uniqued class references.
862 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000863
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000864 /// SelectorReferences - uniqued selector references.
865 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000866
Daniel Dunbarb036db82008-08-13 03:21:16 +0000867 /// Protocols - Protocols for which an objc_protocol structure has
868 /// been emitted. Forward declarations are handled by creating an
869 /// empty structure whose initializer is filled in when/if defined.
870 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000871
Daniel Dunbarc475d422008-10-29 22:36:39 +0000872 /// DefinedProtocols - Protocols which have actually been
873 /// defined. We should not need this, see FIXME in GenerateProtocol.
874 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000875
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000876 /// DefinedClasses - List of defined classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000877 SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +0000878
879 /// ImplementedClasses - List of @implemented classes.
880 SmallVector<const ObjCInterfaceDecl*, 16> ImplementedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000881
882 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000883 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000884
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000885 /// DefinedCategories - List of defined categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000886 SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000887
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000888 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000889 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000890
John McCallcd21d542016-11-30 23:15:55 +0000891 /// Cached reference to the class for constant strings. This value has type
892 /// int * but is actually an Obj-C class pointer.
893 llvm::WeakVH ConstantStringClassRef;
894
895 /// \brief The LLVM type corresponding to NSConstantString.
896 llvm::StructType *NSConstantStringType = nullptr;
897
898 llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
899
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000900 /// GetNameForMethod - Return a name for the given method.
901 /// \param[out] NameOut - The return value.
902 void GetNameForMethod(const ObjCMethodDecl *OMD,
903 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000904 SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000905
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000906 /// GetMethodVarName - Return a unique constant for the given
907 /// selector's name. The return value has type char *.
908 llvm::Constant *GetMethodVarName(Selector Sel);
909 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000910
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000911 /// GetMethodVarType - Return a unique constant for the given
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000912 /// method's type encoding string. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000913
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000914 // FIXME: This is a horrible name.
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000915 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
916 bool Extended = false);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000917 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000918
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000919 /// GetPropertyName - Return a unique constant for the given
920 /// name. The return value has type char *.
921 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000922
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000923 // FIXME: This can be dropped once string functions are unified.
924 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
925 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000926
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000927 /// GetClassName - Return a unique constant for the given selector's
Fariborz Jahanian451b92a2014-07-16 16:16:04 +0000928 /// runtime name (which may change via use of objc_runtime_name attribute on
929 /// class or protocol definition. The return value has type char *.
930 llvm::Constant *GetClassName(StringRef RuntimeName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000931
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000932 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
933
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000934 /// BuildIvarLayout - Builds ivar layout bitmap for the class
935 /// implementation for the __strong or __weak case.
936 ///
John McCall460ce582015-10-22 18:38:17 +0000937 /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there
938 /// are any weak ivars defined directly in the class. Meaningless unless
939 /// building a weak layout. Does not guarantee that the layout will
940 /// actually have any entries, because the ivar might be under-aligned.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000941 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
John McCall3fd13f062015-10-21 18:06:47 +0000942 CharUnits beginOffset,
943 CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +0000944 bool forStrongLayout,
945 bool hasMRCWeakIvars);
946
947 llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI,
948 CharUnits beginOffset,
949 CharUnits endOffset) {
950 return BuildIvarLayout(OI, beginOffset, endOffset, true, false);
951 }
952
953 llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI,
954 CharUnits beginOffset,
955 CharUnits endOffset,
956 bool hasMRCWeakIvars) {
957 return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
958 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +0000959
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000960 Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
Fariborz Jahanian2dd78192012-11-02 22:51:18 +0000961
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000962 void UpdateRunSkipBlockVars(bool IsByref,
963 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000964 CharUnits FieldOffset,
965 CharUnits FieldSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000966
967 void BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000968 CharUnits BytePos, bool &HasUnion,
969 bool ByrefLayout=false);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000970
971 void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
972 const RecordDecl *RD,
973 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000974 CharUnits BytePos, bool &HasUnion,
975 bool ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000976
Fariborz Jahanian23290b02012-11-01 18:32:55 +0000977 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
978
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000979 llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
980
Fariborz Jahanian01dff422009-03-05 19:17:31 +0000981 /// GetIvarLayoutName - Returns a unique constant for the given
982 /// ivar layout bitmap.
983 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
984 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000985
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000986 /// EmitPropertyList - Emit the given property list. The return
987 /// value has type PropertyListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000988 llvm::Constant *EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000989 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000990 const ObjCContainerDecl *OCD,
Manman Renad0e7912016-01-29 19:22:54 +0000991 const ObjCCommonTypesHelper &ObjCTypes,
992 bool IsClassProperty);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000993
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000994 /// EmitProtocolMethodTypes - Generate the array of extended method type
995 /// strings. The return value has type Int8PtrPtrTy.
996 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +0000997 ArrayRef<llvm::Constant*> MethodTypes,
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000998 const ObjCCommonTypesHelper &ObjCTypes);
999
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001000 /// GetProtocolRef - Return a reference to the internal protocol
1001 /// description, creating an empty one if it has not been
1002 /// defined. The return value has type ProtocolPtrTy.
1003 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +00001004
Douglas Gregor24ae22c2016-04-01 23:23:52 +00001005 /// Return a reference to the given Class using runtime calls rather than
1006 /// by a symbol reference.
1007 llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
1008 const ObjCInterfaceDecl *ID,
1009 ObjCCommonTypesHelper &ObjCTypes);
1010
John McCall3fd13f062015-10-21 18:06:47 +00001011public:
Daniel Dunbar30c65362009-03-09 20:09:19 +00001012 /// CreateMetadataVar - Create a global variable with internal
1013 /// linkage for use by the Objective-C runtime.
1014 ///
1015 /// This is a convenience wrapper which not only creates the
1016 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +00001017 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001018 ///
1019 /// \param Name - The variable name.
1020 /// \param Init - The variable initializer; this is also used to
John McCall176f8922016-11-30 02:39:18 +00001021 /// define the type of the variable.
Alp Toker541d5072014-06-07 23:30:53 +00001022 /// \param Section - The section the variable should go into, or empty.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001023 /// \param Align - The alignment for the variable, or 0.
1024 /// \param AddToUsed - Whether the variable should be added to
John McCall176f8922016-11-30 02:39:18 +00001025 /// "llvm.used".
1026 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1027 ConstantStructBuilder &Init,
1028 StringRef Section, CharUnits Align,
1029 bool AddToUsed);
1030 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1031 llvm::Constant *Init,
John McCall7f416cc2015-09-08 08:05:57 +00001032 StringRef Section, CharUnits Align,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001033 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +00001034
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001035 llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00001036 ObjCLabelType LabelType,
1037 bool ForceNonFragileABI = false,
1038 bool NullTerminate = true);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001039
John McCall3fd13f062015-10-21 18:06:47 +00001040protected:
John McCall9e8bb002011-05-14 03:10:52 +00001041 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1042 ReturnValueSlot Return,
1043 QualType ResultType,
1044 llvm::Value *Sel,
1045 llvm::Value *Arg0,
1046 QualType Arg0Ty,
1047 bool IsSuper,
1048 const CallArgList &CallArgs,
1049 const ObjCMethodDecl *OMD,
John McCall1e3157b2015-09-10 22:27:50 +00001050 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00001051 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +00001052
Daniel Dunbar5e639272010-04-25 20:39:01 +00001053 /// EmitImageInfo - Emit the image info marker used to encode some module
1054 /// level information.
1055 void EmitImageInfo();
1056
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001057public:
Owen Andersonae86c192009-07-13 04:10:07 +00001058 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
John McCalla729c622012-02-17 03:33:10 +00001059 CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001060
John McCall3fd13f062015-10-21 18:06:47 +00001061 bool isNonFragileABI() const {
1062 return ObjCABI == 2;
1063 }
1064
John McCall7f416cc2015-09-08 08:05:57 +00001065 ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
John McCallcd21d542016-11-30 23:15:55 +00001066 ConstantAddress GenerateConstantNSString(const StringLiteral *SL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001067
Craig Topper4f12f102014-03-12 06:41:41 +00001068 llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
Craig Topper8a13c412014-05-21 05:09:00 +00001069 const ObjCContainerDecl *CD=nullptr) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001070
1071 void GenerateProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001072
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001073 /// GetOrEmitProtocol - Get the protocol object for the given
1074 /// declaration, emitting it if necessary. The return value has type
1075 /// ProtocolPtrTy.
1076 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001077
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001078 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1079 /// object for the given declaration, emitting it if needed. These
1080 /// forward references will be filled in with empty bodies if no
1081 /// definition is seen. The return value has type ProtocolPtrTy.
1082 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCallcd21d542016-11-30 23:15:55 +00001083
1084 virtual llvm::Constant *getNSConstantStringClassRef() = 0;
1085
Craig Topper4f12f102014-03-12 06:41:41 +00001086 llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1087 const CGBlockInfo &blockInfo) override;
1088 llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1089 const CGBlockInfo &blockInfo) override;
1090
1091 llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1092 QualType T) override;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001093};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001094
John McCall176f8922016-11-30 02:39:18 +00001095namespace {
1096
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001097enum class MethodListType {
1098 CategoryInstanceMethods,
1099 CategoryClassMethods,
1100 InstanceMethods,
1101 ClassMethods,
1102 ProtocolInstanceMethods,
1103 ProtocolClassMethods,
1104 OptionalProtocolInstanceMethods,
1105 OptionalProtocolClassMethods,
1106};
1107
John McCall176f8922016-11-30 02:39:18 +00001108/// A convenience class for splitting the methods of a protocol into
1109/// the four interesting groups.
1110class ProtocolMethodLists {
1111public:
1112 enum Kind {
1113 RequiredInstanceMethods,
1114 RequiredClassMethods,
1115 OptionalInstanceMethods,
1116 OptionalClassMethods
1117 };
1118 enum {
1119 NumProtocolMethodLists = 4
1120 };
1121
1122 static MethodListType getMethodListKind(Kind kind) {
1123 switch (kind) {
1124 case RequiredInstanceMethods:
1125 return MethodListType::ProtocolInstanceMethods;
1126 case RequiredClassMethods:
1127 return MethodListType::ProtocolClassMethods;
1128 case OptionalInstanceMethods:
1129 return MethodListType::OptionalProtocolInstanceMethods;
1130 case OptionalClassMethods:
1131 return MethodListType::OptionalProtocolClassMethods;
1132 }
1133 llvm_unreachable("bad kind");
1134 }
1135
1136 SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];
1137
1138 static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
1139 ProtocolMethodLists result;
1140
1141 for (auto MD : PD->methods()) {
1142 size_t index = (2 * size_t(MD->isOptional()))
1143 + (size_t(MD->isClassMethod()));
1144 result.Methods[index].push_back(MD);
1145 }
1146
1147 return result;
1148 }
1149
1150 template <class Self>
1151 SmallVector<llvm::Constant*, 8> emitExtendedTypesArray(Self *self) const {
1152 // In both ABIs, the method types list is parallel with the
1153 // concatenation of the methods arrays in the following order:
1154 // instance methods
1155 // class methods
1156 // optional instance methods
1157 // optional class methods
1158 SmallVector<llvm::Constant*, 8> result;
1159
1160 // Methods is already in the correct order for both ABIs.
1161 for (auto &list : Methods) {
1162 for (auto MD : list) {
1163 result.push_back(self->GetMethodVarType(MD, true));
1164 }
1165 }
1166
1167 return result;
1168 }
1169
1170 template <class Self>
1171 llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD,
1172 Kind kind) const {
1173 return self->emitMethodList(PD->getObjCRuntimeNameAsString(),
1174 getMethodListKind(kind), Methods[kind]);
1175 }
1176};
1177
1178} // end anonymous namespace
1179
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001180class CGObjCMac : public CGObjCCommonMac {
1181private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001182 friend ProtocolMethodLists;
John McCall176f8922016-11-30 02:39:18 +00001183
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001184 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001185
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001186 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001187 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001188 void EmitModuleInfo();
1189
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001190 /// EmitModuleSymols - Emit module symbols, the list of defined
1191 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001192 llvm::Constant *EmitModuleSymbols();
1193
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001194 /// FinishModule - Write out global data structures at the end of
1195 /// processing a translation unit.
1196 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +00001197
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001198 /// EmitClassExtension - Generate the class extension structure used
1199 /// to store the weak ivar layout and properties. The return value
1200 /// has type ClassExtensionPtrTy.
John McCall3fd13f062015-10-21 18:06:47 +00001201 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
John McCall460ce582015-10-22 18:38:17 +00001202 CharUnits instanceSize,
Manman Renad0e7912016-01-29 19:22:54 +00001203 bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00001204 bool isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001205
1206 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1207 /// for the given class.
John McCall882987f2013-02-28 19:01:20 +00001208 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001209 const ObjCInterfaceDecl *ID);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001210
John McCall882987f2013-02-28 19:01:20 +00001211 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00001212 IdentifierInfo *II);
Craig Topper4f12f102014-03-12 06:41:41 +00001213
1214 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
1215
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001216 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1217 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001218
1219 /// EmitIvarList - Emit the ivar list for the given
1220 /// implementation. If ForClass is true the list of class ivars
1221 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1222 /// interface ivars will be emitted. The return value has type
1223 /// IvarListPtrTy.
1224 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00001225 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001226
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001227 /// EmitMetaClass - Emit a forward reference to the class structure
1228 /// for the metaclass of the given interface. The return value has
1229 /// type ClassPtrTy.
1230 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1231
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001232 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001233 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001234 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1235 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00001236 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001237
John McCall176f8922016-11-30 02:39:18 +00001238 void emitMethodConstant(ConstantArrayBuilder &builder,
1239 const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001240
John McCall176f8922016-11-30 02:39:18 +00001241 void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
1242 const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001243
1244 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +00001245 /// implementation. The return value has type MethodListPtrTy.
John McCall176f8922016-11-30 02:39:18 +00001246 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1247 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001248
Daniel Dunbarc475d422008-10-29 22:36:39 +00001249 /// GetOrEmitProtocol - Get the protocol object for the given
1250 /// declaration, emitting it if necessary. The return value has type
1251 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001252 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001253
1254 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1255 /// object for the given declaration, emitting it if needed. These
1256 /// forward references will be filled in with empty bodies if no
1257 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001258 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001259
Daniel Dunbarb036db82008-08-13 03:21:16 +00001260 /// EmitProtocolExtension - Generate the protocol extension
1261 /// structure used to store optional instance and class methods, and
1262 /// protocol properties. The return value has type
1263 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001264 llvm::Constant *
1265 EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00001266 const ProtocolMethodLists &methodLists);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001267
1268 /// EmitProtocolList - Generate the list of referenced
1269 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001270 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001271 ObjCProtocolDecl::protocol_iterator begin,
1272 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001273
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001274 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1275 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001276 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1277 Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001278
1279public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001280 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001281
John McCallcd21d542016-11-30 23:15:55 +00001282 llvm::Constant *getNSConstantStringClassRef() override;
1283
Craig Topper4f12f102014-03-12 06:41:41 +00001284 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001285
Craig Topper4f12f102014-03-12 06:41:41 +00001286 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1287 ReturnValueSlot Return,
1288 QualType ResultType,
1289 Selector Sel, llvm::Value *Receiver,
1290 const CallArgList &CallArgs,
1291 const ObjCInterfaceDecl *Class,
1292 const ObjCMethodDecl *Method) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001293
Craig Topper4f12f102014-03-12 06:41:41 +00001294 CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001295 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001296 ReturnValueSlot Return, QualType ResultType,
1297 Selector Sel, const ObjCInterfaceDecl *Class,
1298 bool isCategoryImpl, llvm::Value *Receiver,
1299 bool IsClassMessage, const CallArgList &CallArgs,
1300 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001301
Craig Topper4f12f102014-03-12 06:41:41 +00001302 llvm::Value *GetClass(CodeGenFunction &CGF,
1303 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001304
John McCall7f416cc2015-09-08 08:05:57 +00001305 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
1306 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001307
1308 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1309 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001310 llvm::Value *GetSelector(CodeGenFunction &CGF,
1311 const ObjCMethodDecl *Method) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001312
Craig Topper4f12f102014-03-12 06:41:41 +00001313 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001314
Craig Topper4f12f102014-03-12 06:41:41 +00001315 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001316
Craig Topper4f12f102014-03-12 06:41:41 +00001317 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001318
Craig Topper4f12f102014-03-12 06:41:41 +00001319 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001320
Craig Topper4f12f102014-03-12 06:41:41 +00001321 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1322 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001323
Craig Topper4f12f102014-03-12 06:41:41 +00001324 llvm::Constant *GetPropertyGetFunction() override;
1325 llvm::Constant *GetPropertySetFunction() override;
1326 llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1327 bool copy) override;
1328 llvm::Constant *GetGetStructFunction() override;
1329 llvm::Constant *GetSetStructFunction() override;
1330 llvm::Constant *GetCppAtomicObjectGetFunction() override;
1331 llvm::Constant *GetCppAtomicObjectSetFunction() override;
1332 llvm::Constant *EnumerationMutationFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001333
Craig Topper4f12f102014-03-12 06:41:41 +00001334 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1335 const ObjCAtTryStmt &S) override;
1336 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1337 const ObjCAtSynchronizedStmt &S) override;
John McCallbd309292010-07-06 01:34:17 +00001338 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Craig Topper4f12f102014-03-12 06:41:41 +00001339 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1340 bool ClearInsertionPoint=true) override;
1341 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001342 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001343 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001344 llvm::Value *src, Address dst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001345 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001346 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001347 bool threadlocal = false) override;
1348 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001349 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001350 llvm::Value *ivarOffset) override;
1351 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001352 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001353 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001354 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001355 llvm::Value *size) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001356
Craig Topper4f12f102014-03-12 06:41:41 +00001357 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1358 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1359 unsigned CVRQualifiers) override;
1360 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1361 const ObjCInterfaceDecl *Interface,
1362 const ObjCIvarDecl *Ivar) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001363};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001364
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001365class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001366private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001367 friend ProtocolMethodLists;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001368 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001369 llvm::GlobalVariable* ObjCEmptyCacheVar;
John McCall176f8922016-11-30 02:39:18 +00001370 llvm::Constant* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001371
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001372 /// SuperClassReferences - uniqued super class references.
1373 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001374
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001375 /// MetaClassReferences - uniqued meta class references.
1376 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001377
1378 /// EHTypeReferences - uniqued class ehtype references.
1379 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001380
John McCall9e8bb002011-05-14 03:10:52 +00001381 /// VTableDispatchMethods - List of methods for which we generate
1382 /// vtable-based message dispatch.
1383 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001384
Fariborz Jahanian67260552009-11-17 21:37:35 +00001385 /// DefinedMetaClasses - List of defined meta-classes.
1386 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1387
John McCall9e8bb002011-05-14 03:10:52 +00001388 /// isVTableDispatchedSelector - Returns true if SEL is a
1389 /// vtable-based selector.
1390 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001391
Fariborz Jahanian71394042009-01-23 23:53:38 +00001392 /// FinishNonFragileABIModule - Write out global data structures at the end of
1393 /// processing a translation unit.
1394 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001395
Daniel Dunbar19573e72009-05-15 21:48:48 +00001396 /// AddModuleClassList - Add the given list of class pointers to the
1397 /// module with the provided symbol and section names.
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001398 void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container,
1399 StringRef SymbolName, StringRef SectionName);
Daniel Dunbar19573e72009-05-15 21:48:48 +00001400
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001401 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1402 unsigned InstanceStart,
1403 unsigned InstanceSize,
1404 const ObjCImplementationDecl *ID);
John McCalldba63a72016-11-30 23:54:50 +00001405 llvm::GlobalVariable *BuildClassObject(const ObjCInterfaceDecl *CI,
1406 bool isMetaclass,
1407 llvm::Constant *IsAGV,
1408 llvm::Constant *SuperClassGV,
1409 llvm::Constant *ClassRoGV,
1410 bool HiddenVisibility);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001411
John McCall176f8922016-11-30 02:39:18 +00001412 void emitMethodConstant(ConstantArrayBuilder &builder,
1413 const ObjCMethodDecl *MD,
1414 bool forProtocol);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001415
John McCall176f8922016-11-30 02:39:18 +00001416 /// Emit the method list for the given implementation. The return value
1417 /// has type MethodListnfABITy.
1418 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1419 ArrayRef<const ObjCMethodDecl *> Methods);
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001420
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001421 /// EmitIvarList - Emit the ivar list for the given
1422 /// implementation. If ForClass is true the list of class ivars
1423 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1424 /// interface ivars will be emitted. The return value has type
1425 /// IvarListnfABIPtrTy.
1426 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001427
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001428 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001429 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00001430 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001431
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001432 /// GetOrEmitProtocol - Get the protocol object for the given
1433 /// declaration, emitting it if necessary. The return value has type
1434 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001435 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001436
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001437 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1438 /// object for the given declaration, emitting it if needed. These
1439 /// forward references will be filled in with empty bodies if no
1440 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001441 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001442
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001443 /// EmitProtocolList - Generate the list of referenced
1444 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001445 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001446 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001447 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001448
John McCall9e8bb002011-05-14 03:10:52 +00001449 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1450 ReturnValueSlot Return,
1451 QualType ResultType,
1452 Selector Sel,
1453 llvm::Value *Receiver,
1454 QualType Arg0Ty,
1455 bool IsSuper,
1456 const CallArgList &CallArgs,
1457 const ObjCMethodDecl *Method);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001458
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001459 /// GetClassGlobal - Return the global variable for the Objective-C
1460 /// class of the given name.
John McCalldba63a72016-11-30 23:54:50 +00001461 llvm::Constant *GetClassGlobal(StringRef Name,
1462 ForDefinition_t IsForDefinition,
1463 bool Weak = false, bool DLLImport = false);
1464 llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID,
1465 bool isMetaclass,
1466 ForDefinition_t isForDefinition);
Rafael Espindola554256c2014-02-26 22:25:45 +00001467
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001468 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001469 /// for the given class reference.
John McCall882987f2013-02-28 19:01:20 +00001470 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001471 const ObjCInterfaceDecl *ID);
John McCall31168b02011-06-15 23:02:42 +00001472
John McCall882987f2013-02-28 19:01:20 +00001473 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
John McCalldba63a72016-11-30 23:54:50 +00001474 IdentifierInfo *II,
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00001475 const ObjCInterfaceDecl *ID);
Craig Topper4f12f102014-03-12 06:41:41 +00001476
1477 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001478
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001479 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1480 /// for the given super class reference.
John McCall882987f2013-02-28 19:01:20 +00001481 llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001482 const ObjCInterfaceDecl *ID);
1483
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001484 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1485 /// meta-data
John McCall882987f2013-02-28 19:01:20 +00001486 llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00001487 const ObjCInterfaceDecl *ID, bool Weak);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001488
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001489 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1490 /// the given ivar.
1491 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001492 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001493 const ObjCInterfaceDecl *ID,
1494 const ObjCIvarDecl *Ivar);
1495
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001496 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1497 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001498 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1499 Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001500
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001501 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001502 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001503 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
John McCalldba63a72016-11-30 23:54:50 +00001504 ForDefinition_t IsForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001505
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001506 StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001507
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001508 StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; }
Daniel Dunbar15894b72009-04-07 05:48:37 +00001509
Daniel Dunbar961202372009-05-03 12:57:56 +00001510 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001511 uint32_t &InstanceStart,
1512 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001513
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001514 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001515 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001516 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1517 return CGM.getContext().Selectors.getSelector(0, &II);
1518 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001519
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001520 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001521 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1522 return CGM.getContext().Selectors.getSelector(1, &II);
1523 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001524
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001525 /// ImplementationIsNonLazy - Check whether the given category or
1526 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001527 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001528
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001529 bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001530 const ObjCIvarDecl *IV) {
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001531 // Annotate the load as an invariant load iff inside an instance method
1532 // and ivar belongs to instance method's class and one of its super class.
1533 // This check is needed because the ivar offset is a lazily
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001534 // initialised value that may depend on objc_msgSend to perform a fixup on
1535 // the first message dispatch.
1536 //
1537 // An additional opportunity to mark the load as invariant arises when the
1538 // base of the ivar access is a parameter to an Objective C method.
1539 // However, because the parameters are not available in the current
1540 // interface, we cannot perform this check.
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001541 if (const ObjCMethodDecl *MD =
1542 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
Fariborz Jahanian7a583022014-03-04 22:57:32 +00001543 if (MD->isInstanceMethod())
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001544 if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
1545 return IV->getContainingInterface()->isSuperClassOf(ID);
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001546 return false;
1547 }
1548
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001549public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001550 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
John McCallcd21d542016-11-30 23:15:55 +00001551
1552 llvm::Constant *getNSConstantStringClassRef() override;
1553
Craig Topper4f12f102014-03-12 06:41:41 +00001554 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001555
Craig Topper4f12f102014-03-12 06:41:41 +00001556 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1557 ReturnValueSlot Return,
1558 QualType ResultType, Selector Sel,
1559 llvm::Value *Receiver,
1560 const CallArgList &CallArgs,
1561 const ObjCInterfaceDecl *Class,
1562 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001563
Craig Topper4f12f102014-03-12 06:41:41 +00001564 CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001565 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001566 ReturnValueSlot Return, QualType ResultType,
1567 Selector Sel, const ObjCInterfaceDecl *Class,
1568 bool isCategoryImpl, llvm::Value *Receiver,
1569 bool IsClassMessage, const CallArgList &CallArgs,
1570 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001571
Craig Topper4f12f102014-03-12 06:41:41 +00001572 llvm::Value *GetClass(CodeGenFunction &CGF,
1573 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001574
John McCall7f416cc2015-09-08 08:05:57 +00001575 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override
1576 { return EmitSelector(CGF, Sel); }
1577 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override
1578 { return EmitSelectorAddr(CGF, Sel); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001579
1580 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1581 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001582 llvm::Value *GetSelector(CodeGenFunction &CGF,
1583 const ObjCMethodDecl *Method) override
John McCall882987f2013-02-28 19:01:20 +00001584 { return EmitSelector(CGF, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001585
Craig Topper4f12f102014-03-12 06:41:41 +00001586 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001587
Craig Topper4f12f102014-03-12 06:41:41 +00001588 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
David Chisnall92d436b2012-01-31 18:59:20 +00001589
Craig Topper4f12f102014-03-12 06:41:41 +00001590 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001591
Craig Topper4f12f102014-03-12 06:41:41 +00001592 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1593 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001594
Craig Topper4f12f102014-03-12 06:41:41 +00001595 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001596
Craig Topper4f12f102014-03-12 06:41:41 +00001597 llvm::Constant *GetPropertyGetFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001598 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001599 }
Craig Topper4f12f102014-03-12 06:41:41 +00001600 llvm::Constant *GetPropertySetFunction() override {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001601 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001602 }
Craig Topper4f12f102014-03-12 06:41:41 +00001603
1604 llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1605 bool copy) override {
Ted Kremeneke65b0862012-03-06 20:05:56 +00001606 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1607 }
Craig Topper4f12f102014-03-12 06:41:41 +00001608
1609 llvm::Constant *GetSetStructFunction() override {
David Chisnall168b80f2010-12-26 22:13:16 +00001610 return ObjCTypes.getCopyStructFn();
1611 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001612
Craig Topper4f12f102014-03-12 06:41:41 +00001613 llvm::Constant *GetGetStructFunction() override {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001614 return ObjCTypes.getCopyStructFn();
1615 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001616
Craig Topper4f12f102014-03-12 06:41:41 +00001617 llvm::Constant *GetCppAtomicObjectSetFunction() override {
David Chisnall0d75e062012-12-17 18:54:24 +00001618 return ObjCTypes.getCppAtomicObjectFunction();
1619 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001620
Craig Topper4f12f102014-03-12 06:41:41 +00001621 llvm::Constant *GetCppAtomicObjectGetFunction() override {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001622 return ObjCTypes.getCppAtomicObjectFunction();
1623 }
Craig Topper4f12f102014-03-12 06:41:41 +00001624
1625 llvm::Constant *EnumerationMutationFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001626 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001627 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001628
Craig Topper4f12f102014-03-12 06:41:41 +00001629 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1630 const ObjCAtTryStmt &S) override;
1631 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1632 const ObjCAtSynchronizedStmt &S) override;
1633 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1634 bool ClearInsertionPoint=true) override;
1635 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001636 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001637 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001638 llvm::Value *src, Address edst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001639 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001640 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001641 bool threadlocal = false) override;
1642 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001643 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001644 llvm::Value *ivarOffset) override;
1645 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001646 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001647 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001648 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001649 llvm::Value *size) override;
1650 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1651 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1652 unsigned CVRQualifiers) override;
1653 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1654 const ObjCInterfaceDecl *Interface,
1655 const ObjCIvarDecl *Ivar) override;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001656};
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001657
1658/// A helper class for performing the null-initialization of a return
1659/// value.
1660struct NullReturnState {
1661 llvm::BasicBlock *NullBB;
Craig Topper8a13c412014-05-21 05:09:00 +00001662 NullReturnState() : NullBB(nullptr) {}
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001663
John McCall3d1e2c92013-02-12 05:53:35 +00001664 /// Perform a null-check of the given receiver.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001665 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
John McCall3d1e2c92013-02-12 05:53:35 +00001666 // Make blocks for the null-receiver and call edges.
1667 NullBB = CGF.createBasicBlock("msgSend.null-receiver");
1668 llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001669
1670 // Check for a null receiver and, if there is one, jump to the
John McCall3d1e2c92013-02-12 05:53:35 +00001671 // null-receiver block. There's no point in trying to avoid it:
1672 // we're always going to put *something* there, because otherwise
1673 // we shouldn't have done this null-check in the first place.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001674 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1675 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1676
1677 // Otherwise, start performing the call.
1678 CGF.EmitBlock(callBB);
1679 }
1680
John McCall3d1e2c92013-02-12 05:53:35 +00001681 /// Complete the null-return operation. It is valid to call this
1682 /// regardless of whether 'init' has been called.
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001683 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
1684 const CallArgList &CallArgs,
1685 const ObjCMethodDecl *Method) {
John McCall3d1e2c92013-02-12 05:53:35 +00001686 // If we never had to do a null-check, just use the raw result.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001687 if (!NullBB) return result;
John McCall3d1e2c92013-02-12 05:53:35 +00001688
1689 // The continuation block. This will be left null if we don't have an
1690 // IP, which can happen if the method we're calling is marked noreturn.
Craig Topper8a13c412014-05-21 05:09:00 +00001691 llvm::BasicBlock *contBB = nullptr;
1692
John McCall3d1e2c92013-02-12 05:53:35 +00001693 // Finish the call path.
1694 llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
1695 if (callBB) {
1696 contBB = CGF.createBasicBlock("msgSend.cont");
1697 CGF.Builder.CreateBr(contBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001698 }
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001699
John McCall3d1e2c92013-02-12 05:53:35 +00001700 // Okay, start emitting the null-receiver block.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001701 CGF.EmitBlock(NullBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001702
John McCall3d1e2c92013-02-12 05:53:35 +00001703 // Release any consumed arguments we've got.
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001704 if (Method) {
1705 CallArgList::const_iterator I = CallArgs.begin();
1706 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1707 e = Method->param_end(); i != e; ++i, ++I) {
1708 const ParmVarDecl *ParamDecl = (*i);
1709 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1710 RValue RV = I->RV;
1711 assert(RV.isScalar() &&
1712 "NullReturnState::complete - arg not on object");
John McCallcdda29c2013-03-13 03:10:54 +00001713 CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001714 }
1715 }
1716 }
John McCall3d1e2c92013-02-12 05:53:35 +00001717
1718 // The phi code below assumes that we haven't needed any control flow yet.
1719 assert(CGF.Builder.GetInsertBlock() == NullBB);
1720
1721 // If we've got a void return, just jump to the continuation block.
1722 if (result.isScalar() && resultType->isVoidType()) {
1723 // No jumps required if the message-send was noreturn.
1724 if (contBB) CGF.EmitBlock(contBB);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001725 return result;
1726 }
1727
John McCall3d1e2c92013-02-12 05:53:35 +00001728 // If we've got a scalar return, build a phi.
1729 if (result.isScalar()) {
1730 // Derive the null-initialization value.
1731 llvm::Constant *null = CGF.CGM.EmitNullConstant(resultType);
1732
1733 // If no join is necessary, just flow out.
1734 if (!contBB) return RValue::get(null);
1735
1736 // Otherwise, build a phi.
1737 CGF.EmitBlock(contBB);
1738 llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2);
1739 phi->addIncoming(result.getScalarVal(), callBB);
1740 phi->addIncoming(null, NullBB);
1741 return RValue::get(phi);
1742 }
1743
1744 // If we've got an aggregate return, null the buffer out.
1745 // FIXME: maybe we should be doing things differently for all the
1746 // cases where the ABI has us returning (1) non-agg values in
1747 // memory or (2) agg values in registers.
1748 if (result.isAggregate()) {
1749 assert(result.isAggregate() && "null init of non-aggregate result?");
John McCall7f416cc2015-09-08 08:05:57 +00001750 CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
John McCall3d1e2c92013-02-12 05:53:35 +00001751 if (contBB) CGF.EmitBlock(contBB);
1752 return result;
1753 }
1754
1755 // Complex types.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001756 CGF.EmitBlock(contBB);
John McCall3d1e2c92013-02-12 05:53:35 +00001757 CodeGenFunction::ComplexPairTy callResult = result.getComplexVal();
1758
1759 // Find the scalar type and its zero value.
1760 llvm::Type *scalarTy = callResult.first->getType();
1761 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1762
1763 // Build phis for both coordinates.
1764 llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2);
1765 real->addIncoming(callResult.first, callBB);
1766 real->addIncoming(scalarZero, NullBB);
1767 llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2);
1768 imag->addIncoming(callResult.second, callBB);
1769 imag->addIncoming(scalarZero, NullBB);
1770 return RValue::getComplex(real, imag);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001771 }
1772};
1773
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001774} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001775
1776/* *** Helper Functions *** */
1777
1778/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001779static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
David Blaikiee3b172a2015-04-02 18:55:21 +00001780 llvm::GlobalVariable *C, unsigned idx0,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001781 unsigned idx1) {
1782 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001783 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1784 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001785 };
David Blaikiee3b172a2015-04-02 18:55:21 +00001786 return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001787}
1788
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001789/// hasObjCExceptionAttribute - Return true if this class or any super
1790/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001791static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001792 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001793 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001794 return true;
1795 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001796 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001797 return false;
1798}
1799
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001800/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001801
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001802CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001803 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001804 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001805 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001806}
1807
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001808/// GetClass - Return a reference to the class for the given interface
1809/// decl.
John McCall882987f2013-02-28 19:01:20 +00001810llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001811 const ObjCInterfaceDecl *ID) {
John McCall882987f2013-02-28 19:01:20 +00001812 return EmitClassRef(CGF, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001813}
1814
1815/// GetSelector - Return the pointer to the unique'd string for this selector.
John McCall7f416cc2015-09-08 08:05:57 +00001816llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
1817 return EmitSelector(CGF, Sel);
1818}
1819Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
1820 return EmitSelectorAddr(CGF, Sel);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001821}
John McCall882987f2013-02-28 19:01:20 +00001822llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001823 *Method) {
John McCall882987f2013-02-28 19:01:20 +00001824 return EmitSelector(CGF, Method->getSelector());
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001825}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001826
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001827llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001828 if (T->isObjCIdType() ||
1829 T->isObjCQualifiedIdType()) {
1830 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001831 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001832 }
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001833 if (T->isObjCClassType() ||
1834 T->isObjCQualifiedClassType()) {
1835 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001836 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001837 }
1838 if (T->isObjCObjectPointerType())
1839 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
1840
John McCall2ca705e2010-07-24 00:37:23 +00001841 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall2ca705e2010-07-24 00:37:23 +00001842}
1843
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001844/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001845/*
1846 struct __builtin_CFString {
1847 const int *isa; // point to __CFConstantStringClassReference
1848 int flags;
1849 const char *str;
1850 long length;
1851 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001852*/
1853
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001854/// or Generate a constant NSString object.
1855/*
1856 struct __builtin_NSString {
1857 const int *isa; // point to __NSConstantStringClassReference
1858 const char *str;
1859 unsigned int length;
1860 };
1861*/
1862
John McCallcd21d542016-11-30 23:15:55 +00001863ConstantAddress
1864CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) {
1865 return (!CGM.getLangOpts().NoConstantCFStrings
1866 ? CGM.GetAddrOfConstantCFString(SL)
1867 : GenerateConstantNSString(SL));
1868}
1869
1870static llvm::StringMapEntry<llvm::GlobalVariable *> &
1871GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
1872 const StringLiteral *Literal, unsigned &StringLength) {
1873 StringRef String = Literal->getString();
1874 StringLength = String.size();
1875 return *Map.insert(std::make_pair(String, nullptr)).first;
1876}
1877
1878llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1879 if (llvm::Value *V = ConstantStringClassRef)
1880 return cast<llvm::Constant>(V);
1881
1882 auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
1883 std::string str =
1884 StringClass.empty() ? "_NSConstantStringClassReference"
1885 : "_" + StringClass + "ClassReference";
1886
1887 llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0);
1888 auto GV = CGM.CreateRuntimeVariable(PTy, str);
1889 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1890 ConstantStringClassRef = V;
1891 return V;
1892}
1893
1894llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1895 if (llvm::Value *V = ConstantStringClassRef)
1896 return cast<llvm::Constant>(V);
1897
1898 auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
1899 std::string str =
1900 StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
1901 : "OBJC_CLASS_$_" + StringClass;
John McCalldba63a72016-11-30 23:54:50 +00001902 auto GV = GetClassGlobal(str, NotForDefinition);
John McCallcd21d542016-11-30 23:15:55 +00001903
1904 // Make sure the result is of the correct type.
1905 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1906
1907 ConstantStringClassRef = V;
1908 return V;
1909}
1910
1911ConstantAddress
1912CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) {
1913 unsigned StringLength = 0;
1914 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
1915 GetConstantStringEntry(NSConstantStringMap, Literal, StringLength);
1916
1917 if (auto *C = Entry.second)
1918 return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
1919
1920 // If we don't already have it, get _NSConstantStringClassReference.
1921 llvm::Constant *Class = getNSConstantStringClassRef();
1922
1923 // If we don't already have it, construct the type for a constant NSString.
1924 if (!NSConstantStringType) {
1925 NSConstantStringType =
1926 llvm::StructType::create({
1927 CGM.Int32Ty->getPointerTo(),
1928 CGM.Int8PtrTy,
1929 CGM.IntTy
1930 }, "struct.__builtin_NSString");
1931 }
1932
1933 ConstantInitBuilder Builder(CGM);
1934 auto Fields = Builder.beginStruct(NSConstantStringType);
1935
1936 // Class pointer.
1937 Fields.add(Class);
1938
1939 // String pointer.
1940 llvm::Constant *C =
1941 llvm::ConstantDataArray::getString(VMContext, Entry.first());
1942
1943 llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
1944 bool isConstant = !CGM.getLangOpts().WritableStrings;
1945
1946 auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant,
1947 Linkage, C, ".str");
1948 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1949 // Don't enforce the target's minimum global alignment, since the only use
1950 // of the string is via this class initializer.
1951 GV->setAlignment(1);
1952 Fields.addBitCast(GV, CGM.Int8PtrTy);
1953
1954 // String length.
1955 Fields.addInt(CGM.IntTy, StringLength);
1956
1957 // The struct.
1958 CharUnits Alignment = CGM.getPointerAlign();
1959 GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
1960 /*constant*/ true,
1961 llvm::GlobalVariable::PrivateLinkage);
1962 const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
1963 const char *NSStringNonFragileABISection =
1964 "__DATA,__objc_stringobj,regular,no_dead_strip";
1965 // FIXME. Fix section.
1966 GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile()
1967 ? NSStringNonFragileABISection
1968 : NSStringSection);
1969 Entry.second = GV;
1970
1971 return ConstantAddress(GV, Alignment);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001972}
1973
Ted Kremeneke65b0862012-03-06 20:05:56 +00001974enum {
1975 kCFTaggedObjectID_Integer = (1 << 1) + 1
1976};
1977
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001978/// Generates a message send where the super is the receiver. This is
1979/// a message send to self with special delivery semantics indicating
1980/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001981CodeGen::RValue
1982CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001983 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001984 QualType ResultType,
1985 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001986 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001987 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001988 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001989 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001990 const CodeGen::CallArgList &CallArgs,
1991 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001992 // Create and init a super structure; this is a (receiver, class)
1993 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00001994 Address ObjCSuper =
1995 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
1996 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001997 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001998 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
David Blaikie1ed728c2015-04-05 22:45:47 +00001999 CGF.Builder.CreateStore(
2000 ReceiverAsObject,
John McCall7f416cc2015-09-08 08:05:57 +00002001 CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero()));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002002
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002003 // If this is a class message the metaclass is passed as the target.
2004 llvm::Value *Target;
2005 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002006 if (isCategoryImpl) {
2007 // Message sent to 'super' in a class method defined in a category
2008 // implementation requires an odd treatment.
2009 // If we are in a class method, we must retrieve the
2010 // _metaclass_ for the current class, pointed at by
2011 // the class's "isa" pointer. The following assumes that
2012 // isa" is the first ivar in a class (which it must be).
John McCall882987f2013-02-28 19:01:20 +00002013 Target = EmitClassRef(CGF, Class->getSuperClass());
David Blaikie1ed728c2015-04-05 22:45:47 +00002014 Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
John McCall7f416cc2015-09-08 08:05:57 +00002015 Target = CGF.Builder.CreateAlignedLoad(Target, CGF.getPointerAlign());
Mike Stump658fe022009-07-30 22:28:39 +00002016 } else {
David Blaikie1ed728c2015-04-05 22:45:47 +00002017 llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
2018 llvm::Value *SuperPtr =
2019 CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00002020 llvm::Value *Super =
2021 CGF.Builder.CreateAlignedLoad(SuperPtr, CGF.getPointerAlign());
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002022 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002023 }
David Blaikie1ed728c2015-04-05 22:45:47 +00002024 } else if (isCategoryImpl)
John McCall882987f2013-02-28 19:01:20 +00002025 Target = EmitClassRef(CGF, Class->getSuperClass());
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00002026 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002027 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
David Blaikie1ed728c2015-04-05 22:45:47 +00002028 ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00002029 Target = CGF.Builder.CreateAlignedLoad(ClassPtr, CGF.getPointerAlign());
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002030 }
Mike Stump18bb9282009-05-16 07:57:57 +00002031 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
2032 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00002033 llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00002034 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00002035 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
John McCall7f416cc2015-09-08 08:05:57 +00002036 CGF.Builder.CreateStore(Target,
2037 CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize()));
John McCall9e8bb002011-05-14 03:10:52 +00002038 return EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00002039 EmitSelector(CGF, Sel),
John McCall7f416cc2015-09-08 08:05:57 +00002040 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall1e3157b2015-09-10 22:27:50 +00002041 true, CallArgs, Method, Class, ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002042}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002043
2044/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00002045CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00002046 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00002047 QualType ResultType,
2048 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002049 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00002050 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00002051 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00002052 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00002053 return EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00002054 EmitSelector(CGF, Sel),
John McCall9e8bb002011-05-14 03:10:52 +00002055 Receiver, CGF.getContext().getObjCIdType(),
John McCall1e3157b2015-09-10 22:27:50 +00002056 false, CallArgs, Method, Class, ObjCTypes);
2057}
2058
2059static bool isWeakLinkedClass(const ObjCInterfaceDecl *ID) {
2060 do {
2061 if (ID->isWeakImported())
2062 return true;
2063 } while ((ID = ID->getSuperClass()));
2064
2065 return false;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00002066}
2067
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00002068CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00002069CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
2070 ReturnValueSlot Return,
2071 QualType ResultType,
2072 llvm::Value *Sel,
2073 llvm::Value *Arg0,
2074 QualType Arg0Ty,
2075 bool IsSuper,
2076 const CallArgList &CallArgs,
2077 const ObjCMethodDecl *Method,
John McCall1e3157b2015-09-10 22:27:50 +00002078 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00002079 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc722b852008-08-30 03:02:31 +00002080 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00002081 if (!IsSuper)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00002082 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman43dca6a2011-05-02 17:57:46 +00002083 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
2084 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCall31168b02011-06-15 23:02:42 +00002085 ActualArgs.addFrom(CallArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002086
John McCalla729c622012-02-17 03:33:10 +00002087 // If we're calling a method, use the formal signature.
2088 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002089
Anders Carlsson280e61f12010-06-21 20:59:55 +00002090 if (Method)
Alp Toker314cc812014-01-25 16:55:45 +00002091 assert(CGM.getContext().getCanonicalType(Method->getReturnType()) ==
2092 CGM.getContext().getCanonicalType(ResultType) &&
Anders Carlsson280e61f12010-06-21 20:59:55 +00002093 "Result type mismatch!");
2094
John McCall1e3157b2015-09-10 22:27:50 +00002095 bool ReceiverCanBeNull = true;
2096
2097 // Super dispatch assumes that self is non-null; even the messenger
2098 // doesn't have a null check internally.
2099 if (IsSuper) {
2100 ReceiverCanBeNull = false;
2101
2102 // If this is a direct dispatch of a class method, check whether the class,
2103 // or anything in its hierarchy, was weak-linked.
2104 } else if (ClassReceiver && Method && Method->isClassMethod()) {
2105 ReceiverCanBeNull = isWeakLinkedClass(ClassReceiver);
2106
2107 // If we're emitting a method, and self is const (meaning just ARC, for now),
2108 // and the receiver is a load of self, then self is a valid object.
2109 } else if (auto CurMethod =
2110 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) {
2111 auto Self = CurMethod->getSelfDecl();
2112 if (Self->getType().isConstQualified()) {
2113 if (auto LI = dyn_cast<llvm::LoadInst>(Arg0->stripPointerCasts())) {
2114 llvm::Value *SelfAddr = CGF.GetAddrOfLocalVar(Self).getPointer();
2115 if (SelfAddr == LI->getPointerOperand()) {
2116 ReceiverCanBeNull = false;
2117 }
2118 }
2119 }
2120 }
2121
John McCall5880fb82011-05-14 21:12:11 +00002122 NullReturnState nullReturn;
2123
Craig Topper8a13c412014-05-21 05:09:00 +00002124 llvm::Constant *Fn = nullptr;
Tim Northovere77cc392014-03-29 13:28:05 +00002125 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
John McCall1e3157b2015-09-10 22:27:50 +00002126 if (ReceiverCanBeNull) nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002127 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002128 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00002129 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
2130 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2131 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +00002132 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
2133 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2134 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002135 } else {
Tim Northovere77cc392014-03-29 13:28:05 +00002136 // arm64 uses objc_msgSend for stret methods and yet null receiver check
2137 // must be made for it.
Ahmed Bougachaa3df87b2015-10-02 22:41:59 +00002138 if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
Tim Northovere77cc392014-03-29 13:28:05 +00002139 nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002140 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002141 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002142 }
John McCall1e3157b2015-09-10 22:27:50 +00002143
2144 // Emit a null-check if there's a consumed argument other than the receiver.
2145 bool RequiresNullCheck = false;
2146 if (ReceiverCanBeNull && CGM.getLangOpts().ObjCAutoRefCount && Method) {
David Majnemer59f77922016-06-24 04:05:48 +00002147 for (const auto *ParamDecl : Method->parameters()) {
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002148 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
2149 if (!nullReturn.NullBB)
2150 nullReturn.init(CGF, Arg0);
John McCall1e3157b2015-09-10 22:27:50 +00002151 RequiresNullCheck = true;
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002152 break;
2153 }
2154 }
John McCall1e3157b2015-09-10 22:27:50 +00002155 }
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002156
John McCall1e3157b2015-09-10 22:27:50 +00002157 llvm::Instruction *CallSite;
John McCalla729c622012-02-17 03:33:10 +00002158 Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
John McCallb92ab1a2016-10-26 23:46:34 +00002159 CGCallee Callee = CGCallee::forDirect(Fn);
2160 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2161 &CallSite);
John McCall1e3157b2015-09-10 22:27:50 +00002162
2163 // Mark the call as noreturn if the method is marked noreturn and the
2164 // receiver cannot be null.
2165 if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
2166 llvm::CallSite(CallSite).setDoesNotReturn();
2167 }
2168
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002169 return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
John McCall1e3157b2015-09-10 22:27:50 +00002170 RequiresNullCheck ? Method : nullptr);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002171}
2172
John McCall3fd13f062015-10-21 18:06:47 +00002173static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT,
2174 bool pointee = false) {
2175 // Note that GC qualification applies recursively to C pointer types
2176 // that aren't otherwise decorated. This is weird, but it's probably
2177 // an intentional workaround to the unreliable placement of GC qualifiers.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002178 if (FQT.isObjCGCStrong())
2179 return Qualifiers::Strong;
John McCall3fd13f062015-10-21 18:06:47 +00002180
2181 if (FQT.isObjCGCWeak())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002182 return Qualifiers::Weak;
John McCall3fd13f062015-10-21 18:06:47 +00002183
2184 if (auto ownership = FQT.getObjCLifetime()) {
2185 // Ownership does not apply recursively to C pointer types.
2186 if (pointee) return Qualifiers::GCNone;
2187 switch (ownership) {
2188 case Qualifiers::OCL_Weak: return Qualifiers::Weak;
2189 case Qualifiers::OCL_Strong: return Qualifiers::Strong;
2190 case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone;
2191 case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?");
2192 case Qualifiers::OCL_None: llvm_unreachable("known nonzero");
2193 }
2194 llvm_unreachable("bad objc ownership");
2195 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002196
John McCall3fd13f062015-10-21 18:06:47 +00002197 // Treat unqualified retainable pointers as strong.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002198 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
2199 return Qualifiers::Strong;
2200
John McCall3fd13f062015-10-21 18:06:47 +00002201 // Walk into C pointer types, but only in GC.
2202 if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) {
2203 if (const PointerType *PT = FQT->getAs<PointerType>())
2204 return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true);
2205 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002206
2207 return Qualifiers::GCNone;
2208}
2209
John McCall3fd13f062015-10-21 18:06:47 +00002210namespace {
2211 struct IvarInfo {
2212 CharUnits Offset;
2213 uint64_t SizeInWords;
2214 IvarInfo(CharUnits offset, uint64_t sizeInWords)
2215 : Offset(offset), SizeInWords(sizeInWords) {}
2216
2217 // Allow sorting based on byte pos.
2218 bool operator<(const IvarInfo &other) const {
2219 return Offset < other.Offset;
2220 }
2221 };
2222
2223 /// A helper class for building GC layout strings.
2224 class IvarLayoutBuilder {
2225 CodeGenModule &CGM;
2226
2227 /// The start of the layout. Offsets will be relative to this value,
2228 /// and entries less than this value will be silently discarded.
2229 CharUnits InstanceBegin;
2230
2231 /// The end of the layout. Offsets will never exceed this value.
2232 CharUnits InstanceEnd;
2233
2234 /// Whether we're generating the strong layout or the weak layout.
2235 bool ForStrongLayout;
2236
2237 /// Whether the offsets in IvarsInfo might be out-of-order.
2238 bool IsDisordered = false;
2239
2240 llvm::SmallVector<IvarInfo, 8> IvarsInfo;
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002241
John McCall3fd13f062015-10-21 18:06:47 +00002242 public:
2243 IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
2244 CharUnits instanceEnd, bool forStrongLayout)
2245 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2246 ForStrongLayout(forStrongLayout) {
2247 }
2248
2249 void visitRecord(const RecordType *RT, CharUnits offset);
2250
2251 template <class Iterator, class GetOffsetFn>
2252 void visitAggregate(Iterator begin, Iterator end,
2253 CharUnits aggrOffset,
2254 const GetOffsetFn &getOffset);
2255
2256 void visitField(const FieldDecl *field, CharUnits offset);
2257
2258 /// Add the layout of a block implementation.
2259 void visitBlock(const CGBlockInfo &blockInfo);
2260
2261 /// Is there any information for an interesting bitmap?
2262 bool hasBitmapData() const { return !IvarsInfo.empty(); }
2263
2264 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2265 llvm::SmallVectorImpl<unsigned char> &buffer);
2266
2267 static void dump(ArrayRef<unsigned char> buffer) {
2268 const unsigned char *s = buffer.data();
2269 for (unsigned i = 0, e = buffer.size(); i < e; i++)
2270 if (!(s[i] & 0xf0))
2271 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
2272 else
2273 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
2274 printf("\n");
2275 }
2276 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002277} // end anonymous namespace
John McCall3fd13f062015-10-21 18:06:47 +00002278
John McCall351762c2011-02-07 10:33:21 +00002279llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
2280 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002281
Chris Lattnerece04092012-02-07 00:39:47 +00002282 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
John McCall460ce582015-10-22 18:38:17 +00002283 if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
John McCall351762c2011-02-07 10:33:21 +00002284 return nullPtr;
2285
John McCall3fd13f062015-10-21 18:06:47 +00002286 IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize,
2287 /*for strong layout*/ true);
2288
2289 builder.visitBlock(blockInfo);
2290
2291 if (!builder.hasBitmapData())
2292 return nullPtr;
2293
2294 llvm::SmallVector<unsigned char, 32> buffer;
2295 llvm::Constant *C = builder.buildBitmap(*this, buffer);
John McCallf5ea0722015-10-29 23:36:14 +00002296 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
John McCall3fd13f062015-10-21 18:06:47 +00002297 printf("\n block variable layout for block: ");
2298 builder.dump(buffer);
2299 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002300
John McCall3fd13f062015-10-21 18:06:47 +00002301 return C;
2302}
2303
2304void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00002305 // __isa is the first field in block descriptor and must assume by runtime's
2306 // convention that it is GC'able.
John McCall3fd13f062015-10-21 18:06:47 +00002307 IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1));
John McCall351762c2011-02-07 10:33:21 +00002308
2309 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2310
John McCall351762c2011-02-07 10:33:21 +00002311 // Ignore the optional 'this' capture: C++ objects are not assumed
2312 // to be GC'ed.
2313
John McCall3fd13f062015-10-21 18:06:47 +00002314 CharUnits lastFieldOffset;
2315
John McCall351762c2011-02-07 10:33:21 +00002316 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002317 for (const auto &CI : blockDecl->captures()) {
2318 const VarDecl *variable = CI.getVariable();
John McCall351762c2011-02-07 10:33:21 +00002319 QualType type = variable->getType();
2320
2321 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2322
2323 // Ignore constant captures.
2324 if (capture.isConstant()) continue;
2325
John McCall3fd13f062015-10-21 18:06:47 +00002326 CharUnits fieldOffset = capture.getOffset();
2327
2328 // Block fields are not necessarily ordered; if we detect that we're
2329 // adding them out-of-order, make sure we sort later.
2330 if (fieldOffset < lastFieldOffset)
2331 IsDisordered = true;
2332 lastFieldOffset = fieldOffset;
John McCall351762c2011-02-07 10:33:21 +00002333
2334 // __block variables are passed by their descriptor address.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002335 if (CI.isByRef()) {
John McCall3fd13f062015-10-21 18:06:47 +00002336 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00002337 continue;
John McCall351762c2011-02-07 10:33:21 +00002338 }
2339
2340 assert(!type->isArrayType() && "array variable should not be caught");
2341 if (const RecordType *record = type->getAs<RecordType>()) {
John McCall3fd13f062015-10-21 18:06:47 +00002342 visitRecord(record, fieldOffset);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00002343 continue;
2344 }
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00002345
John McCall351762c2011-02-07 10:33:21 +00002346 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
John McCall351762c2011-02-07 10:33:21 +00002347
John McCall3fd13f062015-10-21 18:06:47 +00002348 if (GCAttr == Qualifiers::Strong) {
2349 assert(CGM.getContext().getTypeSize(type)
2350 == CGM.getTarget().getPointerWidth(0));
2351 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
2352 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002353 }
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00002354}
2355
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00002356/// getBlockCaptureLifetime - This routine returns life time of the captured
2357/// block variable for the purpose of block layout meta-data generation. FQT is
2358/// the type of the variable captured in the block.
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002359Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
2360 bool ByrefLayout) {
John McCall460ce582015-10-22 18:38:17 +00002361 // If it has an ownership qualifier, we're done.
2362 if (auto lifetime = FQT.getObjCLifetime())
2363 return lifetime;
2364
2365 // If it doesn't, and this is ARC, it has no ownership.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002366 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCall460ce582015-10-22 18:38:17 +00002367 return Qualifiers::OCL_None;
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002368
John McCall460ce582015-10-22 18:38:17 +00002369 // In MRC, retainable pointers are owned by non-__block variables.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002370 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002371 return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002372
2373 return Qualifiers::OCL_None;
2374}
2375
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002376void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
2377 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002378 CharUnits FieldOffset,
2379 CharUnits FieldSize) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002380 // __block variables are passed by their descriptor address.
2381 if (IsByref)
2382 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002383 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002384 else if (LifeTime == Qualifiers::OCL_Strong)
2385 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002386 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002387 else if (LifeTime == Qualifiers::OCL_Weak)
2388 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002389 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002390 else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2391 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002392 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002393 else
2394 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2395 FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002396 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002397}
2398
2399void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2400 const RecordDecl *RD,
2401 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002402 CharUnits BytePos, bool &HasUnion,
2403 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002404 bool IsUnion = (RD && RD->isUnion());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002405 CharUnits MaxUnionSize = CharUnits::Zero();
Craig Topper8a13c412014-05-21 05:09:00 +00002406 const FieldDecl *MaxField = nullptr;
2407 const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002408 CharUnits MaxFieldOffset = CharUnits::Zero();
2409 CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002410
2411 if (RecFields.empty())
2412 return;
John McCallc8e01702013-04-16 22:48:15 +00002413 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002414
2415 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2416 const FieldDecl *Field = RecFields[i];
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002417 // Note that 'i' here is actually the field index inside RD of Field,
2418 // although this dependency is hidden.
2419 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002420 CharUnits FieldOffset =
2421 CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002422
2423 // Skip over unnamed or bitfields
2424 if (!Field->getIdentifier() || Field->isBitField()) {
2425 LastFieldBitfieldOrUnnamed = Field;
2426 LastBitfieldOrUnnamedOffset = FieldOffset;
2427 continue;
2428 }
Craig Topper8a13c412014-05-21 05:09:00 +00002429
2430 LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002431 QualType FQT = Field->getType();
2432 if (FQT->isRecordType() || FQT->isUnionType()) {
2433 if (FQT->isUnionType())
2434 HasUnion = true;
2435
2436 BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
2437 BytePos + FieldOffset, HasUnion);
2438 continue;
2439 }
2440
2441 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2442 const ConstantArrayType *CArray =
2443 dyn_cast_or_null<ConstantArrayType>(Array);
2444 uint64_t ElCount = CArray->getSize().getZExtValue();
2445 assert(CArray && "only array with known element size is supported");
2446 FQT = CArray->getElementType();
2447 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2448 const ConstantArrayType *CArray =
2449 dyn_cast_or_null<ConstantArrayType>(Array);
2450 ElCount *= CArray->getSize().getZExtValue();
2451 FQT = CArray->getElementType();
2452 }
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002453 if (FQT->isRecordType() && ElCount) {
2454 int OldIndex = RunSkipBlockVars.size() - 1;
2455 const RecordType *RT = FQT->getAs<RecordType>();
2456 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
2457 HasUnion);
2458
2459 // Replicate layout information for each array element. Note that
2460 // one element is already done.
2461 uint64_t ElIx = 1;
2462 for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002463 CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002464 for (int i = OldIndex+1; i <= FirstIndex; ++i)
2465 RunSkipBlockVars.push_back(
2466 RUN_SKIP(RunSkipBlockVars[i].opcode,
2467 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2468 RunSkipBlockVars[i].block_var_size));
2469 }
2470 continue;
2471 }
2472 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002473 CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002474 if (IsUnion) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002475 CharUnits UnionIvarSize = FieldSize;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002476 if (UnionIvarSize > MaxUnionSize) {
2477 MaxUnionSize = UnionIvarSize;
2478 MaxField = Field;
2479 MaxFieldOffset = FieldOffset;
2480 }
2481 } else {
2482 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002483 getBlockCaptureLifetime(FQT, ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002484 BytePos + FieldOffset,
2485 FieldSize);
2486 }
2487 }
2488
2489 if (LastFieldBitfieldOrUnnamed) {
2490 if (LastFieldBitfieldOrUnnamed->isBitField()) {
2491 // Last field was a bitfield. Must update the info.
2492 uint64_t BitFieldSize
2493 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002494 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
Eli Friedman8cbca202012-11-06 22:15:52 +00002495 ((BitFieldSize % ByteSizeInBits) != 0);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002496 CharUnits Size = CharUnits::fromQuantity(UnsSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002497 Size += LastBitfieldOrUnnamedOffset;
2498 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002499 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2500 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002501 BytePos + LastBitfieldOrUnnamedOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002502 Size);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002503 } else {
2504 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2505 // Last field was unnamed. Must update skip info.
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002506 CharUnits FieldSize
2507 = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002508 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002509 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2510 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002511 BytePos + LastBitfieldOrUnnamedOffset,
2512 FieldSize);
2513 }
2514 }
2515
2516 if (MaxField)
2517 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002518 getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002519 BytePos + MaxFieldOffset,
2520 MaxUnionSize);
2521}
2522
2523void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002524 CharUnits BytePos,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002525 bool &HasUnion,
2526 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002527 const RecordDecl *RD = RT->getDecl();
Aaron Ballman62e47c42014-03-10 13:43:55 +00002528 SmallVector<const FieldDecl*, 16> Fields(RD->fields());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002529 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
2530 const llvm::StructLayout *RecLayout =
2531 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2532
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002533 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002534}
2535
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002536/// InlineLayoutInstruction - This routine produce an inline instruction for the
2537/// block variable layout if it can. If not, it returns 0. Rules are as follow:
2538/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
2539/// an inline layout of value 0x0000000000000xyz is interpreted as follows:
2540/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
2541/// y captured object of BLOCK_LAYOUT_BYREF. Followed by
2542/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
2543/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
2544/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
2545uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2546 SmallVectorImpl<unsigned char> &Layout) {
2547 uint64_t Result = 0;
2548 if (Layout.size() <= 3) {
2549 unsigned size = Layout.size();
2550 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2551 unsigned char inst;
2552 enum BLOCK_LAYOUT_OPCODE opcode ;
2553 switch (size) {
2554 case 3:
2555 inst = Layout[0];
2556 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2557 if (opcode == BLOCK_LAYOUT_STRONG)
2558 strong_word_count = (inst & 0xF)+1;
2559 else
2560 return 0;
2561 inst = Layout[1];
2562 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2563 if (opcode == BLOCK_LAYOUT_BYREF)
2564 byref_word_count = (inst & 0xF)+1;
2565 else
2566 return 0;
2567 inst = Layout[2];
2568 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2569 if (opcode == BLOCK_LAYOUT_WEAK)
2570 weak_word_count = (inst & 0xF)+1;
2571 else
2572 return 0;
2573 break;
2574
2575 case 2:
2576 inst = Layout[0];
2577 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2578 if (opcode == BLOCK_LAYOUT_STRONG) {
2579 strong_word_count = (inst & 0xF)+1;
2580 inst = Layout[1];
2581 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2582 if (opcode == BLOCK_LAYOUT_BYREF)
2583 byref_word_count = (inst & 0xF)+1;
2584 else if (opcode == BLOCK_LAYOUT_WEAK)
2585 weak_word_count = (inst & 0xF)+1;
2586 else
2587 return 0;
2588 }
2589 else if (opcode == BLOCK_LAYOUT_BYREF) {
2590 byref_word_count = (inst & 0xF)+1;
2591 inst = Layout[1];
2592 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2593 if (opcode == BLOCK_LAYOUT_WEAK)
2594 weak_word_count = (inst & 0xF)+1;
2595 else
2596 return 0;
2597 }
2598 else
2599 return 0;
2600 break;
2601
2602 case 1:
2603 inst = Layout[0];
2604 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2605 if (opcode == BLOCK_LAYOUT_STRONG)
2606 strong_word_count = (inst & 0xF)+1;
2607 else if (opcode == BLOCK_LAYOUT_BYREF)
2608 byref_word_count = (inst & 0xF)+1;
2609 else if (opcode == BLOCK_LAYOUT_WEAK)
2610 weak_word_count = (inst & 0xF)+1;
2611 else
2612 return 0;
2613 break;
2614
2615 default:
2616 return 0;
2617 }
2618
2619 // Cannot inline when any of the word counts is 15. Because this is one less
2620 // than the actual work count (so 15 means 16 actual word counts),
2621 // and we can only display 0 thru 15 word counts.
2622 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2623 return 0;
2624
2625 unsigned count =
2626 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2627
2628 if (size == count) {
2629 if (strong_word_count)
2630 Result = strong_word_count;
2631 Result <<= 4;
2632 if (byref_word_count)
2633 Result += byref_word_count;
2634 Result <<= 4;
2635 if (weak_word_count)
2636 Result += weak_word_count;
2637 }
2638 }
2639 return Result;
2640}
2641
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002642llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
2643 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2644 if (RunSkipBlockVars.empty())
2645 return nullPtr;
John McCallc8e01702013-04-16 22:48:15 +00002646 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2647 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002648 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2649
2650 // Sort on byte position; captures might not be allocated in order,
2651 // and unions can do funny things.
2652 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2653 SmallVector<unsigned char, 16> Layout;
2654
2655 unsigned size = RunSkipBlockVars.size();
2656 for (unsigned i = 0; i < size; i++) {
2657 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2658 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2659 CharUnits end_byte_pos = start_byte_pos;
2660 unsigned j = i+1;
2661 while (j < size) {
2662 if (opcode == RunSkipBlockVars[j].opcode) {
2663 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2664 i++;
2665 }
2666 else
2667 break;
2668 }
2669 CharUnits size_in_bytes =
2670 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2671 if (j < size) {
2672 CharUnits gap =
2673 RunSkipBlockVars[j].block_var_bytepos -
2674 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2675 size_in_bytes += gap;
2676 }
2677 CharUnits residue_in_bytes = CharUnits::Zero();
2678 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2679 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2680 size_in_bytes -= residue_in_bytes;
2681 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2682 }
2683
2684 unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
2685 while (size_in_words >= 16) {
2686 // Note that value in imm. is one less that the actual
2687 // value. So, 0xf means 16 words follow!
2688 unsigned char inst = (opcode << 4) | 0xf;
2689 Layout.push_back(inst);
2690 size_in_words -= 16;
2691 }
2692 if (size_in_words > 0) {
2693 // Note that value in imm. is one less that the actual
2694 // value. So, we subtract 1 away!
2695 unsigned char inst = (opcode << 4) | (size_in_words-1);
2696 Layout.push_back(inst);
2697 }
2698 if (residue_in_bytes > CharUnits::Zero()) {
2699 unsigned char inst =
2700 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
2701 Layout.push_back(inst);
2702 }
2703 }
2704
John McCall7f416cc2015-09-08 08:05:57 +00002705 while (!Layout.empty()) {
2706 unsigned char inst = Layout.back();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002707 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2708 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2709 Layout.pop_back();
2710 else
2711 break;
2712 }
2713
2714 uint64_t Result = InlineLayoutInstruction(Layout);
2715 if (Result != 0) {
2716 // Block variable layout instruction has been inlined.
2717 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2718 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002719 printf("\n Inline BYREF variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002720 else
John McCall7f416cc2015-09-08 08:05:57 +00002721 printf("\n Inline block variable layout: ");
2722 printf("0x0%" PRIx64 "", Result);
2723 if (auto numStrong = (Result & 0xF00) >> 8)
2724 printf(", BL_STRONG:%d", (int) numStrong);
2725 if (auto numByref = (Result & 0x0F0) >> 4)
2726 printf(", BL_BYREF:%d", (int) numByref);
2727 if (auto numWeak = (Result & 0x00F) >> 0)
2728 printf(", BL_WEAK:%d", (int) numWeak);
2729 printf(", BL_OPERATOR:0\n");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002730 }
Vedant Kumar3ed0df02015-12-21 19:43:25 +00002731 return llvm::ConstantInt::get(CGM.IntPtrTy, Result);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002732 }
2733
2734 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2735 Layout.push_back(inst);
2736 std::string BitMap;
2737 for (unsigned i = 0, e = Layout.size(); i != e; i++)
2738 BitMap += Layout[i];
2739
2740 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2741 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002742 printf("\n Byref variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002743 else
John McCall7f416cc2015-09-08 08:05:57 +00002744 printf("\n Block variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002745 for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
2746 unsigned char inst = BitMap[i];
2747 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2748 unsigned delta = 1;
2749 switch (opcode) {
2750 case BLOCK_LAYOUT_OPERATOR:
2751 printf("BL_OPERATOR:");
2752 delta = 0;
2753 break;
2754 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2755 printf("BL_NON_OBJECT_BYTES:");
2756 break;
2757 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2758 printf("BL_NON_OBJECT_WORD:");
2759 break;
2760 case BLOCK_LAYOUT_STRONG:
2761 printf("BL_STRONG:");
2762 break;
2763 case BLOCK_LAYOUT_BYREF:
2764 printf("BL_BYREF:");
2765 break;
2766 case BLOCK_LAYOUT_WEAK:
2767 printf("BL_WEAK:");
2768 break;
2769 case BLOCK_LAYOUT_UNRETAINED:
2770 printf("BL_UNRETAINED:");
2771 break;
2772 }
2773 // Actual value of word count is one more that what is in the imm.
2774 // field of the instruction
2775 printf("%d", (inst & 0xf) + delta);
2776 if (i < e-1)
2777 printf(", ");
2778 else
2779 printf("\n");
2780 }
2781 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00002782
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00002783 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2784 /*ForceNonFragileABI=*/true,
2785 /*NullTerminate=*/false);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002786 return getConstantGEP(VMContext, Entry, 0, 0);
2787}
2788
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002789llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2790 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002791 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2792
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002793 RunSkipBlockVars.clear();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002794 bool hasUnion = false;
2795
John McCallc8e01702013-04-16 22:48:15 +00002796 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2797 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002798 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2799
2800 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2801
2802 // Calculate the basic layout of the block structure.
2803 const llvm::StructLayout *layout =
2804 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
2805
2806 // Ignore the optional 'this' capture: C++ objects are not assumed
2807 // to be GC'ed.
Fariborz Jahanian4cf177e2012-12-04 17:20:57 +00002808 if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
2809 UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
2810 blockInfo.BlockHeaderForcedGapOffset,
2811 blockInfo.BlockHeaderForcedGapSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002812 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002813 for (const auto &CI : blockDecl->captures()) {
2814 const VarDecl *variable = CI.getVariable();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002815 QualType type = variable->getType();
2816
2817 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2818
2819 // Ignore constant captures.
2820 if (capture.isConstant()) continue;
2821
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002822 CharUnits fieldOffset =
2823 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002824
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002825 assert(!type->isArrayType() && "array variable should not be caught");
Aaron Ballman9371dd22014-03-14 18:34:04 +00002826 if (!CI.isByRef())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002827 if (const RecordType *record = type->getAs<RecordType>()) {
2828 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2829 continue;
2830 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002831 CharUnits fieldSize;
Aaron Ballman9371dd22014-03-14 18:34:04 +00002832 if (CI.isByRef())
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002833 fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2834 else
2835 fieldSize = CGM.getContext().getTypeSizeInChars(type);
Aaron Ballman9371dd22014-03-14 18:34:04 +00002836 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002837 fieldOffset, fieldSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002838 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002839 return getBitmapBlockLayout(false);
2840}
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002841
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002842llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2843 QualType T) {
2844 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2845 assert(!T->isArrayType() && "__block array variable should not be caught");
2846 CharUnits fieldOffset;
2847 RunSkipBlockVars.clear();
2848 bool hasUnion = false;
2849 if (const RecordType *record = T->getAs<RecordType>()) {
2850 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
2851 llvm::Constant *Result = getBitmapBlockLayout(true);
Vedant Kumar2f5bb1152015-12-21 20:21:15 +00002852 if (isa<llvm::ConstantInt>(Result))
2853 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002854 return Result;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002855 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002856 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2857 return nullPtr;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002858}
2859
John McCall882987f2013-02-28 19:01:20 +00002860llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00002861 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00002862 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002863 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00002864 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2865
Owen Andersonade90fd2009-07-29 18:54:39 +00002866 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00002867 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002868}
2869
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002870void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00002871 // FIXME: We shouldn't need this, the protocol decl should contain enough
2872 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00002873 DefinedProtocols.insert(PD->getIdentifier());
2874
2875 // If we have generated a forward reference to this protocol, emit
2876 // it now. Otherwise do nothing, the protocol objects are lazily
2877 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002878 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00002879 GetOrEmitProtocol(PD);
2880}
2881
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002882llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002883 if (DefinedProtocols.count(PD->getIdentifier()))
2884 return GetOrEmitProtocol(PD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002885
Daniel Dunbarc475d422008-10-29 22:36:39 +00002886 return GetOrEmitProtocolRef(PD);
2887}
2888
Douglas Gregor24ae22c2016-04-01 23:23:52 +00002889llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
2890 CodeGenFunction &CGF,
2891 const ObjCInterfaceDecl *ID,
2892 ObjCCommonTypesHelper &ObjCTypes) {
2893 llvm::Constant *lookUpClassFn = ObjCTypes.getLookUpClassFn();
2894
2895 llvm::Value *className =
2896 CGF.CGM.GetAddrOfConstantCString(ID->getObjCRuntimeNameAsString())
2897 .getPointer();
2898 ASTContext &ctx = CGF.CGM.getContext();
2899 className =
2900 CGF.Builder.CreateBitCast(className,
2901 CGF.ConvertType(
2902 ctx.getPointerType(ctx.CharTy.withConst())));
2903 llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className);
2904 call->setDoesNotThrow();
2905 return call;
2906}
2907
Daniel Dunbarb036db82008-08-13 03:21:16 +00002908/*
Rafael Espindolaf9e1e5e2014-02-20 14:09:04 +00002909// Objective-C 1.0 extensions
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002910struct _objc_protocol {
2911struct _objc_protocol_extension *isa;
2912char *protocol_name;
2913struct _objc_protocol_list *protocol_list;
2914struct _objc__method_prototype_list *instance_methods;
2915struct _objc__method_prototype_list *class_methods
2916};
Daniel Dunbarb036db82008-08-13 03:21:16 +00002917
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002918See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00002919*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00002920llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00002921 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbarc475d422008-10-29 22:36:39 +00002922
2923 // Early exit if a defining object has already been generated.
2924 if (Entry && Entry->hasInitializer())
2925 return Entry;
2926
Douglas Gregora715bff2012-01-01 19:51:50 +00002927 // Use the protocol definition, if there is one.
2928 if (const ObjCProtocolDecl *Def = PD->getDefinition())
2929 PD = Def;
2930
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002931 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002932 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002933 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2934
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002935 // Construct method lists.
John McCall176f8922016-11-30 02:39:18 +00002936 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002937
John McCall176f8922016-11-30 02:39:18 +00002938 ConstantInitBuilder builder(CGM);
2939 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
2940 values.add(EmitProtocolExtension(PD, methodLists));
2941 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
2942 values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
2943 PD->protocol_begin(), PD->protocol_end()));
2944 values.add(methodLists.emitMethodList(this, PD,
2945 ProtocolMethodLists::RequiredInstanceMethods));
2946 values.add(methodLists.emitMethodList(this, PD,
2947 ProtocolMethodLists::RequiredClassMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002948
Daniel Dunbarb036db82008-08-13 03:21:16 +00002949 if (Entry) {
Rafael Espindola5d117f32014-03-06 01:10:46 +00002950 // Already created, update the initializer.
Rafael Espindolab3262952014-05-09 00:43:37 +00002951 assert(Entry->hasPrivateLinkage());
John McCall176f8922016-11-30 02:39:18 +00002952 values.finishAndSetAsInitializer(Entry);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002953 } else {
John McCall176f8922016-11-30 02:39:18 +00002954 Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(),
2955 CGM.getPointerAlign(),
2956 /*constant*/ false,
2957 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002958 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
John McCallf9582a72012-03-30 21:29:05 +00002959
2960 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002961 }
Rafael Espindola060062a2014-03-06 22:15:10 +00002962 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00002963
2964 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002965}
2966
Daniel Dunbarc475d422008-10-29 22:36:39 +00002967llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002968 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
2969
2970 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002971 // We use the initializer as a marker of whether this is a forward
2972 // reference or not. At module finalization we add the empty
2973 // contents for protocols which were referenced but never defined.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00002974 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
2975 false, llvm::GlobalValue::PrivateLinkage,
2976 nullptr, "OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002977 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002978 // FIXME: Is this necessary? Why only for protocol?
2979 Entry->setAlignment(4);
2980 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002981
Daniel Dunbarb036db82008-08-13 03:21:16 +00002982 return Entry;
2983}
2984
2985/*
2986 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002987 uint32_t size;
2988 struct objc_method_description_list *optional_instance_methods;
2989 struct objc_method_description_list *optional_class_methods;
2990 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002991 const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00002992 struct objc_property_list *class_properties;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002993 };
2994*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002995llvm::Constant *
2996CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00002997 const ProtocolMethodLists &methodLists) {
2998 auto optInstanceMethods =
2999 methodLists.emitMethodList(this, PD,
3000 ProtocolMethodLists::OptionalInstanceMethods);
3001 auto optClassMethods =
3002 methodLists.emitMethodList(this, PD,
3003 ProtocolMethodLists::OptionalClassMethods);
3004
3005 auto extendedMethodTypes =
3006 EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
3007 methodLists.emitExtendedTypesArray(this),
3008 ObjCTypes);
3009
3010 auto instanceProperties =
3011 EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD,
3012 ObjCTypes, false);
3013 auto classProperties =
3014 EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr,
3015 PD, ObjCTypes, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003016
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003017 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00003018 if (optInstanceMethods->isNullValue() &&
3019 optClassMethods->isNullValue() &&
3020 extendedMethodTypes->isNullValue() &&
3021 instanceProperties->isNullValue() &&
3022 classProperties->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003023 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003024 }
Daniel Dunbarb036db82008-08-13 03:21:16 +00003025
John McCall176f8922016-11-30 02:39:18 +00003026 uint64_t size =
3027 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3028
3029 ConstantInitBuilder builder(CGM);
3030 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3031 values.addInt(ObjCTypes.IntTy, size);
3032 values.add(optInstanceMethods);
3033 values.add(optClassMethods);
3034 values.add(instanceProperties);
3035 values.add(extendedMethodTypes);
3036 values.add(classProperties);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003037
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003038 // No special section, but goes in llvm.used
John McCall176f8922016-11-30 02:39:18 +00003039 return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00003040 StringRef(), CGM.getPointerAlign(), true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003041}
3042
3043/*
3044 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00003045 struct objc_protocol_list *next;
3046 long count;
3047 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00003048 };
3049*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00003050llvm::Constant *
John McCall176f8922016-11-30 02:39:18 +00003051CGObjCMac::EmitProtocolList(Twine name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00003052 ObjCProtocolDecl::protocol_iterator begin,
3053 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003054 // Just return null for empty protocol lists
John McCall176f8922016-11-30 02:39:18 +00003055 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00003056 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003057
John McCall176f8922016-11-30 02:39:18 +00003058 ConstantInitBuilder builder(CGM);
3059 auto values = builder.beginStruct();
Daniel Dunbarb036db82008-08-13 03:21:16 +00003060
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003061 // This field is only used by the runtime.
John McCall176f8922016-11-30 02:39:18 +00003062 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003063
John McCall176f8922016-11-30 02:39:18 +00003064 // Reserve a slot for the count.
3065 auto countSlot = values.addPlaceholder();
3066
3067 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3068 for (; begin != end; ++begin) {
3069 refsArray.add(GetProtocolRef(*begin));
3070 }
3071 auto count = refsArray.size();
3072
3073 // This list is null terminated.
3074 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3075
3076 refsArray.finishAndAddTo(values);
3077 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3078
3079 StringRef section;
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003080 if (CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00003081 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003082
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003083 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003084 CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false);
Owen Andersonade90fd2009-07-29 18:54:39 +00003085 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003086}
3087
John McCall176f8922016-11-30 02:39:18 +00003088static void
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003089PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
John McCall176f8922016-11-30 02:39:18 +00003090 SmallVectorImpl<const ObjCPropertyDecl *> &Properties,
Aaron Ballmandc4bea42014-03-13 18:47:37 +00003091 const ObjCProtocolDecl *Proto,
Manman Renad0e7912016-01-29 19:22:54 +00003092 bool IsClassProperty) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00003093 for (const auto *P : Proto->protocols())
John McCall176f8922016-11-30 02:39:18 +00003094 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Manman Renad0e7912016-01-29 19:22:54 +00003095
3096 for (const auto *PD : Proto->properties()) {
3097 if (IsClassProperty != PD->isClassProperty())
3098 continue;
David Blaikie82e95a32014-11-19 07:49:47 +00003099 if (!PropertySet.insert(PD->getIdentifier()).second)
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003100 continue;
John McCall176f8922016-11-30 02:39:18 +00003101 Properties.push_back(PD);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003102 }
3103}
3104
Daniel Dunbarb036db82008-08-13 03:21:16 +00003105/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003106 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00003107 const char * const name;
3108 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003109 };
3110
3111 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00003112 uint32_t entsize; // sizeof (struct _objc_property)
3113 uint32_t prop_count;
3114 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003115 };
3116*/
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003117llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003118 const Decl *Container,
3119 const ObjCContainerDecl *OCD,
Manman Renad0e7912016-01-29 19:22:54 +00003120 const ObjCCommonTypesHelper &ObjCTypes,
3121 bool IsClassProperty) {
Manman Ren01b705e2016-04-19 19:05:03 +00003122 if (IsClassProperty) {
3123 // Make this entry NULL for OS X with deployment target < 10.11, for iOS
3124 // with deployment target < 9.0.
3125 const llvm::Triple &Triple = CGM.getTarget().getTriple();
3126 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3127 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3128 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3129 }
3130
John McCall176f8922016-11-30 02:39:18 +00003131 SmallVector<const ObjCPropertyDecl *, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003132 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Nico Weber08c93332015-12-03 17:44:51 +00003133
Nico Weber08c93332015-12-03 17:44:51 +00003134 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3135 for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
Manman Renad0e7912016-01-29 19:22:54 +00003136 for (auto *PD : ClassExt->properties()) {
3137 if (IsClassProperty != PD->isClassProperty())
3138 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003139 PropertySet.insert(PD->getIdentifier());
John McCall176f8922016-11-30 02:39:18 +00003140 Properties.push_back(PD);
Nico Weber08c93332015-12-03 17:44:51 +00003141 }
Manman Renad0e7912016-01-29 19:22:54 +00003142
3143 for (const auto *PD : OCD->properties()) {
3144 if (IsClassProperty != PD->isClassProperty())
3145 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003146 // Don't emit duplicate metadata for properties that were already in a
3147 // class extension.
3148 if (!PropertySet.insert(PD->getIdentifier()).second)
3149 continue;
John McCall176f8922016-11-30 02:39:18 +00003150 Properties.push_back(PD);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003151 }
Nico Weber08c93332015-12-03 17:44:51 +00003152
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003153 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003154 for (const auto *P : OID->all_referenced_protocols())
John McCall176f8922016-11-30 02:39:18 +00003155 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003156 }
3157 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
Aaron Ballman19a41762014-03-14 12:55:57 +00003158 for (const auto *P : CD->protocols())
John McCall176f8922016-11-30 02:39:18 +00003159 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003160 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003161
3162 // Return null for empty list.
3163 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003164 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003165
John McCall176f8922016-11-30 02:39:18 +00003166 unsigned propertySize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00003167 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
John McCall176f8922016-11-30 02:39:18 +00003168
3169 ConstantInitBuilder builder(CGM);
3170 auto values = builder.beginStruct();
3171 values.addInt(ObjCTypes.IntTy, propertySize);
3172 values.addInt(ObjCTypes.IntTy, Properties.size());
3173 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3174 for (auto PD : Properties) {
3175 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3176 property.add(GetPropertyName(PD->getIdentifier()));
3177 property.add(GetPropertyTypeString(PD, Container));
3178 property.finishAndAddTo(propertiesArray);
3179 }
3180 propertiesArray.finishAndAddTo(values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003181
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003182 StringRef Section;
3183 if (CGM.getTriple().isOSBinFormatMachO())
3184 Section = (ObjCABI == 2) ? "__DATA, __objc_const"
3185 : "__OBJC,__property,regular,no_dead_strip";
3186
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003187 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003188 CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003189 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003190}
3191
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003192llvm::Constant *
3193CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
3194 ArrayRef<llvm::Constant*> MethodTypes,
3195 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003196 // Return null for empty list.
3197 if (MethodTypes.empty())
3198 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3199
3200 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3201 MethodTypes.size());
3202 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
3203
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003204 StringRef Section;
3205 if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3206 Section = "__DATA, __objc_const";
3207
3208 llvm::GlobalVariable *GV =
3209 CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003210 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
3211}
3212
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003213/*
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003214 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003215 char *category_name;
3216 char *class_name;
3217 struct _objc_method_list *instance_methods;
3218 struct _objc_method_list *class_methods;
3219 struct _objc_protocol_list *protocols;
3220 uint32_t size; // <rdar://4585769>
3221 struct _objc_property_list *instance_properties;
Manman Ren96df0b32016-01-29 23:45:01 +00003222 struct _objc_property_list *class_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003223 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003224*/
Daniel Dunbar92992502008-08-15 22:20:32 +00003225void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00003226 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003227
Mike Stump18bb9282009-05-16 07:57:57 +00003228 // FIXME: This is poor design, the OCD should have a pointer to the category
3229 // decl. Additionally, note that Category can be null for the @implementation
3230 // w/o an @interface case. Sema should just create one for us as it does for
3231 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003232 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003233 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003234 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003235
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003236 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003237 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
3238 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003239
John McCall176f8922016-11-30 02:39:18 +00003240 ConstantInitBuilder Builder(CGM);
3241 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
Aaron Ballmanf26acce2014-03-13 19:50:17 +00003242
John McCall176f8922016-11-30 02:39:18 +00003243 enum {
3244 InstanceMethods,
3245 ClassMethods,
3246 NumMethodLists
3247 };
3248 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3249 for (const auto *MD : OCD->methods()) {
3250 Methods[unsigned(MD->isClassMethod())].push_back(MD);
3251 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003252
John McCall176f8922016-11-30 02:39:18 +00003253 Values.add(GetClassName(OCD->getName()));
3254 Values.add(GetClassName(Interface->getObjCRuntimeNameAsString()));
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00003255 LazySymbols.insert(Interface->getIdentifier());
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003256
John McCall176f8922016-11-30 02:39:18 +00003257 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3258 Methods[InstanceMethods]));
3259 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3260 Methods[ClassMethods]));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003261 if (Category) {
John McCall176f8922016-11-30 02:39:18 +00003262 Values.add(
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003263 EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003264 Category->protocol_begin(), Category->protocol_end()));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003265 } else {
John McCall176f8922016-11-30 02:39:18 +00003266 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003267 }
John McCall176f8922016-11-30 02:39:18 +00003268 Values.addInt(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003269
3270 // If there is no category @interface then there can be no properties.
3271 if (Category) {
John McCall176f8922016-11-30 02:39:18 +00003272 Values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
3273 OCD, Category, ObjCTypes, false));
3274 Values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
3275 OCD, Category, ObjCTypes, true));
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003276 } else {
John McCall176f8922016-11-30 02:39:18 +00003277 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3278 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003279 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003280
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003281 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003282 CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values,
John McCall7f416cc2015-09-08 08:05:57 +00003283 "__OBJC,__category,regular,no_dead_strip",
3284 CGM.getPointerAlign(), true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003285 DefinedCategories.push_back(GV);
Justin Lebar5e83dfe2016-10-21 21:45:01 +00003286 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003287 // method definition entries must be clear for next implementation.
3288 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003289}
3290
John McCallef19dbb2012-10-17 04:53:23 +00003291enum FragileClassFlags {
John McCall460ce582015-10-22 18:38:17 +00003292 /// Apparently: is not a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003293 FragileABI_Class_Factory = 0x00001,
John McCall460ce582015-10-22 18:38:17 +00003294
3295 /// Is a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003296 FragileABI_Class_Meta = 0x00002,
John McCall460ce582015-10-22 18:38:17 +00003297
3298 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003299 FragileABI_Class_HasCXXStructors = 0x02000,
John McCall460ce582015-10-22 18:38:17 +00003300
3301 /// Has hidden visibility.
John McCall09ec1ec2015-10-21 22:06:03 +00003302 FragileABI_Class_Hidden = 0x20000,
John McCall460ce582015-10-22 18:38:17 +00003303
3304 /// Class implementation was compiled under ARC.
3305 FragileABI_Class_CompiledByARC = 0x04000000,
3306
3307 /// Class implementation was compiled under MRC and has MRC weak ivars.
3308 /// Exclusive with CompiledByARC.
3309 FragileABI_Class_HasMRCWeakIvars = 0x08000000,
John McCallef19dbb2012-10-17 04:53:23 +00003310};
3311
3312enum NonFragileClassFlags {
3313 /// Is a meta-class.
3314 NonFragileABI_Class_Meta = 0x00001,
3315
3316 /// Is a root class.
3317 NonFragileABI_Class_Root = 0x00002,
3318
John McCall460ce582015-10-22 18:38:17 +00003319 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003320 NonFragileABI_Class_HasCXXStructors = 0x00004,
3321
3322 /// Has hidden visibility.
3323 NonFragileABI_Class_Hidden = 0x00010,
3324
3325 /// Has the exception attribute.
3326 NonFragileABI_Class_Exception = 0x00020,
3327
3328 /// (Obsolete) ARC-specific: this class has a .release_ivars method
3329 NonFragileABI_Class_HasIvarReleaser = 0x00040,
3330
3331 /// Class implementation was compiled under ARC.
John McCall0d54a172012-10-17 04:53:31 +00003332 NonFragileABI_Class_CompiledByARC = 0x00080,
3333
3334 /// Class has non-trivial destructors, but zero-initialization is okay.
John McCall460ce582015-10-22 18:38:17 +00003335 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100,
3336
3337 /// Class implementation was compiled under MRC and has MRC weak ivars.
3338 /// Exclusive with CompiledByARC.
3339 NonFragileABI_Class_HasMRCWeakIvars = 0x00200,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003340};
3341
John McCall460ce582015-10-22 18:38:17 +00003342static bool hasWeakMember(QualType type) {
3343 if (type.getObjCLifetime() == Qualifiers::OCL_Weak) {
3344 return true;
3345 }
3346
3347 if (auto recType = type->getAs<RecordType>()) {
3348 for (auto field : recType->getDecl()->fields()) {
3349 if (hasWeakMember(field->getType()))
3350 return true;
3351 }
3352 }
3353
3354 return false;
3355}
3356
3357/// For compatibility, we only want to set the "HasMRCWeakIvars" flag
3358/// (and actually fill in a layout string) if we really do have any
3359/// __weak ivars.
3360static bool hasMRCWeakIvars(CodeGenModule &CGM,
3361 const ObjCImplementationDecl *ID) {
3362 if (!CGM.getLangOpts().ObjCWeak) return false;
3363 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
3364
3365 for (const ObjCIvarDecl *ivar =
3366 ID->getClassInterface()->all_declared_ivar_begin();
3367 ivar; ivar = ivar->getNextIvar()) {
3368 if (hasWeakMember(ivar->getType()))
3369 return true;
3370 }
3371
3372 return false;
3373}
3374
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003375/*
3376 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003377 Class isa;
3378 Class super_class;
3379 const char *name;
3380 long version;
3381 long info;
3382 long instance_size;
3383 struct _objc_ivar_list *ivars;
3384 struct _objc_method_list *methods;
3385 struct _objc_cache *cache;
3386 struct _objc_protocol_list *protocols;
3387 // Objective-C 1.0 extensions (<rdr://4585769>)
3388 const char *ivar_layout;
3389 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003390 };
3391
3392 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003393*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003394void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003395 DefinedSymbols.insert(ID->getIdentifier());
3396
Chris Lattner86d7d912008-11-24 03:54:41 +00003397 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003398 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003399 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003400 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003401 llvm::Constant *Protocols =
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003402 EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(),
3403 Interface->all_referenced_protocol_begin(),
3404 Interface->all_referenced_protocol_end());
John McCallef19dbb2012-10-17 04:53:23 +00003405 unsigned Flags = FragileABI_Class_Factory;
John McCall0d54a172012-10-17 04:53:31 +00003406 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCallef19dbb2012-10-17 04:53:23 +00003407 Flags |= FragileABI_Class_HasCXXStructors;
John McCall09ec1ec2015-10-21 22:06:03 +00003408
John McCall460ce582015-10-22 18:38:17 +00003409 bool hasMRCWeak = false;
3410
John McCall09ec1ec2015-10-21 22:06:03 +00003411 if (CGM.getLangOpts().ObjCAutoRefCount)
3412 Flags |= FragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00003413 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
3414 Flags |= FragileABI_Class_HasMRCWeakIvars;
John McCall09ec1ec2015-10-21 22:06:03 +00003415
John McCall3fd13f062015-10-21 18:06:47 +00003416 CharUnits Size =
3417 CGM.getContext().getASTObjCImplementationLayout(ID).getSize();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003418
3419 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00003420 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003421 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003422
John McCall176f8922016-11-30 02:39:18 +00003423 enum {
3424 InstanceMethods,
3425 ClassMethods,
3426 NumMethodLists
3427 };
3428 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3429 for (const auto *MD : ID->methods()) {
3430 Methods[unsigned(MD->isClassMethod())].push_back(MD);
3431 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003432
Aaron Ballmand85eff42014-03-14 15:02:45 +00003433 for (const auto *PID : ID->property_impls()) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003434 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3435 ObjCPropertyDecl *PD = PID->getPropertyDecl();
3436
3437 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003438 if (GetMethodDefinition(MD))
3439 Methods[InstanceMethods].push_back(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003440 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003441 if (GetMethodDefinition(MD))
3442 Methods[InstanceMethods].push_back(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003443 }
3444 }
3445
John McCall176f8922016-11-30 02:39:18 +00003446 ConstantInitBuilder builder(CGM);
3447 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3448 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003449 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003450 // Record a reference to the super class.
3451 LazySymbols.insert(Super->getIdentifier());
3452
John McCall176f8922016-11-30 02:39:18 +00003453 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3454 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003455 } else {
John McCall176f8922016-11-30 02:39:18 +00003456 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003457 }
John McCall176f8922016-11-30 02:39:18 +00003458 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003459 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003460 values.addInt(ObjCTypes.LongTy, 0);
3461 values.addInt(ObjCTypes.LongTy, Flags);
3462 values.addInt(ObjCTypes.LongTy, Size.getQuantity());
3463 values.add(EmitIvarList(ID, false));
3464 values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods,
3465 Methods[InstanceMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003466 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003467 values.addNullPointer(ObjCTypes.CachePtrTy);
3468 values.add(Protocols);
3469 values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size));
3470 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3471 /*isMetaclass*/ false));
3472
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003473 std::string Name("OBJC_CLASS_");
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003474 Name += ClassName;
3475 const char *Section = "__OBJC,__class,regular,no_dead_strip";
3476 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003477 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003478 if (GV) {
3479 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3480 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003481 values.finishAndSetAsInitializer(GV);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003482 GV->setSection(Section);
John McCall7f416cc2015-09-08 08:05:57 +00003483 GV->setAlignment(CGM.getPointerAlign().getQuantity());
Rafael Espindola060062a2014-03-06 22:15:10 +00003484 CGM.addCompilerUsedGlobal(GV);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003485 } else
John McCall176f8922016-11-30 02:39:18 +00003486 GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003487 DefinedClasses.push_back(GV);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00003488 ImplementedClasses.push_back(Interface);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003489 // method definition entries must be clear for next implementation.
3490 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003491}
3492
3493llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3494 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00003495 ArrayRef<const ObjCMethodDecl*> Methods) {
John McCallef19dbb2012-10-17 04:53:23 +00003496 unsigned Flags = FragileABI_Class_Meta;
Micah Villmowdd31ca12012-10-08 16:25:52 +00003497 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003498
John McCall457a04e2010-10-22 21:05:15 +00003499 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003500 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003501
John McCall176f8922016-11-30 02:39:18 +00003502 ConstantInitBuilder builder(CGM);
3503 auto values = builder.beginStruct(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003504 // The isa for the metaclass is the root of the hierarchy.
3505 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3506 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3507 Root = Super;
John McCall176f8922016-11-30 02:39:18 +00003508 values.addBitCast(GetClassName(Root->getObjCRuntimeNameAsString()),
3509 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003510 // The super class for the metaclass is emitted as the name of the
3511 // super class. The runtime fixes this up to point to the
3512 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003513 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
John McCall176f8922016-11-30 02:39:18 +00003514 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3515 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003516 } else {
John McCall176f8922016-11-30 02:39:18 +00003517 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003518 }
John McCall176f8922016-11-30 02:39:18 +00003519 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003520 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003521 values.addInt(ObjCTypes.LongTy, 0);
3522 values.addInt(ObjCTypes.LongTy, Flags);
3523 values.addInt(ObjCTypes.LongTy, Size);
3524 values.add(EmitIvarList(ID, true));
3525 values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods,
3526 Methods));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003527 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003528 values.addNullPointer(ObjCTypes.CachePtrTy);
3529 values.add(Protocols);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003530 // ivar_layout for metaclass is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003531 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Renad0e7912016-01-29 19:22:54 +00003532 // The class extension is used to store class properties for metaclasses.
John McCall176f8922016-11-30 02:39:18 +00003533 values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/,
3534 /*isMetaclass*/true));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003535
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003536 std::string Name("OBJC_METACLASS_");
Benjamin Kramer1bbcbd02012-07-31 11:45:39 +00003537 Name += ID->getName();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003538
3539 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003540 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003541 if (GV) {
3542 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3543 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003544 values.finishAndSetAsInitializer(GV);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003545 } else {
John McCall176f8922016-11-30 02:39:18 +00003546 GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
3547 /*constant*/ false,
3548 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003549 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003550 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00003551 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003552
3553 return GV;
3554}
3555
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003556llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003557 std::string Name = "OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003558
Mike Stump18bb9282009-05-16 07:57:57 +00003559 // FIXME: Should we look these up somewhere other than the module. Its a bit
3560 // silly since we only generate these while processing an implementation, so
3561 // exactly one pointer would work if know when we entered/exitted an
3562 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003563
3564 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00003565 // Previously, metaclass with internal linkage may have been defined.
3566 // pass 'true' as 2nd argument so it is returned.
Rafael Espindola21039aa2014-02-27 16:26:32 +00003567 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3568 if (!GV)
3569 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003570 llvm::GlobalValue::PrivateLinkage, nullptr,
3571 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003572
3573 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3574 "Forward metaclass reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003575 return GV;
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003576}
3577
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003578llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003579 std::string Name = "OBJC_CLASS_" + ID->getNameAsString();
Rafael Espindola21039aa2014-02-27 16:26:32 +00003580 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3581
3582 if (!GV)
3583 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003584 llvm::GlobalValue::PrivateLinkage, nullptr,
3585 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003586
3587 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3588 "Forward class metadata reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003589 return GV;
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003590}
3591
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003592/*
John McCall3fd13f062015-10-21 18:06:47 +00003593 Emit a "class extension", which in this specific context means extra
3594 data that doesn't fit in the normal fragile-ABI class structure, and
3595 has nothing to do with the language concept of a class extension.
3596
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003597 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003598 uint32_t size;
3599 const char *weak_ivar_layout;
3600 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003601 };
3602*/
3603llvm::Constant *
John McCall3fd13f062015-10-21 18:06:47 +00003604CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
Manman Renad0e7912016-01-29 19:22:54 +00003605 CharUnits InstanceSize, bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00003606 bool isMetaclass) {
3607 // Weak ivar layout.
3608 llvm::Constant *layout;
3609 if (isMetaclass) {
3610 layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
3611 } else {
3612 layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
3613 hasMRCWeakIvars);
3614 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003615
John McCall176f8922016-11-30 02:39:18 +00003616 // Properties.
3617 llvm::Constant *propertyList =
3618 EmitPropertyList((isMetaclass ? Twine("\01l_OBJC_$_CLASS_PROP_LIST_")
3619 : Twine("\01l_OBJC_$_PROP_LIST_"))
3620 + ID->getName(),
3621 ID, ID->getClassInterface(), ObjCTypes, isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003622
3623 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00003624 if (layout->isNullValue() && propertyList->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003625 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003626 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003627
John McCall176f8922016-11-30 02:39:18 +00003628 uint64_t size =
3629 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3630
3631 ConstantInitBuilder builder(CGM);
3632 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3633 values.addInt(ObjCTypes.IntTy, size);
3634 values.add(layout);
3635 values.add(propertyList);
3636
3637 return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00003638 "__OBJC,__class_ext,regular,no_dead_strip",
3639 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003640}
3641
3642/*
3643 struct objc_ivar {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003644 char *ivar_name;
3645 char *ivar_type;
3646 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003647 };
3648
3649 struct objc_ivar_list {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003650 int ivar_count;
3651 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003652 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003653*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003654llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003655 bool ForClass) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003656 // When emitting the root class GCC emits ivar entries for the
3657 // actual class structure. It is not clear if we need to follow this
3658 // behavior; for now lets try and get away with not doing it. If so,
3659 // the cleanest solution would be to make up an ObjCInterfaceDecl
3660 // for the class.
3661 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00003662 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003663
Jordy Rosea91768e2011-07-22 02:08:32 +00003664 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003665
John McCall176f8922016-11-30 02:39:18 +00003666 ConstantInitBuilder builder(CGM);
3667 auto ivarList = builder.beginStruct();
3668 auto countSlot = ivarList.addPlaceholder();
3669 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3670
Jordy Rosea91768e2011-07-22 02:08:32 +00003671 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00003672 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00003673 // Ignore unnamed bit-fields.
3674 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003675 continue;
John McCall176f8922016-11-30 02:39:18 +00003676
3677 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3678 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3679 ivar.add(GetMethodVarType(IVD));
3680 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3681 ivar.finishAndAddTo(ivars);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003682 }
3683
3684 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00003685 auto count = ivars.size();
3686 if (count == 0) {
3687 ivars.abandon();
3688 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00003689 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003690 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003691
John McCall176f8922016-11-30 02:39:18 +00003692 ivars.finishAndAddTo(ivarList);
3693 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003694
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003695 llvm::GlobalVariable *GV;
3696 if (ForClass)
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003697 GV =
John McCall176f8922016-11-30 02:39:18 +00003698 CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003699 "__OBJC,__class_vars,regular,no_dead_strip",
3700 CGM.getPointerAlign(), true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003701 else
John McCall176f8922016-11-30 02:39:18 +00003702 GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003703 "__OBJC,__instance_vars,regular,no_dead_strip",
3704 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003705 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003706}
3707
John McCall176f8922016-11-30 02:39:18 +00003708/// Build a struct objc_method_description constant for the given method.
3709///
3710/// struct objc_method_description {
3711/// SEL method_name;
3712/// char *method_types;
3713/// };
3714void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
3715 const ObjCMethodDecl *MD) {
3716 auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy);
3717 description.addBitCast(GetMethodVarName(MD->getSelector()),
3718 ObjCTypes.SelectorPtrTy);
3719 description.add(GetMethodVarType(MD));
3720 description.finishAndAddTo(builder);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003721}
3722
John McCall176f8922016-11-30 02:39:18 +00003723/// Build a struct objc_method constant for the given method.
3724///
3725/// struct objc_method {
3726/// SEL method_name;
3727/// char *method_types;
3728/// void *method;
3729/// };
3730void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
3731 const ObjCMethodDecl *MD) {
3732 llvm::Function *fn = GetMethodDefinition(MD);
3733 assert(fn && "no definition registered for method");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003734
John McCall176f8922016-11-30 02:39:18 +00003735 auto method = builder.beginStruct(ObjCTypes.MethodTy);
3736 method.addBitCast(GetMethodVarName(MD->getSelector()),
3737 ObjCTypes.SelectorPtrTy);
3738 method.add(GetMethodVarType(MD));
3739 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
3740 method.finishAndAddTo(builder);
3741}
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003742
John McCall176f8922016-11-30 02:39:18 +00003743/// Build a struct objc_method_list or struct objc_method_description_list,
3744/// as appropriate.
3745///
3746/// struct objc_method_list {
3747/// struct objc_method_list *obsolete;
3748/// int count;
3749/// struct objc_method methods_list[count];
3750/// };
3751///
3752/// struct objc_method_description_list {
3753/// int count;
3754/// struct objc_method_description list[count];
3755/// };
3756llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3757 ArrayRef<const ObjCMethodDecl *> methods) {
3758 StringRef prefix;
3759 StringRef section;
3760 bool forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003761 switch (MLT) {
3762 case MethodListType::CategoryInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003763 prefix = "OBJC_CATEGORY_INSTANCE_METHODS_";
3764 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3765 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003766 break;
3767 case MethodListType::CategoryClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003768 prefix = "OBJC_CATEGORY_CLASS_METHODS_";
3769 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3770 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003771 break;
3772 case MethodListType::InstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003773 prefix = "OBJC_INSTANCE_METHODS_";
3774 section = "__OBJC,__inst_meth,regular,no_dead_strip";
3775 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003776 break;
3777 case MethodListType::ClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003778 prefix = "OBJC_CLASS_METHODS_";
3779 section = "__OBJC,__cls_meth,regular,no_dead_strip";
3780 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003781 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003782 case MethodListType::ProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003783 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_";
3784 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3785 forProtocol = true;
3786 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003787 case MethodListType::ProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003788 prefix = "OBJC_PROTOCOL_CLASS_METHODS_";
3789 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3790 forProtocol = true;
3791 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003792 case MethodListType::OptionalProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003793 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3794 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3795 forProtocol = true;
3796 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003797 case MethodListType::OptionalProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003798 prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3799 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3800 forProtocol = true;
3801 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003802 }
3803
John McCall176f8922016-11-30 02:39:18 +00003804 // Return null for empty list.
3805 if (methods.empty())
3806 return llvm::Constant::getNullValue(forProtocol
3807 ? ObjCTypes.MethodDescriptionListPtrTy
3808 : ObjCTypes.MethodListPtrTy);
3809
3810 // For protocols, this is an objc_method_description_list, which has
3811 // a slightly different structure.
3812 if (forProtocol) {
3813 ConstantInitBuilder builder(CGM);
3814 auto values = builder.beginStruct();
3815 values.addInt(ObjCTypes.IntTy, methods.size());
3816 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3817 for (auto MD : methods) {
3818 emitMethodDescriptionConstant(methodArray, MD);
3819 }
3820 methodArray.finishAndAddTo(values);
3821
3822 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3823 CGM.getPointerAlign(), true);
3824 return llvm::ConstantExpr::getBitCast(GV,
3825 ObjCTypes.MethodDescriptionListPtrTy);
3826 }
3827
3828 // Otherwise, it's an objc_method_list.
3829 ConstantInitBuilder builder(CGM);
3830 auto values = builder.beginStruct();
3831 values.addNullPointer(ObjCTypes.Int8PtrTy);
3832 values.addInt(ObjCTypes.IntTy, methods.size());
3833 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3834 for (auto MD : methods) {
3835 emitMethodConstant(methodArray, MD);
3836 }
3837 methodArray.finishAndAddTo(values);
3838
3839 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003840 CGM.getPointerAlign(), true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003841 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003842}
3843
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00003844llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003845 const ObjCContainerDecl *CD) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003846 SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00003847 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003848
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00003849 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00003850 llvm::FunctionType *MethodTy =
John McCalla729c622012-02-17 03:33:10 +00003851 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003852 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00003853 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003854 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00003855 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003856 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003857 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003858
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003859 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003860}
3861
Alp Toker541d5072014-06-07 23:30:53 +00003862llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
John McCall176f8922016-11-30 02:39:18 +00003863 ConstantStructBuilder &Init,
3864 StringRef Section,
3865 CharUnits Align,
3866 bool AddToUsed) {
3867 llvm::GlobalVariable *GV =
3868 Init.finishAndCreateGlobal(Name, Align, /*constant*/ false,
3869 llvm::GlobalValue::PrivateLinkage);
3870 if (!Section.empty())
3871 GV->setSection(Section);
3872 if (AddToUsed)
3873 CGM.addCompilerUsedGlobal(GV);
3874 return GV;
3875}
3876
3877llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
Alp Toker541d5072014-06-07 23:30:53 +00003878 llvm::Constant *Init,
3879 StringRef Section,
John McCall7f416cc2015-09-08 08:05:57 +00003880 CharUnits Align,
Alp Toker541d5072014-06-07 23:30:53 +00003881 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003882 llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003883 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00003884 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00003885 llvm::GlobalValue::PrivateLinkage, Init, Name);
Alp Toker541d5072014-06-07 23:30:53 +00003886 if (!Section.empty())
Daniel Dunbar30c65362009-03-09 20:09:19 +00003887 GV->setSection(Section);
John McCall7f416cc2015-09-08 08:05:57 +00003888 GV->setAlignment(Align.getQuantity());
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003889 if (AddToUsed)
Rafael Espindola060062a2014-03-06 22:15:10 +00003890 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003891 return GV;
3892}
3893
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003894llvm::GlobalVariable *
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003895CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type,
3896 bool ForceNonFragileABI,
3897 bool NullTerminate) {
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003898 StringRef Label;
3899 switch (Type) {
3900 case ObjCLabelType::ClassName: Label = "OBJC_CLASS_NAME_"; break;
3901 case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break;
3902 case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break;
3903 case ObjCLabelType::PropertyName: Label = "OBJC_PROP_NAME_ATTR_"; break;
3904 }
3905
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003906 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
3907
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003908 StringRef Section;
3909 switch (Type) {
3910 case ObjCLabelType::ClassName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003911 Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals"
3912 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003913 break;
3914 case ObjCLabelType::MethodVarName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003915 Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
3916 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003917 break;
3918 case ObjCLabelType::MethodVarType:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003919 Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals"
3920 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003921 break;
3922 case ObjCLabelType::PropertyName:
3923 Section = "__TEXT,__cstring,cstring_literals";
3924 break;
3925 }
3926
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003927 llvm::Constant *Value =
3928 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003929 llvm::GlobalVariable *GV =
Saleem Abdulrasool0c54dc82016-09-18 16:12:04 +00003930 new llvm::GlobalVariable(CGM.getModule(), Value->getType(),
3931 /*isConstant=*/true,
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003932 llvm::GlobalValue::PrivateLinkage, Value, Label);
Saleem Abdulrasool3f307512016-09-18 16:12:14 +00003933 if (CGM.getTriple().isOSBinFormatMachO())
3934 GV->setSection(Section);
3935 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003936 GV->setAlignment(CharUnits::One().getQuantity());
3937 CGM.addCompilerUsedGlobal(GV);
3938
3939 return GV;
3940}
3941
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003942llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003943 // Abuse this interface function as a place to finalize.
3944 FinishModule();
Craig Topper8a13c412014-05-21 05:09:00 +00003945 return nullptr;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003946}
3947
Chris Lattnerd4808922009-03-22 21:03:39 +00003948llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003949 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003950}
3951
Chris Lattnerd4808922009-03-22 21:03:39 +00003952llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003953 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003954}
3955
Ted Kremeneke65b0862012-03-06 20:05:56 +00003956llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
3957 bool copy) {
3958 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
3959}
3960
David Chisnall168b80f2010-12-26 22:13:16 +00003961llvm::Constant *CGObjCMac::GetGetStructFunction() {
3962 return ObjCTypes.getCopyStructFn();
3963}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00003964
David Chisnall168b80f2010-12-26 22:13:16 +00003965llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00003966 return ObjCTypes.getCopyStructFn();
3967}
3968
David Chisnall0d75e062012-12-17 18:54:24 +00003969llvm::Constant *CGObjCMac::GetCppAtomicObjectGetFunction() {
3970 return ObjCTypes.getCppAtomicObjectFunction();
3971}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00003972
David Chisnall0d75e062012-12-17 18:54:24 +00003973llvm::Constant *CGObjCMac::GetCppAtomicObjectSetFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00003974 return ObjCTypes.getCppAtomicObjectFunction();
3975}
3976
Chris Lattnerd4808922009-03-22 21:03:39 +00003977llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003978 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00003979}
3980
John McCallbd309292010-07-06 01:34:17 +00003981void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
3982 return EmitTryOrSynchronizedStmt(CGF, S);
3983}
3984
3985void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
3986 const ObjCAtSynchronizedStmt &S) {
3987 return EmitTryOrSynchronizedStmt(CGF, S);
3988}
3989
John McCall65bea082010-07-21 06:59:36 +00003990namespace {
David Blaikie7e70d682015-08-18 22:40:54 +00003991 struct PerformFragileFinally final : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00003992 const Stmt &S;
John McCall7f416cc2015-09-08 08:05:57 +00003993 Address SyncArgSlot;
3994 Address CallTryExitVar;
3995 Address ExceptionData;
John McCall65bea082010-07-21 06:59:36 +00003996 ObjCTypesHelper &ObjCTypes;
3997 PerformFragileFinally(const Stmt *S,
John McCall7f416cc2015-09-08 08:05:57 +00003998 Address SyncArgSlot,
3999 Address CallTryExitVar,
4000 Address ExceptionData,
John McCall65bea082010-07-21 06:59:36 +00004001 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00004002 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00004003 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4004
Craig Topper4f12f102014-03-12 06:41:41 +00004005 void Emit(CodeGenFunction &CGF, Flags flags) override {
John McCall65bea082010-07-21 06:59:36 +00004006 // Check whether we need to call objc_exception_try_exit.
4007 // In optimized code, this branch will always be folded.
4008 llvm::BasicBlock *FinallyCallExit =
4009 CGF.createBasicBlock("finally.call_exit");
4010 llvm::BasicBlock *FinallyNoCallExit =
4011 CGF.createBasicBlock("finally.no_call_exit");
4012 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
4013 FinallyCallExit, FinallyNoCallExit);
4014
4015 CGF.EmitBlock(FinallyCallExit);
John McCall882987f2013-02-28 19:01:20 +00004016 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004017 ExceptionData.getPointer());
John McCall65bea082010-07-21 06:59:36 +00004018
4019 CGF.EmitBlock(FinallyNoCallExit);
4020
4021 if (isa<ObjCAtTryStmt>(S)) {
4022 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00004023 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
John McCall638d4f52013-04-03 00:56:07 +00004024 // Don't try to do the @finally if this is an EH cleanup.
4025 if (flags.isForEHCleanup()) return;
4026
John McCallcebe0ca2010-08-11 00:16:14 +00004027 // Save the current cleanup destination in case there's
4028 // control flow inside the finally statement.
4029 llvm::Value *CurCleanupDest =
4030 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
4031
John McCall65bea082010-07-21 06:59:36 +00004032 CGF.EmitStmt(FinallyStmt->getFinallyBody());
4033
John McCallcebe0ca2010-08-11 00:16:14 +00004034 if (CGF.HaveInsertPoint()) {
4035 CGF.Builder.CreateStore(CurCleanupDest,
4036 CGF.getNormalCleanupDestSlot());
4037 } else {
4038 // Currently, the end of the cleanup must always exist.
4039 CGF.EnsureInsertPoint();
4040 }
4041 }
John McCall65bea082010-07-21 06:59:36 +00004042 } else {
4043 // Emit objc_sync_exit(expr); as finally's sole statement for
4044 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00004045 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall882987f2013-02-28 19:01:20 +00004046 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg);
John McCall65bea082010-07-21 06:59:36 +00004047 }
4048 }
4049 };
John McCall42227ed2010-07-31 23:20:56 +00004050
4051 class FragileHazards {
4052 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004053 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00004054 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
4055
4056 llvm::InlineAsm *ReadHazard;
4057 llvm::InlineAsm *WriteHazard;
4058
4059 llvm::FunctionType *GetAsmFnType();
4060
4061 void collectLocals();
4062 void emitReadHazard(CGBuilderTy &Builder);
4063
4064 public:
4065 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00004066
John McCall42227ed2010-07-31 23:20:56 +00004067 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00004068 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004069 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004070} // end anonymous namespace
John McCall42227ed2010-07-31 23:20:56 +00004071
4072/// Create the fragile-ABI read and write hazards based on the current
4073/// state of the function, which is presumed to be immediately prior
4074/// to a @try block. These hazards are used to maintain correct
4075/// semantics in the face of optimization and the fragile ABI's
4076/// cavalier use of setjmp/longjmp.
4077FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
4078 collectLocals();
4079
4080 if (Locals.empty()) return;
4081
4082 // Collect all the blocks in the function.
4083 for (llvm::Function::iterator
4084 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
4085 BlocksBeforeTry.insert(&*I);
4086
4087 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4088
4089 // Create a read hazard for the allocas. This inhibits dead-store
4090 // optimizations and forces the values to memory. This hazard is
4091 // inserted before any 'throwing' calls in the protected scope to
4092 // reflect the possibility that the variables might be read from the
4093 // catch block if the call throws.
4094 {
4095 std::string Constraint;
4096 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
4097 if (I) Constraint += ',';
4098 Constraint += "*m";
4099 }
4100
4101 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
4102 }
4103
4104 // Create a write hazard for the allocas. This inhibits folding
4105 // loads across the hazard. This hazard is inserted at the
4106 // beginning of the catch path to reflect the possibility that the
4107 // variables might have been written within the protected scope.
4108 {
4109 std::string Constraint;
4110 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
4111 if (I) Constraint += ',';
4112 Constraint += "=*m";
4113 }
4114
4115 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
4116 }
4117}
4118
4119/// Emit a write hazard at the current location.
4120void FragileHazards::emitWriteHazard() {
4121 if (Locals.empty()) return;
4122
John McCall882987f2013-02-28 19:01:20 +00004123 CGF.EmitNounwindRuntimeCall(WriteHazard, Locals);
John McCall42227ed2010-07-31 23:20:56 +00004124}
4125
John McCall42227ed2010-07-31 23:20:56 +00004126void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
4127 assert(!Locals.empty());
John McCall882987f2013-02-28 19:01:20 +00004128 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4129 call->setDoesNotThrow();
4130 call->setCallingConv(CGF.getRuntimeCC());
John McCall42227ed2010-07-31 23:20:56 +00004131}
4132
4133/// Emit read hazards in all the protected blocks, i.e. all the blocks
4134/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00004135void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00004136 if (Locals.empty()) return;
4137
John McCall7f416cc2015-09-08 08:05:57 +00004138 CGBuilderTy Builder(CGF, CGF.getLLVMContext());
John McCall42227ed2010-07-31 23:20:56 +00004139
4140 // Iterate through all blocks, skipping those prior to the try.
4141 for (llvm::Function::iterator
4142 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
4143 llvm::BasicBlock &BB = *FI;
4144 if (BlocksBeforeTry.count(&BB)) continue;
4145
4146 // Walk through all the calls in the block.
4147 for (llvm::BasicBlock::iterator
4148 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
4149 llvm::Instruction &I = *BI;
4150
4151 // Ignore instructions that aren't non-intrinsic calls.
4152 // These are the only calls that can possibly call longjmp.
4153 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
4154 if (isa<llvm::IntrinsicInst>(I))
4155 continue;
4156
4157 // Ignore call sites marked nounwind. This may be questionable,
4158 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
4159 llvm::CallSite CS(&I);
4160 if (CS.doesNotThrow()) continue;
4161
John McCall2dd7d442010-08-04 05:59:32 +00004162 // Insert a read hazard before the call. This will ensure that
4163 // any writes to the locals are performed before making the
4164 // call. If the call throws, then this is sufficient to
4165 // guarantee correctness as long as it doesn't also write to any
4166 // locals.
John McCall42227ed2010-07-31 23:20:56 +00004167 Builder.SetInsertPoint(&BB, BI);
4168 emitReadHazard(Builder);
4169 }
4170 }
4171}
4172
4173static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
4174 if (V) S.insert(V);
4175}
4176
John McCall7f416cc2015-09-08 08:05:57 +00004177static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) {
4178 if (V.isValid()) S.insert(V.getPointer());
4179}
4180
John McCall42227ed2010-07-31 23:20:56 +00004181void FragileHazards::collectLocals() {
4182 // Compute a set of allocas to ignore.
4183 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
4184 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
4185 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00004186
4187 // Collect all the allocas currently in the function. This is
4188 // probably way too aggressive.
4189 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
4190 for (llvm::BasicBlock::iterator
4191 I = Entry.begin(), E = Entry.end(); I != E; ++I)
4192 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
4193 Locals.push_back(&*I);
4194}
4195
4196llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004197 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00004198 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
4199 tys[i] = Locals[i]->getType();
4200 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00004201}
4202
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004203/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004204
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004205 Objective-C setjmp-longjmp (sjlj) Exception Handling
4206 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004207
John McCallbd309292010-07-06 01:34:17 +00004208 A catch buffer is a setjmp buffer plus:
4209 - a pointer to the exception that was caught
4210 - a pointer to the previous exception data buffer
4211 - two pointers of reserved storage
4212 Therefore catch buffers form a stack, with a pointer to the top
4213 of the stack kept in thread-local storage.
4214
4215 objc_exception_try_enter pushes a catch buffer onto the EH stack.
4216 objc_exception_try_exit pops the given catch buffer, which is
4217 required to be the top of the EH stack.
4218 objc_exception_throw pops the top of the EH stack, writes the
4219 thrown exception into the appropriate field, and longjmps
4220 to the setjmp buffer. It crashes the process (with a printf
4221 and an abort()) if there are no catch buffers on the stack.
4222 objc_exception_extract just reads the exception pointer out of the
4223 catch buffer.
4224
4225 There's no reason an implementation couldn't use a light-weight
4226 setjmp here --- something like __builtin_setjmp, but API-compatible
4227 with the heavyweight setjmp. This will be more important if we ever
4228 want to implement correct ObjC/C++ exception interactions for the
4229 fragile ABI.
4230
4231 Note that for this use of setjmp/longjmp to be correct, we may need
4232 to mark some local variables volatile: if a non-volatile local
4233 variable is modified between the setjmp and the longjmp, it has
4234 indeterminate value. For the purposes of LLVM IR, it may be
4235 sufficient to make loads and stores within the @try (to variables
4236 declared outside the @try) volatile. This is necessary for
4237 optimized correctness, but is not currently being done; this is
4238 being tracked as rdar://problem/8160285
4239
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004240 The basic framework for a @try-catch-finally is as follows:
4241 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004242 objc_exception_data d;
4243 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00004244 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004245
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004246 objc_exception_try_enter(&d);
4247 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004248 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004249 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004250 // exception path
4251 id _caught = objc_exception_extract(&d);
4252
4253 // enter new try scope for handlers
4254 if (!setjmp(d.jmp_buf)) {
4255 ... match exception and execute catch blocks ...
4256
4257 // fell off end, rethrow.
4258 _rethrow = _caught;
4259 ... jump-through-finally to finally_rethrow ...
4260 } else {
4261 // exception in catch block
4262 _rethrow = objc_exception_extract(&d);
4263 _call_try_exit = false;
4264 ... jump-through-finally to finally_rethrow ...
4265 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004266 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004267 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004268
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004269 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00004270 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004271 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00004272
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004273 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004274 ... dispatch to finally destination ...
4275
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004276 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004277 objc_exception_throw(_rethrow);
4278
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004279 finally_end:
4280 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004281
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004282 This framework differs slightly from the one gcc uses, in that gcc
4283 uses _rethrow to determine if objc_exception_try_exit should be called
4284 and if the object should be rethrown. This breaks in the face of
4285 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004286
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004287 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004288
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004289 - If there are no catch blocks, then we avoid emitting the second
4290 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004291
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004292 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
4293 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004294
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004295 - FIXME: If there is no @finally block we can do a few more
4296 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004297
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004298 Rethrows and Jumps-Through-Finally
4299 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004300
John McCallbd309292010-07-06 01:34:17 +00004301 '@throw;' is supported by pushing the currently-caught exception
4302 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004303
John McCallbd309292010-07-06 01:34:17 +00004304 Branches through the @finally block are handled with an ordinary
4305 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
4306 exceptions are not compatible with C++ exceptions, and this is
4307 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004308
John McCallbd309292010-07-06 01:34:17 +00004309 @synchronized(expr) { stmt; } is emitted as if it were:
4310 id synch_value = expr;
4311 objc_sync_enter(synch_value);
4312 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004313*/
4314
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00004315void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
4316 const Stmt &S) {
4317 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00004318
4319 // A destination for the fall-through edges of the catch handlers to
4320 // jump to.
4321 CodeGenFunction::JumpDest FinallyEnd =
4322 CGF.getJumpDestInCurrentScope("finally.end");
4323
4324 // A destination for the rethrow edge of the catch handlers to jump
4325 // to.
4326 CodeGenFunction::JumpDest FinallyRethrow =
4327 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004328
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004329 // For @synchronized, call objc_sync_enter(sync.expr). The
4330 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00004331 // @synchronized. We can't avoid a temp here because we need the
4332 // value to be preserved. If the backend ever does liveness
4333 // correctly after setjmp, this will be unnecessary.
John McCall7f416cc2015-09-08 08:05:57 +00004334 Address SyncArgSlot = Address::invalid();
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004335 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00004336 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004337 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4338 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004339 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);
John McCall2dd7d442010-08-04 05:59:32 +00004340
John McCall7f416cc2015-09-08 08:05:57 +00004341 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(),
4342 CGF.getPointerAlign(), "sync.arg");
John McCall2dd7d442010-08-04 05:59:32 +00004343 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004344 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004345
John McCall2dd7d442010-08-04 05:59:32 +00004346 // Allocate memory for the setjmp buffer. This needs to be kept
4347 // live throughout the try and catch blocks.
John McCall7f416cc2015-09-08 08:05:57 +00004348 Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
4349 CGF.getPointerAlign(),
4350 "exceptiondata.ptr");
John McCall2dd7d442010-08-04 05:59:32 +00004351
John McCall42227ed2010-07-31 23:20:56 +00004352 // Create the fragile hazards. Note that this will not capture any
4353 // of the allocas required for exception processing, but will
4354 // capture the current basic block (which extends all the way to the
4355 // setjmp call) as "before the @try".
4356 FragileHazards Hazards(CGF);
4357
John McCallbd309292010-07-06 01:34:17 +00004358 // Create a flag indicating whether the cleanup needs to call
4359 // objc_exception_try_exit. This is true except when
4360 // - no catches match and we're branching through the cleanup
4361 // just to rethrow the exception, or
4362 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00004363 // The setjmp-safety rule here is that we should always store to this
4364 // variable in a place that dominates the branch through the cleanup
4365 // without passing through any setjmps.
John McCall7f416cc2015-09-08 08:05:57 +00004366 Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
4367 CharUnits::One(),
4368 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004369
John McCall9916e3f2010-10-04 23:42:51 +00004370 // A slot containing the exception to rethrow. Only needed when we
4371 // have both a @catch and a @finally.
John McCall7f416cc2015-09-08 08:05:57 +00004372 Address PropagatingExnVar = Address::invalid();
John McCall9916e3f2010-10-04 23:42:51 +00004373
John McCallbd309292010-07-06 01:34:17 +00004374 // Push a normal cleanup to leave the try scope.
John McCall638d4f52013-04-03 00:56:07 +00004375 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00004376 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00004377 CallTryExitVar,
4378 ExceptionData,
4379 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00004380
4381 // Enter a try block:
4382 // - Call objc_exception_try_enter to push ExceptionData on top of
4383 // the EH stack.
Nico Weber6307cf02015-02-26 20:43:00 +00004384 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004385 ExceptionData.getPointer());
John McCallbd309292010-07-06 01:34:17 +00004386
4387 // - Call setjmp on the exception data buffer.
4388 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
4389 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
David Blaikie6b2a8302015-04-03 17:47:16 +00004390 llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
John McCall7f416cc2015-09-08 08:05:57 +00004391 ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes,
4392 "setjmp_buffer");
Nico Weber6307cf02015-02-26 20:43:00 +00004393 llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
4394 ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004395 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00004396
4397 // If setjmp returned 0, enter the protected block; otherwise,
4398 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00004399 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
4400 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00004401 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00004402 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4403 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004404
John McCallbd309292010-07-06 01:34:17 +00004405 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004406 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00004407 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004408 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00004409 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00004410
4411 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004412
John McCallbd309292010-07-06 01:34:17 +00004413 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00004414 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004415
John McCall42227ed2010-07-31 23:20:56 +00004416 // Don't optimize loads of the in-scope locals across this point.
4417 Hazards.emitWriteHazard();
4418
John McCallbd309292010-07-06 01:34:17 +00004419 // For a @synchronized (or a @try with no catches), just branch
4420 // through the cleanup to the rethrow block.
4421 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4422 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00004423 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004424 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00004425
4426 // Otherwise, we have to match against the caught exceptions.
4427 } else {
John McCall2dd7d442010-08-04 05:59:32 +00004428 // Retrieve the exception object. We may emit multiple blocks but
4429 // nothing can cross this so the value is already in SSA form.
4430 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004431 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004432 ExceptionData.getPointer(), "caught");
John McCall2dd7d442010-08-04 05:59:32 +00004433
John McCallbd309292010-07-06 01:34:17 +00004434 // Push the exception to rethrow onto the EH value stack for the
4435 // benefit of any @throws in the handlers.
4436 CGF.ObjCEHValueStack.push_back(Caught);
4437
Douglas Gregor96c79492010-04-23 22:50:49 +00004438 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004439
Craig Topper8a13c412014-05-21 05:09:00 +00004440 bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr);
John McCallbd309292010-07-06 01:34:17 +00004441
Craig Topper8a13c412014-05-21 05:09:00 +00004442 llvm::BasicBlock *CatchBlock = nullptr;
4443 llvm::BasicBlock *CatchHandler = nullptr;
John McCall2dd7d442010-08-04 05:59:32 +00004444 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00004445 // Save the currently-propagating exception before
4446 // objc_exception_try_enter clears the exception slot.
4447 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
John McCall7f416cc2015-09-08 08:05:57 +00004448 CGF.getPointerAlign(),
John McCall9916e3f2010-10-04 23:42:51 +00004449 "propagating_exception");
4450 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
4451
John McCall2dd7d442010-08-04 05:59:32 +00004452 // Enter a new exception try block (in case a @catch block
4453 // throws an exception).
John McCall882987f2013-02-28 19:01:20 +00004454 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004455 ExceptionData.getPointer());
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004456
John McCall2dd7d442010-08-04 05:59:32 +00004457 llvm::CallInst *SetJmpResult =
John McCall882987f2013-02-28 19:01:20 +00004458 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(),
4459 SetJmpBuffer, "setjmp.result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004460 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004461
John McCall2dd7d442010-08-04 05:59:32 +00004462 llvm::Value *Threw =
4463 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4464
4465 CatchBlock = CGF.createBasicBlock("catch");
4466 CatchHandler = CGF.createBasicBlock("catch_for_catch");
4467 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4468
4469 CGF.EmitBlock(CatchBlock);
4470 }
4471
4472 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004473
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004474 // Handle catch list. As a special case we check if everything is
4475 // matched and avoid generating code for falling off the end if
4476 // so.
4477 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00004478 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
4479 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004480
Douglas Gregor46a572b2010-04-26 16:46:50 +00004481 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Craig Topper8a13c412014-05-21 05:09:00 +00004482 const ObjCObjectPointerType *OPT = nullptr;
Daniel Dunbar523208f2008-09-27 07:36:24 +00004483
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004484 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004485 if (!CatchParam) {
4486 AllMatched = true;
4487 } else {
John McCall9dd450b2009-09-21 23:43:11 +00004488 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004489
John McCallbd309292010-07-06 01:34:17 +00004490 // catch(id e) always matches under this ABI, since only
4491 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00004492 // FIXME: For the time being we also match id<X>; this should
4493 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00004494 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004495 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004496 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004497
John McCallbd309292010-07-06 01:34:17 +00004498 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004499 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00004500 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4501
Anders Carlsson9396a892008-09-11 09:15:33 +00004502 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00004503 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004504 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00004505
4506 // These types work out because ConvertType(id) == i8*.
John McCall17f02752015-10-30 00:56:02 +00004507 EmitInitOfCatchParam(CGF, Caught, CatchParam);
Anders Carlsson9396a892008-09-11 09:15:33 +00004508 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004509
Anders Carlsson9396a892008-09-11 09:15:33 +00004510 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004511
4512 // The scope of the catch variable ends right here.
4513 CatchVarCleanups.ForceCleanup();
4514
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004515 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004516 break;
4517 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004518
Steve Naroff7cae42b2009-07-10 23:34:53 +00004519 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00004520 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00004521
4522 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00004523 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
4524 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004525
4526 // Check if the @catch block matches the exception object.
John McCall882987f2013-02-28 19:01:20 +00004527 llvm::Value *Class = EmitClassRef(CGF, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004528
John McCall882987f2013-02-28 19:01:20 +00004529 llvm::Value *matchArgs[] = { Class, Caught };
John McCallbd309292010-07-06 01:34:17 +00004530 llvm::CallInst *Match =
John McCall882987f2013-02-28 19:01:20 +00004531 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(),
4532 matchArgs, "match");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004533
John McCallbd309292010-07-06 01:34:17 +00004534 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
4535 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004536
4537 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00004538 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004539
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004540 // Emit the @catch block.
4541 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00004542
4543 // Collect any cleanups for the catch variable. The scope lasts until
4544 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00004545 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00004546
John McCall1c9c3fd2010-10-15 04:57:14 +00004547 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004548 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004549
John McCallbd309292010-07-06 01:34:17 +00004550 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004551 llvm::Value *Tmp =
4552 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004553 CGF.ConvertType(CatchParam->getType()));
John McCall17f02752015-10-30 00:56:02 +00004554 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004555
Anders Carlsson9396a892008-09-11 09:15:33 +00004556 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004557
4558 // We're done with the catch variable.
4559 CatchVarCleanups.ForceCleanup();
4560
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004561 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004562
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004563 CGF.EmitBlock(NextCatchBlock);
4564 }
4565
John McCallbd309292010-07-06 01:34:17 +00004566 CGF.ObjCEHValueStack.pop_back();
4567
John McCall2dd7d442010-08-04 05:59:32 +00004568 // If nothing wanted anything to do with the caught exception,
4569 // kill the extract call.
4570 if (Caught->use_empty())
4571 Caught->eraseFromParent();
4572
4573 if (!AllMatched)
4574 CGF.EmitBranchThroughCleanup(FinallyRethrow);
4575
4576 if (HasFinally) {
4577 // Emit the exception handler for the @catch blocks.
4578 CGF.EmitBlock(CatchHandler);
4579
4580 // In theory we might now need a write hazard, but actually it's
4581 // unnecessary because there's no local-accessing code between
4582 // the try's write hazard and here.
4583 //Hazards.emitWriteHazard();
4584
John McCall9916e3f2010-10-04 23:42:51 +00004585 // Extract the new exception and save it to the
4586 // propagating-exception slot.
John McCall7f416cc2015-09-08 08:05:57 +00004587 assert(PropagatingExnVar.isValid());
John McCall9916e3f2010-10-04 23:42:51 +00004588 llvm::CallInst *NewCaught =
John McCall882987f2013-02-28 19:01:20 +00004589 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004590 ExceptionData.getPointer(), "caught");
John McCall9916e3f2010-10-04 23:42:51 +00004591 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4592
John McCall2dd7d442010-08-04 05:59:32 +00004593 // Don't pop the catch handler; the throw already did.
4594 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004595 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004596 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004597 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004598
John McCall42227ed2010-07-31 23:20:56 +00004599 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00004600 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004601
John McCallbd309292010-07-06 01:34:17 +00004602 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00004603 CGF.Builder.restoreIP(TryFallthroughIP);
4604 if (CGF.HaveInsertPoint())
4605 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00004606 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00004607 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004608
John McCallbd309292010-07-06 01:34:17 +00004609 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00004610 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00004611 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00004612 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00004613 // If we have a propagating-exception variable, check it.
4614 llvm::Value *PropagatingExn;
John McCall7f416cc2015-09-08 08:05:57 +00004615 if (PropagatingExnVar.isValid()) {
John McCall9916e3f2010-10-04 23:42:51 +00004616 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00004617
John McCall9916e3f2010-10-04 23:42:51 +00004618 // Otherwise, just look in the buffer for the exception to throw.
4619 } else {
4620 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004621 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004622 ExceptionData.getPointer());
John McCall9916e3f2010-10-04 23:42:51 +00004623 PropagatingExn = Caught;
4624 }
4625
John McCall882987f2013-02-28 19:01:20 +00004626 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(),
4627 PropagatingExn);
John McCallbd309292010-07-06 01:34:17 +00004628 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00004629 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004630
John McCall42227ed2010-07-31 23:20:56 +00004631 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004632}
4633
4634void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004635 const ObjCAtThrowStmt &S,
4636 bool ClearInsertionPoint) {
Anders Carlssone005aa12008-09-09 16:16:55 +00004637 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004638
Anders Carlssone005aa12008-09-09 16:16:55 +00004639 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00004640 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004641 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004642 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00004643 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004644 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004645 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00004646 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00004647 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004648
John McCall882987f2013-02-28 19:01:20 +00004649 CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
John McCallbd309292010-07-06 01:34:17 +00004650 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004651 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004652
4653 // Clear the insertion point to indicate we are in unreachable code.
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004654 if (ClearInsertionPoint)
4655 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004656}
4657
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004658/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004659/// object: objc_read_weak (id *src)
4660///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004661llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004662 Address AddrWeakObj) {
4663 llvm::Type* DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004664 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4665 ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004666 llvm::Value *read_weak =
4667 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004668 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00004669 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004670 return read_weak;
4671}
4672
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004673/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4674/// objc_assign_weak (id src, id *dst)
4675///
4676void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004677 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004678 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004679 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004680 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004681 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004682 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4683 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004684 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4685 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004686 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4687 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004688 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00004689 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4690 args, "weakassign");
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004691}
4692
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004693/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4694/// objc_assign_global (id src, id *dst)
4695///
4696void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004697 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00004698 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004699 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004700 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004701 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004702 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004703 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4704 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004705 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4706 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004707 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4708 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004709 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00004710 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00004711 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4712 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00004713 else
John McCall882987f2013-02-28 19:01:20 +00004714 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4715 args, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004716}
4717
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004718/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004719/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004720///
4721void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004722 llvm::Value *src, Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004723 llvm::Value *ivarOffset) {
4724 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00004725 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004726 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004727 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004728 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004729 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4730 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004731 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4732 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004733 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4734 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004735 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00004736 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004737}
4738
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004739/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
4740/// objc_assign_strongCast (id src, id *dst)
4741///
4742void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004743 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004744 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004745 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004746 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004747 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004748 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4749 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004750 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4751 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004752 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4753 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004754 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00004755 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004756 args, "strongassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004757}
4758
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004759void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004760 Address DestPtr,
4761 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00004762 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004763 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
4764 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004765 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size };
John McCall882987f2013-02-28 19:01:20 +00004766 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004767}
4768
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004769/// EmitObjCValueForIvar - Code Gen for ivar reference.
4770///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004771LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4772 QualType ObjectTy,
4773 llvm::Value *BaseValue,
4774 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004775 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00004776 const ObjCInterfaceDecl *ID =
4777 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00004778 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4779 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004780}
4781
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004782llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00004783 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004784 const ObjCIvarDecl *Ivar) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004785 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4786 return llvm::ConstantInt::get(
4787 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
4788 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004789}
4790
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004791/* *** Private Interface *** */
4792
4793/// EmitImageInfo - Emit the image info marker used to encode some module
4794/// level information.
4795///
4796/// See: <rdr://4810609&4810587&4810587>
4797/// struct IMAGE_INFO {
4798/// unsigned version;
4799/// unsigned flags;
4800/// };
4801enum ImageInfoFlags {
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004802 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004803 eImageInfo_GarbageCollected = (1 << 1),
4804 eImageInfo_GCOnly = (1 << 2),
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004805 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
Daniel Dunbar75e909f2009-04-20 07:11:47 +00004806
Daniel Dunbar5e639272010-04-25 20:39:01 +00004807 // A flag indicating that the module has no instances of a @synthesize of a
4808 // superclass variable. <rdar://problem/6803242>
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004809 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
Manman Ren96df0b32016-01-29 23:45:01 +00004810 eImageInfo_ImageIsSimulated = (1 << 5),
4811 eImageInfo_ClassProperties = (1 << 6)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004812};
4813
Daniel Dunbar5e639272010-04-25 20:39:01 +00004814void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004815 unsigned version = 0; // Version is unused?
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004816 const char *Section = (ObjCABI == 1) ?
4817 "__OBJC, __image_info,regular" :
4818 "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004819
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004820 // Generate module-level named metadata to convey this information to the
4821 // linker and code-gen.
4822 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004823
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004824 // Add the ObjC ABI version to the module flags.
4825 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
4826 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
4827 version);
4828 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
4829 llvm::MDString::get(VMContext,Section));
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004830
David Blaikiebbafb8a2012-03-11 07:00:24 +00004831 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004832 // Non-GC overrides those files which specify GC.
4833 Mod.addModuleFlag(llvm::Module::Override,
4834 "Objective-C Garbage Collection", (uint32_t)0);
4835 } else {
4836 // Add the ObjC garbage collection value.
4837 Mod.addModuleFlag(llvm::Module::Error,
4838 "Objective-C Garbage Collection",
4839 eImageInfo_GarbageCollected);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004840
David Blaikiebbafb8a2012-03-11 07:00:24 +00004841 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004842 // Add the ObjC GC Only value.
4843 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
4844 eImageInfo_GCOnly);
4845
4846 // Require that GC be specified and set to eImageInfo_GarbageCollected.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +00004847 llvm::Metadata *Ops[2] = {
4848 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
4849 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
4850 llvm::Type::getInt32Ty(VMContext), eImageInfo_GarbageCollected))};
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004851 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
4852 llvm::MDNode::get(VMContext, Ops));
4853 }
4854 }
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004855
4856 // Indicate whether we're compiling this to run on a simulator.
4857 const llvm::Triple &Triple = CGM.getTarget().getTriple();
Tim Northover756447a2015-10-30 16:30:36 +00004858 if ((Triple.isiOS() || Triple.isWatchOS()) &&
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004859 (Triple.getArch() == llvm::Triple::x86 ||
4860 Triple.getArch() == llvm::Triple::x86_64))
4861 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
4862 eImageInfo_ImageIsSimulated);
Manman Ren96df0b32016-01-29 23:45:01 +00004863
4864 // Indicate whether we are generating class properties.
4865 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Class Properties",
4866 eImageInfo_ClassProperties);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004867}
4868
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004869// struct objc_module {
4870// unsigned long version;
4871// unsigned long size;
4872// const char *name;
4873// Symtab symtab;
4874// };
4875
4876// FIXME: Get from somewhere
4877static const int ModuleVersion = 7;
4878
4879void CGObjCMac::EmitModuleInfo() {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004880 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004881
John McCall176f8922016-11-30 02:39:18 +00004882 ConstantInitBuilder builder(CGM);
4883 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
4884 values.addInt(ObjCTypes.LongTy, ModuleVersion);
4885 values.addInt(ObjCTypes.LongTy, Size);
4886 // This used to be the filename, now it is unused. <rdr://4327263>
4887 values.add(GetClassName(StringRef("")));
4888 values.add(EmitModuleSymbols());
4889 CreateMetadataVar("OBJC_MODULES", values,
John McCall7f416cc2015-09-08 08:05:57 +00004890 "__OBJC,__module_info,regular,no_dead_strip",
4891 CGM.getPointerAlign(), true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004892}
4893
4894llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004895 unsigned NumClasses = DefinedClasses.size();
4896 unsigned NumCategories = DefinedCategories.size();
4897
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004898 // Return null if no symbols were defined.
4899 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00004900 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004901
John McCall176f8922016-11-30 02:39:18 +00004902 ConstantInitBuilder builder(CGM);
4903 auto values = builder.beginStruct();
4904 values.addInt(ObjCTypes.LongTy, 0);
4905 values.addNullPointer(ObjCTypes.SelectorPtrTy);
4906 values.addInt(ObjCTypes.ShortTy, NumClasses);
4907 values.addInt(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004908
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004909 // The runtime expects exactly the list of defined classes followed
4910 // by the list of defined categories, in a single array.
John McCall176f8922016-11-30 02:39:18 +00004911 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00004912 for (unsigned i=0; i<NumClasses; i++) {
4913 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
4914 assert(ID);
4915 if (ObjCImplementationDecl *IMP = ID->getImplementation())
4916 // We are implementing a weak imported interface. Give it external linkage
4917 if (ID->isWeakImported() && !IMP->isWeakImported())
4918 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
John McCall176f8922016-11-30 02:39:18 +00004919
4920 array.addBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00004921 }
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004922 for (unsigned i=0; i<NumCategories; i++)
John McCall176f8922016-11-30 02:39:18 +00004923 array.addBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004924
John McCall176f8922016-11-30 02:39:18 +00004925 array.finishAndAddTo(values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004926
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00004927 llvm::GlobalVariable *GV = CreateMetadataVar(
John McCall176f8922016-11-30 02:39:18 +00004928 "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip",
John McCall7f416cc2015-09-08 08:05:57 +00004929 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00004930 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004931}
4932
John McCall882987f2013-02-28 19:01:20 +00004933llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
4934 IdentifierInfo *II) {
John McCall31168b02011-06-15 23:02:42 +00004935 LazySymbols.insert(II);
4936
4937 llvm::GlobalVariable *&Entry = ClassReferences[II];
4938
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004939 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004940 llvm::Constant *Casted =
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00004941 llvm::ConstantExpr::getBitCast(GetClassName(II->getName()),
John McCall31168b02011-06-15 23:02:42 +00004942 ObjCTypes.ClassPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00004943 Entry = CreateMetadataVar(
4944 "OBJC_CLASS_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00004945 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
4946 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004947 }
John McCall31168b02011-06-15 23:02:42 +00004948
John McCall7f416cc2015-09-08 08:05:57 +00004949 return CGF.Builder.CreateAlignedLoad(Entry, CGF.getPointerAlign());
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004950}
4951
John McCall882987f2013-02-28 19:01:20 +00004952llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00004953 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00004954 // If the class has the objc_runtime_visible attribute, we need to
4955 // use the Objective-C runtime to get the class.
4956 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
4957 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
4958
John McCall882987f2013-02-28 19:01:20 +00004959 return EmitClassRefFromId(CGF, ID->getIdentifier());
John McCall31168b02011-06-15 23:02:42 +00004960}
4961
John McCall882987f2013-02-28 19:01:20 +00004962llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00004963 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
John McCall882987f2013-02-28 19:01:20 +00004964 return EmitClassRefFromId(CGF, II);
John McCall31168b02011-06-15 23:02:42 +00004965}
4966
John McCall7f416cc2015-09-08 08:05:57 +00004967llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
4968 return CGF.Builder.CreateLoad(EmitSelectorAddr(CGF, Sel));
4969}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004970
John McCall7f416cc2015-09-08 08:05:57 +00004971Address CGObjCMac::EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel) {
4972 CharUnits Align = CGF.getPointerAlign();
4973
4974 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004975 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004976 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00004977 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004978 ObjCTypes.SelectorPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00004979 Entry = CreateMetadataVar(
4980 "OBJC_SELECTOR_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00004981 "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true);
Michael Gottesman5c205962013-02-05 23:08:45 +00004982 Entry->setExternallyInitialized(true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004983 }
4984
John McCall7f416cc2015-09-08 08:05:57 +00004985 return Address(Entry, Align);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004986}
4987
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00004988llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
4989 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
4990 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004991 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00004992 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004993}
4994
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004995llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
4996 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
4997 I = MethodDefinitions.find(MD);
4998 if (I != MethodDefinitions.end())
4999 return I->second;
5000
Craig Topper8a13c412014-05-21 05:09:00 +00005001 return nullptr;
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005002}
5003
Fariborz Jahanian01dff422009-03-05 19:17:31 +00005004/// GetIvarLayoutName - Returns a unique constant for the given
5005/// ivar layout bitmap.
5006llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005007 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00005008 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00005009}
5010
John McCall3fd13f062015-10-21 18:06:47 +00005011void IvarLayoutBuilder::visitRecord(const RecordType *RT,
5012 CharUnits offset) {
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005013 const RecordDecl *RD = RT->getDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005014
John McCall3fd13f062015-10-21 18:06:47 +00005015 // If this is a union, remember that we had one, because it might mess
5016 // up the ordering of layout entries.
5017 if (RD->isUnion())
5018 IsDisordered = true;
5019
5020 const ASTRecordLayout *recLayout = nullptr;
5021 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5022 [&](const FieldDecl *field) -> CharUnits {
5023 if (!recLayout)
5024 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5025 auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
5026 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5027 });
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005028}
5029
John McCall3fd13f062015-10-21 18:06:47 +00005030template <class Iterator, class GetOffsetFn>
5031void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
5032 CharUnits aggregateOffset,
5033 const GetOffsetFn &getOffset) {
5034 for (; begin != end; ++begin) {
5035 auto field = *begin;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005036
John McCall3fd13f062015-10-21 18:06:47 +00005037 // Skip over bitfields.
5038 if (field->isBitField()) {
5039 continue;
5040 }
5041
5042 // Compute the offset of the field within the aggregate.
5043 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5044
5045 visitField(field, fieldOffset);
5046 }
5047}
5048
5049/// Collect layout information for the given fields into IvarsInfo.
5050void IvarLayoutBuilder::visitField(const FieldDecl *field,
5051 CharUnits fieldOffset) {
5052 QualType fieldType = field->getType();
5053
5054 // Drill down into arrays.
5055 uint64_t numElts = 1;
5056 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5057 numElts *= arrayType->getSize().getZExtValue();
5058 fieldType = arrayType->getElementType();
5059 }
5060
5061 assert(!fieldType->isArrayType() && "ivar of non-constant array type?");
5062
5063 // If we ended up with a zero-sized array, we've done what we can do within
5064 // the limits of this layout encoding.
5065 if (numElts == 0) return;
5066
5067 // Recurse if the base element type is a record type.
5068 if (auto recType = fieldType->getAs<RecordType>()) {
5069 size_t oldEnd = IvarsInfo.size();
5070
5071 visitRecord(recType, fieldOffset);
5072
5073 // If we have an array, replicate the first entry's layout information.
5074 auto numEltEntries = IvarsInfo.size() - oldEnd;
5075 if (numElts != 1 && numEltEntries != 0) {
5076 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5077 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5078 // Copy the last numEltEntries onto the end of the array, adjusting
5079 // each for the element size.
5080 for (size_t i = 0; i != numEltEntries; ++i) {
5081 auto firstEntry = IvarsInfo[oldEnd + i];
5082 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5083 firstEntry.SizeInWords));
5084 }
5085 }
5086 }
5087
Fariborz Jahanian524bb202009-03-10 16:22:08 +00005088 return;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00005089 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005090
John McCall3fd13f062015-10-21 18:06:47 +00005091 // Classify the element type.
5092 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005093
John McCall3fd13f062015-10-21 18:06:47 +00005094 // If it matches what we're looking for, add an entry.
5095 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
5096 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5097 assert(CGM.getContext().getTypeSizeInChars(fieldType)
5098 == CGM.getPointerSize());
5099 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5100 }
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00005101}
5102
John McCall3fd13f062015-10-21 18:06:47 +00005103/// buildBitmap - This routine does the horsework of taking the offsets of
5104/// strong/weak references and creating a bitmap. The bitmap is also
5105/// returned in the given buffer, suitable for being passed to \c dump().
5106llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5107 llvm::SmallVectorImpl<unsigned char> &buffer) {
5108 // The bitmap is a series of skip/scan instructions, aligned to word
5109 // boundaries. The skip is performed first.
5110 const unsigned char MaxNibble = 0xF;
5111 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5112 const unsigned char ScanMask = 0x0F, ScanShift = 0;
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005113
John McCall3fd13f062015-10-21 18:06:47 +00005114 assert(!IvarsInfo.empty() && "generating bitmap for no data");
5115
5116 // Sort the ivar info on byte position in case we encounterred a
5117 // union nested in the ivar list.
5118 if (IsDisordered) {
5119 // This isn't a stable sort, but our algorithm should handle it fine.
5120 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5121 } else {
Craig Toppera3467052016-01-03 19:43:20 +00005122 assert(std::is_sorted(IvarsInfo.begin(), IvarsInfo.end()));
John McCall3fd13f062015-10-21 18:06:47 +00005123 }
5124 assert(IvarsInfo.back().Offset < InstanceEnd);
5125
5126 assert(buffer.empty());
5127
5128 // Skip the next N words.
5129 auto skip = [&](unsigned numWords) {
5130 assert(numWords > 0);
5131
5132 // Try to merge into the previous byte. Since scans happen second, we
5133 // can't do this if it includes a scan.
5134 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5135 unsigned lastSkip = buffer.back() >> SkipShift;
5136 if (lastSkip < MaxNibble) {
5137 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5138 numWords -= claimed;
5139 lastSkip += claimed;
5140 buffer.back() = (lastSkip << SkipShift);
5141 }
5142 }
5143
5144 while (numWords >= MaxNibble) {
5145 buffer.push_back(MaxNibble << SkipShift);
5146 numWords -= MaxNibble;
5147 }
5148 if (numWords) {
5149 buffer.push_back(numWords << SkipShift);
5150 }
5151 };
5152
5153 // Scan the next N words.
5154 auto scan = [&](unsigned numWords) {
5155 assert(numWords > 0);
5156
5157 // Try to merge into the previous byte. Since scans happen second, we can
5158 // do this even if it includes a skip.
5159 if (!buffer.empty()) {
5160 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5161 if (lastScan < MaxNibble) {
5162 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5163 numWords -= claimed;
5164 lastScan += claimed;
5165 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5166 }
5167 }
5168
5169 while (numWords >= MaxNibble) {
5170 buffer.push_back(MaxNibble << ScanShift);
5171 numWords -= MaxNibble;
5172 }
5173 if (numWords) {
5174 buffer.push_back(numWords << ScanShift);
5175 }
5176 };
5177
5178 // One past the end of the last scan.
5179 unsigned endOfLastScanInWords = 0;
5180 const CharUnits WordSize = CGM.getPointerSize();
5181
5182 // Consider all the scan requests.
5183 for (auto &request : IvarsInfo) {
5184 CharUnits beginOfScan = request.Offset - InstanceBegin;
5185
5186 // Ignore scan requests that don't start at an even multiple of the
5187 // word size. We can't encode them.
5188 if ((beginOfScan % WordSize) != 0) continue;
5189
5190 // Ignore scan requests that start before the instance start.
5191 // This assumes that scans never span that boundary. The boundary
5192 // isn't the true start of the ivars, because in the fragile-ARC case
5193 // it's rounded up to word alignment, but the test above should leave
5194 // us ignoring that possibility.
5195 if (beginOfScan.isNegative()) {
5196 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5197 continue;
5198 }
5199
5200 unsigned beginOfScanInWords = beginOfScan / WordSize;
5201 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5202
5203 // If the scan starts some number of words after the last one ended,
5204 // skip forward.
5205 if (beginOfScanInWords > endOfLastScanInWords) {
5206 skip(beginOfScanInWords - endOfLastScanInWords);
5207
5208 // Otherwise, start scanning where the last left off.
5209 } else {
5210 beginOfScanInWords = endOfLastScanInWords;
5211
5212 // If that leaves us with nothing to scan, ignore this request.
5213 if (beginOfScanInWords >= endOfScanInWords) continue;
5214 }
5215
5216 // Scan to the end of the request.
5217 assert(beginOfScanInWords < endOfScanInWords);
5218 scan(endOfScanInWords - beginOfScanInWords);
5219 endOfLastScanInWords = endOfScanInWords;
5220 }
5221
John McCallf5ea0722015-10-29 23:36:14 +00005222 if (buffer.empty())
5223 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5224
John McCall3fd13f062015-10-21 18:06:47 +00005225 // For GC layouts, emit a skip to the end of the allocation so that we
5226 // have precise information about the entire thing. This isn't useful
5227 // or necessary for the ARC-style layout strings.
5228 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5229 unsigned lastOffsetInWords =
5230 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5231 if (lastOffsetInWords > endOfLastScanInWords) {
5232 skip(lastOffsetInWords - endOfLastScanInWords);
5233 }
5234 }
5235
5236 // Null terminate the string.
5237 buffer.push_back(0);
5238
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005239 auto *Entry = CGObjC.CreateCStringLiteral(
5240 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
John McCall3fd13f062015-10-21 18:06:47 +00005241 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005242}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005243
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005244/// BuildIvarLayout - Builds ivar layout bitmap for the class
5245/// implementation for the __strong or __weak case.
5246/// The layout map displays which words in ivar list must be skipped
5247/// and which must be scanned by GC (see below). String is built of bytes.
5248/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
5249/// of words to skip and right nibble is count of words to scan. So, each
5250/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
5251/// represented by a 0x00 byte which also ends the string.
5252/// 1. when ForStrongLayout is true, following ivars are scanned:
5253/// - id, Class
5254/// - object *
5255/// - __strong anything
5256///
5257/// 2. When ForStrongLayout is false, following ivars are scanned:
5258/// - __weak anything
5259///
John McCall3fd13f062015-10-21 18:06:47 +00005260llvm::Constant *
5261CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5262 CharUnits beginOffset, CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +00005263 bool ForStrongLayout, bool HasMRCWeakIvars) {
5264 // If this is MRC, and we're either building a strong layout or there
5265 // are no weak ivars, bail out early.
Chris Lattnerece04092012-02-07 00:39:47 +00005266 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikiebbafb8a2012-03-11 07:00:24 +00005267 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
John McCall460ce582015-10-22 18:38:17 +00005268 !CGM.getLangOpts().ObjCAutoRefCount &&
5269 (ForStrongLayout || !HasMRCWeakIvars))
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005270 return llvm::Constant::getNullValue(PtrTy);
5271
Jordy Rosea91768e2011-07-22 02:08:32 +00005272 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
John McCall3fd13f062015-10-21 18:06:47 +00005273 SmallVector<const ObjCIvarDecl*, 32> ivars;
5274
5275 // GC layout strings include the complete object layout, possibly
5276 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5277 // up.
5278 //
5279 // ARC layout strings only include the class's ivars. In non-fragile
John McCallf5ea0722015-10-29 23:36:14 +00005280 // runtimes, that means starting at InstanceStart, rounded up to word
5281 // alignment. In fragile runtimes, there's no InstanceStart, so it means
John McCalld80218f2015-11-19 02:27:55 +00005282 // starting at the offset of the first ivar, rounded up to word alignment.
John McCall460ce582015-10-22 18:38:17 +00005283 //
5284 // MRC weak layout strings follow the ARC style.
John McCall3fd13f062015-10-21 18:06:47 +00005285 CharUnits baseOffset;
John McCall460ce582015-10-22 18:38:17 +00005286 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Jordy Rosea91768e2011-07-22 02:08:32 +00005287 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005288 IVD; IVD = IVD->getNextIvar())
John McCall3fd13f062015-10-21 18:06:47 +00005289 ivars.push_back(IVD);
5290
5291 if (isNonFragileABI()) {
5292 baseOffset = beginOffset; // InstanceStart
John McCalld80218f2015-11-19 02:27:55 +00005293 } else if (!ivars.empty()) {
5294 baseOffset =
5295 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
John McCall3fd13f062015-10-21 18:06:47 +00005296 } else {
5297 baseOffset = CharUnits::Zero();
5298 }
John McCallf5ea0722015-10-29 23:36:14 +00005299
Rui Ueyama83aa9792016-01-14 21:00:27 +00005300 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005301 }
5302 else {
John McCall3fd13f062015-10-21 18:06:47 +00005303 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005304
John McCall3fd13f062015-10-21 18:06:47 +00005305 baseOffset = CharUnits::Zero();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005306 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005307
John McCall3fd13f062015-10-21 18:06:47 +00005308 if (ivars.empty())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005309 return llvm::Constant::getNullValue(PtrTy);
5310
John McCall3fd13f062015-10-21 18:06:47 +00005311 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005312
John McCall3fd13f062015-10-21 18:06:47 +00005313 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5314 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5315 return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
5316 });
5317
5318 if (!builder.hasBitmapData())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005319 return llvm::Constant::getNullValue(PtrTy);
John McCall3fd13f062015-10-21 18:06:47 +00005320
5321 llvm::SmallVector<unsigned char, 4> buffer;
5322 llvm::Constant *C = builder.buildBitmap(*this, buffer);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005323
John McCallf5ea0722015-10-29 23:36:14 +00005324 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005325 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005326 ForStrongLayout ? "strong" : "weak",
Ben Langmuire013bdc2014-07-11 00:43:47 +00005327 OMD->getClassInterface()->getName().str().c_str());
John McCall3fd13f062015-10-21 18:06:47 +00005328 builder.dump(buffer);
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005329 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005330 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00005331}
5332
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005333llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005334 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
Chris Lattner3def9ae2012-02-06 22:16:34 +00005335 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005336 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005337 Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
Owen Anderson170229f2009-07-14 23:10:40 +00005338 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005339}
5340
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005341// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005342llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005343 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5344}
5345
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005346llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005347 std::string TypeStr;
5348 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5349
5350 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005351 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005352 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005353 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005354}
5355
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005356llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5357 bool Extended) {
John McCall843dfcc2016-11-29 21:57:00 +00005358 std::string TypeStr =
5359 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005360
5361 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbar3241fae2009-04-14 23:14:47 +00005362 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005363 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005364 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005365}
5366
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005367// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005368llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005369 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005370 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005371 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
Owen Anderson170229f2009-07-14 23:10:40 +00005372 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005373}
5374
5375// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00005376// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005377llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005378CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5379 const Decl *Container) {
John McCall843dfcc2016-11-29 21:57:00 +00005380 std::string TypeStr =
5381 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005382 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5383}
5384
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005385void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005386 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005387 SmallVectorImpl<char> &Name) {
Daniel Dunbard2386812009-10-19 01:21:19 +00005388 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00005389 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00005390 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
5391 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005392 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00005393 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer2f569922012-02-07 11:57:45 +00005394 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00005395 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00005396}
5397
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005398void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005399 EmitModuleInfo();
5400
Daniel Dunbarc475d422008-10-29 22:36:39 +00005401 // Emit the dummy bodies for any protocols which were referenced but
5402 // never defined.
John McCall176f8922016-11-30 02:39:18 +00005403 for (auto &entry : Protocols) {
5404 llvm::GlobalVariable *global = entry.second;
5405 if (global->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00005406 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005407
John McCall176f8922016-11-30 02:39:18 +00005408 ConstantInitBuilder builder(CGM);
5409 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5410 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5411 values.add(GetClassName(entry.first->getName()));
5412 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5413 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5414 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5415 values.finishAndSetAsInitializer(global);
5416 CGM.addCompilerUsedGlobal(global);
Daniel Dunbarc475d422008-10-29 22:36:39 +00005417 }
5418
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005419 // Add assembler directives to add lazy undefined symbol references
5420 // for classes which are referenced but not defined. This is
5421 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00005422 //
5423 // FIXME: It would be nice if we had an LLVM construct for this.
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005424 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5425 CGM.getTriple().isOSBinFormatMachO()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005426 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00005427 Asm += CGM.getModule().getModuleInlineAsm();
5428 if (!Asm.empty() && Asm.back() != '\n')
5429 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005430
Daniel Dunbard027a922009-09-07 00:20:42 +00005431 llvm::raw_svector_ostream OS(Asm);
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005432 for (const auto *Sym : DefinedSymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005433 OS << "\t.objc_class_name_" << Sym->getName() << "=0\n"
5434 << "\t.globl .objc_class_name_" << Sym->getName() << "\n";
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005435 for (const auto *Sym : LazySymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005436 OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n";
5437 for (const auto &Category : DefinedCategoryNames)
5438 OS << "\t.objc_category_name_" << Category << "=0\n"
5439 << "\t.globl .objc_category_name_" << Category << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00005440
Daniel Dunbard027a922009-09-07 00:20:42 +00005441 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005442 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005443}
5444
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005445CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00005446 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5447 ObjCEmptyVtableVar(nullptr) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005448 ObjCABI = 2;
5449}
5450
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005451/* *** */
5452
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005453ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Craig Topper8a13c412014-05-21 05:09:00 +00005454 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00005455{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005456 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5457 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005458
John McCall176f8922016-11-30 02:39:18 +00005459 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5460 IntTy = CGM.IntTy;
5461 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
Chris Lattnerece04092012-02-07 00:39:47 +00005462 Int8PtrTy = CGM.Int8PtrTy;
5463 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005464
Tim Northover238b5082014-03-29 13:42:40 +00005465 // arm64 targets use "int" ivar offset variables. All others,
5466 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
Tim Northover40956e62014-07-23 12:32:58 +00005467 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
Tim Northover238b5082014-03-29 13:42:40 +00005468 IvarOffsetVarTy = IntTy;
5469 else
5470 IvarOffsetVarTy = LongTy;
5471
John McCall176f8922016-11-30 02:39:18 +00005472 ObjectPtrTy =
5473 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5474 PtrObjectPtrTy =
5475 llvm::PointerType::getUnqual(ObjectPtrTy);
5476 SelectorPtrTy =
5477 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005478
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005479 // I'm not sure I like this. The implicit coordination is a bit
5480 // gross. We should solve this in a reasonable fashion because this
5481 // is a pretty common task (match some runtime data structure with
5482 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005483
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005484 // FIXME: This is leaked.
5485 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005486
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005487 // struct _objc_super {
5488 // id self;
5489 // Class cls;
5490 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00005491 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005492 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005493 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005494 &Ctx.Idents.get("_objc_super"));
Craig Topper8a13c412014-05-21 05:09:00 +00005495 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5496 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5497 false, ICIS_NoInit));
5498 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5499 nullptr, Ctx.getObjCClassType(), nullptr,
5500 nullptr, false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005501 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005502
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005503 SuperCTy = Ctx.getTagDeclType(RD);
5504 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005505
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005506 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005507 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5508
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005509 // struct _prop_t {
5510 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005511 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005512 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005513 PropertyTy = llvm::StructType::create("struct._prop_t",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005514 Int8PtrTy, Int8PtrTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005515
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005516 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005517 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005518 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005519 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005520 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005521 PropertyListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005522 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005523 llvm::ArrayType::get(PropertyTy, 0), nullptr);
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005524 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005525 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005526
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005527 // struct _objc_method {
5528 // SEL _cmd;
5529 // char *method_type;
5530 // char *_imp;
5531 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005532 MethodTy = llvm::StructType::create("struct._objc_method",
5533 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005534 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005535
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005536 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00005537 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005538 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005539}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005540
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005541ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005542 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005543 // struct _objc_method_description {
5544 // SEL name;
5545 // char *types;
5546 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005547 MethodDescriptionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005548 llvm::StructType::create("struct._objc_method_description",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005549 SelectorPtrTy, Int8PtrTy, nullptr);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005550
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005551 // struct _objc_method_description_list {
5552 // int count;
5553 // struct _objc_method_description[1];
5554 // }
Reid Kleckneree7cf842014-12-01 22:02:27 +00005555 MethodDescriptionListTy = llvm::StructType::create(
5556 "struct._objc_method_description_list", IntTy,
5557 llvm::ArrayType::get(MethodDescriptionTy, 0), nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005558
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005559 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005560 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005561 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005562
Daniel Dunbarb036db82008-08-13 03:21:16 +00005563 // Protocol description structures
5564
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005565 // struct _objc_protocol_extension {
5566 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5567 // struct _objc_method_description_list *optional_instance_methods;
5568 // struct _objc_method_description_list *optional_class_methods;
5569 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005570 // const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00005571 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005572 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005573 ProtocolExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005574 llvm::StructType::create("struct._objc_protocol_extension",
5575 IntTy, MethodDescriptionListPtrTy,
5576 MethodDescriptionListPtrTy, PropertyListPtrTy,
Manman Rence7bff52016-01-29 23:46:55 +00005577 Int8PtrPtrTy, PropertyListPtrTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005578
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005579 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005580 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005581
Daniel Dunbarc475d422008-10-29 22:36:39 +00005582 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00005583
Chris Lattnera5f58b02011-07-09 17:41:47 +00005584 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005585 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00005586
Chris Lattnera5f58b02011-07-09 17:41:47 +00005587 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005588 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005589 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005590 LongTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00005591 llvm::ArrayType::get(ProtocolTy, 0),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005592 nullptr);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005593
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005594 // struct _objc_protocol {
5595 // struct _objc_protocol_extension *isa;
5596 // char *protocol_name;
5597 // struct _objc_protocol **_objc_protocol_list;
5598 // struct _objc_method_description_list *instance_methods;
5599 // struct _objc_method_description_list *class_methods;
5600 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005601 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5602 llvm::PointerType::getUnqual(ProtocolListTy),
5603 MethodDescriptionListPtrTy,
5604 MethodDescriptionListPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005605 nullptr);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005606
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005607 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005608 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005609
Owen Anderson9793f0e2009-07-29 22:16:19 +00005610 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005611
5612 // Class description structures
5613
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005614 // struct _objc_ivar {
5615 // char *ivar_name;
5616 // char *ivar_type;
5617 // int ivar_offset;
5618 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005619 IvarTy = llvm::StructType::create("struct._objc_ivar",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005620 Int8PtrTy, Int8PtrTy, IntTy, nullptr);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005621
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005622 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005623 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005624 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005625 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005626
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005627 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005628 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005629 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005630 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005631
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005632 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005633 ClassExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005634 llvm::StructType::create("struct._objc_class_extension",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005635 IntTy, Int8PtrTy, PropertyListPtrTy, nullptr);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005636 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005637
Chris Lattner5ec04a52011-08-12 17:43:31 +00005638 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005639
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005640 // struct _objc_class {
5641 // Class isa;
5642 // Class super_class;
5643 // char *name;
5644 // long version;
5645 // long info;
5646 // long instance_size;
5647 // struct _objc_ivar_list *ivars;
5648 // struct _objc_method_list *methods;
5649 // struct _objc_cache *cache;
5650 // struct _objc_protocol_list *protocols;
5651 // char *ivar_layout;
5652 // struct _objc_class_ext *ext;
5653 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005654 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
5655 llvm::PointerType::getUnqual(ClassTy),
5656 Int8PtrTy,
5657 LongTy,
5658 LongTy,
5659 LongTy,
5660 IvarListPtrTy,
5661 MethodListPtrTy,
5662 CachePtrTy,
5663 ProtocolListPtrTy,
5664 Int8PtrTy,
5665 ClassExtensionPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005666 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005667
Owen Anderson9793f0e2009-07-29 22:16:19 +00005668 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005669
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005670 // struct _objc_category {
5671 // char *category_name;
5672 // char *class_name;
5673 // struct _objc_method_list *instance_method;
5674 // struct _objc_method_list *class_method;
Manman Renb3736772016-01-25 22:37:47 +00005675 // struct _objc_protocol_list *protocols;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005676 // uint32_t size; // sizeof(struct _objc_category)
5677 // struct _objc_property_list *instance_properties;// category's @property
Manman Ren96df0b32016-01-29 23:45:01 +00005678 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005679 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005680 CategoryTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005681 llvm::StructType::create("struct._objc_category",
5682 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5683 MethodListPtrTy, ProtocolListPtrTy,
Manman Ren96df0b32016-01-29 23:45:01 +00005684 IntTy, PropertyListPtrTy, PropertyListPtrTy,
5685 nullptr);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005686
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005687 // Global metadata structures
5688
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005689 // struct _objc_symtab {
5690 // long sel_ref_cnt;
5691 // SEL *refs;
5692 // short cls_def_cnt;
5693 // short cat_def_cnt;
5694 // char *defs[cls_def_cnt + cat_def_cnt];
5695 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005696 SymtabTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005697 llvm::StructType::create("struct._objc_symtab",
5698 LongTy, SelectorPtrTy, ShortTy, ShortTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005699 llvm::ArrayType::get(Int8PtrTy, 0), nullptr);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005700 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005701
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00005702 // struct _objc_module {
5703 // long version;
5704 // long size; // sizeof(struct _objc_module)
5705 // char *name;
5706 // struct _objc_symtab* symtab;
5707 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005708 ModuleTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005709 llvm::StructType::create("struct._objc_module",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005710 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, nullptr);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00005711
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005712
Mike Stump18bb9282009-05-16 07:57:57 +00005713 // FIXME: This is the size of the setjmp buffer and should be target
5714 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00005715 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005716
Anders Carlsson9ff22482008-09-09 10:10:21 +00005717 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00005718 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005719
5720 ExceptionDataTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005721 llvm::StructType::create("struct._objc_exception_data",
Chris Lattnerece04092012-02-07 00:39:47 +00005722 llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005723 StackPtrTy, nullptr);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005724}
5725
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005726ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005727 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005728 // struct _method_list_t {
5729 // uint32_t entsize; // sizeof(struct _objc_method)
5730 // uint32_t method_count;
5731 // struct _objc_method method_list[method_count];
5732 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005733 MethodListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005734 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005735 llvm::ArrayType::get(MethodTy, 0), nullptr);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005736 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005737 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005738
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005739 // struct _protocol_t {
5740 // id isa; // NULL
5741 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005742 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005743 // const struct method_list_t * const instance_methods;
5744 // const struct method_list_t * const class_methods;
5745 // const struct method_list_t *optionalInstanceMethods;
5746 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005747 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005748 // const uint32_t size; // sizeof(struct _protocol_t)
5749 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005750 // const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00005751 // const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00005752 // const struct _prop_list_t * class_properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005753 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005754
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005755 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005756 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005757 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005758
Chris Lattnera5f58b02011-07-09 17:41:47 +00005759 ProtocolnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005760 llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
5761 llvm::PointerType::getUnqual(ProtocolListnfABITy),
5762 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5763 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005764 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
Manman Rence7bff52016-01-29 23:46:55 +00005765 Int8PtrTy, PropertyListPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005766 nullptr);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005767
5768 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005769 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005770
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005771 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005772 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005773 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005774 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005775 ProtocolListnfABITy->setBody(LongTy,
5776 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005777 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005778
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005779 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005780 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005781
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005782 // struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00005783 // unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005784 // char *name;
5785 // char *type;
5786 // uint32_t alignment;
5787 // uint32_t size;
5788 // }
Tim Northover238b5082014-03-29 13:42:40 +00005789 IvarnfABITy = llvm::StructType::create(
5790 "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005791 Int8PtrTy, Int8PtrTy, IntTy, IntTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005792
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005793 // struct _ivar_list_t {
5794 // uint32 entsize; // sizeof(struct _ivar_t)
5795 // uint32 count;
5796 // struct _iver_t list[count];
5797 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005798 IvarListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005799 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005800 llvm::ArrayType::get(IvarnfABITy, 0), nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005801
Owen Anderson9793f0e2009-07-29 22:16:19 +00005802 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005803
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005804 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005805 // uint32_t const flags;
5806 // uint32_t const instanceStart;
5807 // uint32_t const instanceSize;
5808 // uint32_t const reserved; // only when building for 64bit targets
5809 // const uint8_t * const ivarLayout;
5810 // const char *const name;
5811 // const struct _method_list_t * const baseMethods;
5812 // const struct _objc_protocol_list *const baseProtocols;
5813 // const struct _ivar_list_t *const ivars;
5814 // const uint8_t * const weakIvarLayout;
5815 // const struct _prop_list_t * const properties;
5816 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005817
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005818 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattner5ec04a52011-08-12 17:43:31 +00005819 ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
5820 IntTy, IntTy, IntTy, Int8PtrTy,
5821 Int8PtrTy, MethodListnfABIPtrTy,
5822 ProtocolListnfABIPtrTy,
5823 IvarListnfABIPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005824 Int8PtrTy, PropertyListPtrTy,
5825 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005826
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005827 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00005828 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00005829 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
5830 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005831
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005832 // struct _class_t {
5833 // struct _class_t *isa;
5834 // struct _class_t * const superclass;
5835 // void *cache;
5836 // IMP *vtable;
5837 // struct class_ro_t *ro;
5838 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005839
Chris Lattner5ec04a52011-08-12 17:43:31 +00005840 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005841 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
5842 llvm::PointerType::getUnqual(ClassnfABITy),
5843 CachePtrTy,
5844 llvm::PointerType::getUnqual(ImpnfABITy),
5845 llvm::PointerType::getUnqual(ClassRonfABITy),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005846 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005847
Fariborz Jahanian71394042009-01-23 23:53:38 +00005848 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005849 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005850
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005851 // struct _category_t {
5852 // const char * const name;
5853 // struct _class_t *const cls;
5854 // const struct _method_list_t * const instance_methods;
5855 // const struct _method_list_t * const class_methods;
5856 // const struct _protocol_list_t * const protocols;
5857 // const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00005858 // const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00005859 // const uint32_t size;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00005860 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005861 CategorynfABITy = llvm::StructType::create("struct._category_t",
5862 Int8PtrTy, ClassnfABIPtrTy,
5863 MethodListnfABIPtrTy,
5864 MethodListnfABIPtrTy,
5865 ProtocolListnfABIPtrTy,
5866 PropertyListPtrTy,
Manman Ren96df0b32016-01-29 23:45:01 +00005867 PropertyListPtrTy,
Manman Ren42ff3902016-02-24 17:49:50 +00005868 IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005869 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005870
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005871 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005872 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5873 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005874
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005875 // MessageRefTy - LLVM for:
5876 // struct _message_ref_t {
5877 // IMP messenger;
5878 // SEL name;
5879 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005880
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005881 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00005882 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005883 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005884 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005885 &Ctx.Idents.get("_message_ref_t"));
Craig Topper8a13c412014-05-21 05:09:00 +00005886 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5887 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
Richard Smith2b013182012-06-10 03:12:00 +00005888 ICIS_NoInit));
Craig Topper8a13c412014-05-21 05:09:00 +00005889 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5890 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
5891 false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005892 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005893
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005894 MessageRefCTy = Ctx.getTagDeclType(RD);
5895 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
5896 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005897
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005898 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005899 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005900
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005901 // SuperMessageRefTy - LLVM for:
5902 // struct _super_message_ref_t {
5903 // SUPER_IMP messenger;
5904 // SEL name;
5905 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005906 SuperMessageRefTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005907 llvm::StructType::create("struct._super_message_ref_t",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005908 ImpnfABITy, SelectorPtrTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005909
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005910 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005911 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005912
Daniel Dunbarb1559a42009-03-01 04:46:24 +00005913
5914 // struct objc_typeinfo {
5915 // const void** vtable; // objc_ehtype_vtable + 2
5916 // const char* name; // c++ typeinfo string
5917 // Class cls;
5918 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005919 EHTypeTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005920 llvm::StructType::create("struct._objc_typeinfo",
5921 llvm::PointerType::getUnqual(Int8PtrTy),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005922 Int8PtrTy, ClassnfABIPtrTy, nullptr);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005923 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005924}
5925
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005926llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00005927 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005928
Craig Topper8a13c412014-05-21 05:09:00 +00005929 return nullptr;
Fariborz Jahanian71394042009-01-23 23:53:38 +00005930}
5931
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00005932void CGObjCNonFragileABIMac::AddModuleClassList(
5933 ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
5934 StringRef SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00005935 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005936
Daniel Dunbar19573e72009-05-15 21:48:48 +00005937 if (!NumClasses)
5938 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005939
Chris Lattner3def9ae2012-02-06 22:16:34 +00005940 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005941 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00005942 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00005943 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00005944 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005945 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00005946 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00005947 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005948
Daniel Dunbar19573e72009-05-15 21:48:48 +00005949 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005950 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00005951 llvm::GlobalValue::PrivateLinkage,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005952 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005953 SymbolName);
Micah Villmowdd31ca12012-10-08 16:25:52 +00005954 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00005955 GV->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00005956 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005957}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005958
Fariborz Jahanian71394042009-01-23 23:53:38 +00005959void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
5960 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005961
Daniel Dunbar19573e72009-05-15 21:48:48 +00005962 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005963 // L_OBJC_LABEL_CLASS_$.
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005964
5965 for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) {
5966 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5967 assert(ID);
5968 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5969 // We are implementing a weak imported interface. Give it external linkage
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00005970 if (ID->isWeakImported() && !IMP->isWeakImported()) {
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005971 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00005972 DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5973 }
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005974 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005975
5976 AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$",
Daniel Dunbar19573e72009-05-15 21:48:48 +00005977 "__DATA, __objc_classlist, regular, no_dead_strip");
Rafael Espindola554256c2014-02-26 22:25:45 +00005978
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005979 AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$",
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005980 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005981
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005982 // Build list of all implemented category addresses in array
5983 // L_OBJC_LABEL_CATEGORY_$.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005984 AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$",
Daniel Dunbar19573e72009-05-15 21:48:48 +00005985 "__DATA, __objc_catlist, regular, no_dead_strip");
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005986 AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$",
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005987 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005988
Daniel Dunbar5e639272010-04-25 20:39:01 +00005989 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005990}
5991
John McCall9e8bb002011-05-14 03:10:52 +00005992/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
5993/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005994/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005995/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00005996bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
5997 // At various points we've experimented with using vtable-based
5998 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005999 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006000 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00006001 return false;
John McCall9e8bb002011-05-14 03:10:52 +00006002 case CodeGenOptions::NonLegacy:
6003 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006004 case CodeGenOptions::Mixed:
6005 break;
6006 }
6007
6008 // If so, see whether this selector is in the white-list of things which must
6009 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00006010 if (VTableDispatchMethods.empty()) {
6011 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
6012 VTableDispatchMethods.insert(GetNullarySelector("class"));
6013 VTableDispatchMethods.insert(GetNullarySelector("self"));
6014 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
6015 VTableDispatchMethods.insert(GetNullarySelector("length"));
6016 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006017
John McCall9e8bb002011-05-14 03:10:52 +00006018 // These are vtable-based if GC is disabled.
6019 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006020 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00006021 VTableDispatchMethods.insert(GetNullarySelector("retain"));
6022 VTableDispatchMethods.insert(GetNullarySelector("release"));
6023 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
6024 }
6025
6026 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
6027 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
6028 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
6029 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
6030 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
6031 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
6032 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
6033
6034 // These are vtable-based if GC is enabled.
6035 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006036 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00006037 VTableDispatchMethods.insert(GetNullarySelector("hash"));
6038 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
6039
6040 // "countByEnumeratingWithState:objects:count"
6041 IdentifierInfo *KeyIdents[] = {
6042 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
6043 &CGM.getContext().Idents.get("objects"),
6044 &CGM.getContext().Idents.get("count")
6045 };
6046 VTableDispatchMethods.insert(
6047 CGM.getContext().Selectors.getSelector(3, KeyIdents));
6048 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006049 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006050
John McCall9e8bb002011-05-14 03:10:52 +00006051 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006052}
6053
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006054/// BuildClassRoTInitializer - generate meta-data for:
6055/// struct _class_ro_t {
6056/// uint32_t const flags;
6057/// uint32_t const instanceStart;
6058/// uint32_t const instanceSize;
6059/// uint32_t const reserved; // only when building for 64bit targets
6060/// const uint8_t * const ivarLayout;
6061/// const char *const name;
6062/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006063/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006064/// const struct _ivar_list_t *const ivars;
6065/// const uint8_t * const weakIvarLayout;
6066/// const struct _prop_list_t * const properties;
6067/// }
6068///
6069llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006070 unsigned flags,
6071 unsigned InstanceStart,
6072 unsigned InstanceSize,
6073 const ObjCImplementationDecl *ID) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006074 std::string ClassName = ID->getObjCRuntimeNameAsString();
John McCall31168b02011-06-15 23:02:42 +00006075
John McCall3fd13f062015-10-21 18:06:47 +00006076 CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
6077 CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
6078
John McCall460ce582015-10-22 18:38:17 +00006079 bool hasMRCWeak = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00006080 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCallef19dbb2012-10-17 04:53:23 +00006081 flags |= NonFragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00006082 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
6083 flags |= NonFragileABI_Class_HasMRCWeakIvars;
John McCall31168b02011-06-15 23:02:42 +00006084
John McCall176f8922016-11-30 02:39:18 +00006085 ConstantInitBuilder builder(CGM);
6086 auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
6087
6088 values.addInt(ObjCTypes.IntTy, flags);
6089 values.addInt(ObjCTypes.IntTy, InstanceStart);
6090 values.addInt(ObjCTypes.IntTy, InstanceSize);
6091 values.add((flags & NonFragileABI_Class_Meta)
6092 ? GetIvarLayoutName(nullptr, ObjCTypes)
6093 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
6094 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
6095
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006096 // const struct _method_list_t * const baseMethods;
John McCall176f8922016-11-30 02:39:18 +00006097 SmallVector<const ObjCMethodDecl*, 16> methods;
John McCallef19dbb2012-10-17 04:53:23 +00006098 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00006099 for (const auto *MD : ID->class_methods())
6100 methods.push_back(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006101 } else {
John McCall176f8922016-11-30 02:39:18 +00006102 for (const auto *MD : ID->instance_methods())
6103 methods.push_back(MD);
Aaron Ballmanf26acce2014-03-13 19:50:17 +00006104
Aaron Ballmand85eff42014-03-14 15:02:45 +00006105 for (const auto *PID : ID->property_impls()) {
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00006106 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
6107 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006108
John McCall176f8922016-11-30 02:39:18 +00006109 if (auto MD = PD->getGetterMethodDecl())
6110 if (GetMethodDefinition(MD))
6111 methods.push_back(MD);
6112 if (auto MD = PD->getSetterMethodDecl())
6113 if (GetMethodDefinition(MD))
6114 methods.push_back(MD);
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00006115 }
6116 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006117 }
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006118
John McCall176f8922016-11-30 02:39:18 +00006119 values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
6120 (flags & NonFragileABI_Class_Meta)
6121 ? MethodListType::ClassMethods
6122 : MethodListType::InstanceMethods,
6123 methods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006124
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006125 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6126 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
John McCall176f8922016-11-30 02:39:18 +00006127 values.add(EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006128 + OID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006129 OID->all_referenced_protocol_begin(),
6130 OID->all_referenced_protocol_end()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006131
John McCallef19dbb2012-10-17 04:53:23 +00006132 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00006133 values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
6134 values.add(GetIvarLayoutName(nullptr, ObjCTypes));
6135 values.add(EmitPropertyList(
Manman Renad0e7912016-01-29 19:22:54 +00006136 "\01l_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006137 ID, ID->getClassInterface(), ObjCTypes, true));
John McCallef19dbb2012-10-17 04:53:23 +00006138 } else {
John McCall176f8922016-11-30 02:39:18 +00006139 values.add(EmitIvarList(ID));
6140 values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
6141 values.add(EmitPropertyList(
Manman Renad0e7912016-01-29 19:22:54 +00006142 "\01l_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006143 ID, ID->getClassInterface(), ObjCTypes, false));
John McCallef19dbb2012-10-17 04:53:23 +00006144 }
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006145
John McCall176f8922016-11-30 02:39:18 +00006146 llvm::SmallString<64> roLabel;
6147 llvm::raw_svector_ostream(roLabel)
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006148 << ((flags & NonFragileABI_Class_Meta) ? "\01l_OBJC_METACLASS_RO_$_"
6149 : "\01l_OBJC_CLASS_RO_$_")
6150 << ClassName;
6151
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006152 llvm::GlobalVariable *CLASS_RO_GV =
John McCall176f8922016-11-30 02:39:18 +00006153 values.finishAndCreateGlobal(roLabel, CGM.getPointerAlign(),
6154 /*constant*/ false,
6155 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006156 if (CGM.getTriple().isOSBinFormatMachO())
6157 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006158 return CLASS_RO_GV;
6159}
6160
John McCalldba63a72016-11-30 23:54:50 +00006161/// Build the metaclass object for a class.
6162///
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006163/// struct _class_t {
6164/// struct _class_t *isa;
6165/// struct _class_t * const superclass;
6166/// void *cache;
6167/// IMP *vtable;
6168/// struct class_ro_t *ro;
6169/// }
6170///
John McCalldba63a72016-11-30 23:54:50 +00006171llvm::GlobalVariable *
6172CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI,
6173 bool isMetaclass,
6174 llvm::Constant *IsAGV,
6175 llvm::Constant *SuperClassGV,
6176 llvm::Constant *ClassRoGV,
6177 bool HiddenVisibility) {
John McCall176f8922016-11-30 02:39:18 +00006178 ConstantInitBuilder builder(CGM);
6179 auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
6180 values.add(IsAGV);
6181 if (SuperClassGV) {
6182 values.add(SuperClassGV);
6183 } else {
6184 values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
6185 }
6186 values.add(ObjCEmptyCacheVar);
6187 values.add(ObjCEmptyVtableVar);
6188 values.add(ClassRoGV);
6189
John McCalldba63a72016-11-30 23:54:50 +00006190 llvm::GlobalVariable *GV =
6191 cast<llvm::GlobalVariable>(GetClassGlobal(CI, isMetaclass, ForDefinition));
John McCall176f8922016-11-30 02:39:18 +00006192 values.finishAndSetAsInitializer(GV);
6193
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006194 if (CGM.getTriple().isOSBinFormatMachO())
6195 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006196 GV->setAlignment(
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006197 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006198 if (!CGM.getTriple().isOSBinFormatCOFF())
6199 if (HiddenVisibility)
6200 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006201 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006202}
6203
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006204bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00006205CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Craig Topper8a13c412014-05-21 05:09:00 +00006206 return OD->getClassMethod(GetNullarySelector("load")) != nullptr;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006207}
6208
Daniel Dunbar961202372009-05-03 12:57:56 +00006209void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00006210 uint32_t &InstanceStart,
6211 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006212 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00006213 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006214
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006215 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00006216 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006217
6218 // If there are no fields, the start is the same as the end.
6219 if (!RL.getFieldCount())
6220 InstanceStart = InstanceSize;
6221 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00006222 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00006223}
6224
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006225static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
6226 StringRef Name) {
6227 IdentifierInfo &II = CGM.getContext().Idents.get(Name);
6228 TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
6229 DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
6230
6231 const VarDecl *VD = nullptr;
6232 for (const auto &Result : DC->lookup(&II))
6233 if ((VD = dyn_cast<VarDecl>(Result)))
6234 break;
6235
6236 if (!VD)
6237 return llvm::GlobalValue::DLLImportStorageClass;
6238 if (VD->hasAttr<DLLExportAttr>())
6239 return llvm::GlobalValue::DLLExportStorageClass;
6240 if (VD->hasAttr<DLLImportAttr>())
6241 return llvm::GlobalValue::DLLImportStorageClass;
6242 return llvm::GlobalValue::DefaultStorageClass;
6243}
6244
Fariborz Jahanian71394042009-01-23 23:53:38 +00006245void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00006246 if (!ObjCEmptyCacheVar) {
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006247 ObjCEmptyCacheVar =
6248 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false,
6249 llvm::GlobalValue::ExternalLinkage, nullptr,
6250 "_objc_empty_cache");
6251 if (CGM.getTriple().isOSBinFormatCOFF())
6252 ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache"));
Craig Topper8a13c412014-05-21 05:09:00 +00006253
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006254 // Only OS X with deployment version <10.9 use the empty vtable symbol
Fariborz Jahanian42d49552013-10-24 17:40:28 +00006255 const llvm::Triple &Triple = CGM.getTarget().getTriple();
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006256 if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006257 ObjCEmptyVtableVar =
6258 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false,
6259 llvm::GlobalValue::ExternalLinkage, nullptr,
6260 "_objc_empty_vtable");
John McCall176f8922016-11-30 02:39:18 +00006261 else
6262 ObjCEmptyVtableVar =
6263 llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
Fariborz Jahanian71394042009-01-23 23:53:38 +00006264 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006265
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00006266 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006267 uint32_t InstanceStart =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006268 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006269 uint32_t InstanceSize = InstanceStart;
John McCallef19dbb2012-10-17 04:53:23 +00006270 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006271
John McCalldba63a72016-11-30 23:54:50 +00006272 llvm::Constant *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006273
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006274 const auto *CI = ID->getClassInterface();
6275 assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0");
6276
John McCall0d54a172012-10-17 04:53:31 +00006277 // Build the flags for the metaclass.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006278 bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
6279 ? !CI->hasAttr<DLLExportAttr>()
6280 : CI->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006281 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006282 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006283
6284 // FIXME: why is this flag set on the metaclass?
6285 // ObjC metaclasses have no fields and don't really get constructed.
6286 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006287 flags |= NonFragileABI_Class_HasCXXStructors;
John McCall0d54a172012-10-17 04:53:31 +00006288 if (!ID->hasNonZeroConstructors())
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006289 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
John McCall0d54a172012-10-17 04:53:31 +00006290 }
6291
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006292 if (!CI->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006293 // class is root
John McCallef19dbb2012-10-17 04:53:23 +00006294 flags |= NonFragileABI_Class_Root;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006295
John McCalldba63a72016-11-30 23:54:50 +00006296 SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
6297 IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006298 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006299 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00006300 const ObjCInterfaceDecl *Root = ID->getClassInterface();
6301 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
6302 Root = Super;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006303
6304 const auto *Super = CI->getSuperClass();
John McCalldba63a72016-11-30 23:54:50 +00006305 IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
6306 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006307 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006308
6309 llvm::GlobalVariable *CLASS_RO_GV =
6310 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6311
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006312 llvm::GlobalVariable *MetaTClass =
John McCalldba63a72016-11-30 23:54:50 +00006313 BuildClassObject(CI, /*metaclass*/ true,
6314 IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006315 if (CGM.getTriple().isOSBinFormatCOFF())
6316 if (CI->hasAttr<DLLExportAttr>())
6317 MetaTClass->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Fariborz Jahanian67260552009-11-17 21:37:35 +00006318 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00006319
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006320 // Metadata for the class
John McCallef19dbb2012-10-17 04:53:23 +00006321 flags = 0;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006322 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006323 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006324
6325 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006326 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006327
John McCall0d54a172012-10-17 04:53:31 +00006328 // Set a flag to enable a runtime optimization when a class has
6329 // fields that require destruction but which don't require
6330 // anything except zero-initialization during construction. This
6331 // is most notably true of __strong and __weak types, but you can
6332 // also imagine there being C++ types with non-trivial default
6333 // constructors that merely set all fields to null.
6334 if (!ID->hasNonZeroConstructors())
6335 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6336 }
6337
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006338 if (hasObjCExceptionAttribute(CGM.getContext(), CI))
John McCallef19dbb2012-10-17 04:53:23 +00006339 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006340
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006341 if (!CI->getSuperClass()) {
John McCallef19dbb2012-10-17 04:53:23 +00006342 flags |= NonFragileABI_Class_Root;
Craig Topper8a13c412014-05-21 05:09:00 +00006343 SuperClassGV = nullptr;
Chris Lattnerb433b272009-04-19 06:02:28 +00006344 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006345 // Has a root. Current class is not a root.
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006346 const auto *Super = CI->getSuperClass();
John McCalldba63a72016-11-30 23:54:50 +00006347 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006348 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006349
Daniel Dunbar961202372009-05-03 12:57:56 +00006350 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006351 CLASS_RO_GV =
6352 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006353
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006354 llvm::GlobalVariable *ClassMD =
John McCalldba63a72016-11-30 23:54:50 +00006355 BuildClassObject(CI, /*metaclass*/ false,
6356 MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006357 if (CGM.getTriple().isOSBinFormatCOFF())
6358 if (CI->hasAttr<DLLExportAttr>())
6359 ClassMD->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006360 DefinedClasses.push_back(ClassMD);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006361 ImplementedClasses.push_back(CI);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006362
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006363 // Determine if this class is also "non-lazy".
6364 if (ImplementationIsNonLazy(ID))
6365 DefinedNonLazyClasses.push_back(ClassMD);
6366
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006367 // Force the definition of the EHType if necessary.
John McCallef19dbb2012-10-17 04:53:23 +00006368 if (flags & NonFragileABI_Class_Exception)
John McCalldba63a72016-11-30 23:54:50 +00006369 (void) GetInterfaceEHType(CI, ForDefinition);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006370 // Make sure method definition entries are all clear for next implementation.
6371 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00006372}
6373
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006374/// GenerateProtocolRef - This routine is called to generate code for
6375/// a protocol reference expression; as in:
6376/// @code
6377/// @protocol(Proto1);
6378/// @endcode
6379/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
6380/// which will hold address of the protocol meta-data.
6381///
John McCall882987f2013-02-28 19:01:20 +00006382llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006383 const ObjCProtocolDecl *PD) {
6384
Fariborz Jahanian464423d2009-04-10 18:47:34 +00006385 // This routine is called for @protocol only. So, we must build definition
6386 // of protocol's meta-data (not a reference to it!)
6387 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006388 llvm::Constant *Init =
6389 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00006390 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006391
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006392 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006393 ProtocolName += PD->getObjCRuntimeNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006394
John McCall7f416cc2015-09-08 08:05:57 +00006395 CharUnits Align = CGF.getPointerAlign();
6396
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006397 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
6398 if (PTGV)
John McCall7f416cc2015-09-08 08:05:57 +00006399 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006400 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006401 CGM.getModule(),
6402 Init->getType(), false,
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006403 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006404 Init,
6405 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006406 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006407 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
John McCall7f416cc2015-09-08 08:05:57 +00006408 PTGV->setAlignment(Align.getQuantity());
Rafael Espindola060062a2014-03-06 22:15:10 +00006409 CGM.addCompilerUsedGlobal(PTGV);
John McCall7f416cc2015-09-08 08:05:57 +00006410 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006411}
6412
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006413/// GenerateCategory - Build metadata for a category implementation.
6414/// struct _category_t {
6415/// const char * const name;
6416/// struct _class_t *const cls;
6417/// const struct _method_list_t * const instance_methods;
6418/// const struct _method_list_t * const class_methods;
6419/// const struct _protocol_list_t * const protocols;
6420/// const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00006421/// const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00006422/// const uint32_t size;
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006423/// }
6424///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006425void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006426 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006427 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006428
6429 llvm::SmallString<64> ExtCatName(Prefix);
6430 ExtCatName += Interface->getObjCRuntimeNameAsString();
6431 ExtCatName += "_$_";
6432 ExtCatName += OCD->getNameAsString();
6433
John McCall176f8922016-11-30 02:39:18 +00006434 ConstantInitBuilder builder(CGM);
6435 auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
6436 values.add(GetClassName(OCD->getIdentifier()->getName()));
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006437 // meta-class entry symbol
John McCalldba63a72016-11-30 23:54:50 +00006438 values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
John McCall176f8922016-11-30 02:39:18 +00006439 std::string listName =
Saleem Abdulrasool209150a2016-10-24 21:25:57 +00006440 (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006441
John McCall176f8922016-11-30 02:39:18 +00006442 SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
6443 SmallVector<const ObjCMethodDecl *, 8> classMethods;
6444 for (const auto *MD : OCD->methods()) {
6445 if (MD->isInstanceMethod()) {
6446 instanceMethods.push_back(MD);
6447 } else {
6448 classMethods.push_back(MD);
6449 }
6450 }
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006451
John McCall176f8922016-11-30 02:39:18 +00006452 values.add(emitMethodList(listName, MethodListType::CategoryInstanceMethods,
6453 instanceMethods));
6454 values.add(emitMethodList(listName, MethodListType::CategoryClassMethods,
6455 classMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006456
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006457 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00006458 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006459 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006460 SmallString<256> ExtName;
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006461 llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006462 << OCD->getName();
John McCall176f8922016-11-30 02:39:18 +00006463 values.add(EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006464 + Interface->getObjCRuntimeNameAsString() + "_$_"
6465 + Category->getName(),
John McCall176f8922016-11-30 02:39:18 +00006466 Category->protocol_begin(),
6467 Category->protocol_end()));
6468 values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
6469 OCD, Category, ObjCTypes, false));
6470 values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
6471 OCD, Category, ObjCTypes, true));
Mike Stump658fe022009-07-30 22:28:39 +00006472 } else {
John McCall176f8922016-11-30 02:39:18 +00006473 values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
6474 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6475 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006476 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006477
Manman Ren42ff3902016-02-24 17:49:50 +00006478 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
John McCall176f8922016-11-30 02:39:18 +00006479 values.addInt(ObjCTypes.IntTy, Size);
Manman Ren42ff3902016-02-24 17:49:50 +00006480
John McCall176f8922016-11-30 02:39:18 +00006481 llvm::GlobalVariable *GCATV =
6482 values.finishAndCreateGlobal(ExtCatName.str(), CGM.getPointerAlign(),
6483 /*constant*/ false,
6484 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006485 if (CGM.getTriple().isOSBinFormatMachO())
6486 GCATV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006487 CGM.addCompilerUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006488 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006489
6490 // Determine if this category is also "non-lazy".
6491 if (ImplementationIsNonLazy(OCD))
6492 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006493 // method definition entries must be clear for next implementation.
6494 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006495}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006496
John McCall176f8922016-11-30 02:39:18 +00006497/// emitMethodConstant - Return a struct objc_method constant. If
6498/// forProtocol is true, the implementation will be null; otherwise,
6499/// the method must have a definition registered with the runtime.
6500///
6501/// struct _objc_method {
6502/// SEL _cmd;
6503/// char *method_type;
6504/// char *_imp;
6505/// }
6506void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
6507 const ObjCMethodDecl *MD,
6508 bool forProtocol) {
6509 auto method = builder.beginStruct(ObjCTypes.MethodTy);
6510 method.addBitCast(GetMethodVarName(MD->getSelector()),
6511 ObjCTypes.SelectorPtrTy);
6512 method.add(GetMethodVarType(MD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006513
John McCall176f8922016-11-30 02:39:18 +00006514 if (forProtocol) {
6515 // Protocol methods have no implementation. So, this entry is always NULL.
6516 method.addNullPointer(ObjCTypes.Int8PtrTy);
6517 } else {
6518 llvm::Function *fn = GetMethodDefinition(MD);
6519 assert(fn && "no definition for method?");
6520 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
6521 }
6522
6523 method.finishAndAddTo(builder);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006524}
6525
John McCall176f8922016-11-30 02:39:18 +00006526/// Build meta-data for method declarations.
6527///
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006528/// struct _method_list_t {
6529/// uint32_t entsize; // sizeof(struct _objc_method)
6530/// uint32_t method_count;
6531/// struct _objc_method method_list[method_count];
6532/// }
6533///
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00006534llvm::Constant *
John McCall176f8922016-11-30 02:39:18 +00006535CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
6536 ArrayRef<const ObjCMethodDecl *> methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006537 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006538 if (methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006539 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006540
John McCall176f8922016-11-30 02:39:18 +00006541 StringRef prefix;
6542 bool forProtocol;
6543 switch (kind) {
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006544 case MethodListType::CategoryInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006545 prefix = "\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_";
6546 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006547 break;
6548 case MethodListType::CategoryClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006549 prefix = "\01l_OBJC_$_CATEGORY_CLASS_METHODS_";
6550 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006551 break;
6552 case MethodListType::InstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006553 prefix = "\01l_OBJC_$_INSTANCE_METHODS_";
6554 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006555 break;
6556 case MethodListType::ClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006557 prefix = "\01l_OBJC_$_CLASS_METHODS_";
6558 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006559 break;
6560
6561 case MethodListType::ProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006562 prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_";
6563 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006564 break;
6565 case MethodListType::ProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006566 prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_";
6567 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006568 break;
6569 case MethodListType::OptionalProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006570 prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_";
6571 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006572 break;
6573 case MethodListType::OptionalProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006574 prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_";
6575 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006576 break;
6577 }
6578
John McCall176f8922016-11-30 02:39:18 +00006579 ConstantInitBuilder builder(CGM);
6580 auto values = builder.beginStruct();
6581
6582 // sizeof(struct _objc_method)
6583 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
6584 values.addInt(ObjCTypes.IntTy, Size);
6585 // method_count
6586 values.addInt(ObjCTypes.IntTy, methods.size());
6587 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
6588 for (auto MD : methods) {
6589 emitMethodConstant(methodArray, MD, forProtocol);
6590 }
6591 methodArray.finishAndAddTo(values);
6592
6593 auto *GV = values.finishAndCreateGlobal(prefix + name, CGM.getPointerAlign(),
6594 /*constant*/ false,
6595 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006596 if (CGM.getTriple().isOSBinFormatMachO())
6597 GV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006598 CGM.addCompilerUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006599 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006600}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006601
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006602/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6603/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006604llvm::GlobalVariable *
6605CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6606 const ObjCIvarDecl *Ivar) {
6607 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006608 llvm::SmallString<64> Name("OBJC_IVAR_$_");
6609 Name += Container->getObjCRuntimeNameAsString();
6610 Name += ".";
6611 Name += Ivar->getName();
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006612 llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
6613 if (!IvarOffsetGV) {
6614 IvarOffsetGV =
6615 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy,
6616 false, llvm::GlobalValue::ExternalLinkage,
6617 nullptr, Name.str());
6618 if (CGM.getTriple().isOSBinFormatCOFF()) {
6619 bool IsPrivateOrPackage =
6620 Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6621 Ivar->getAccessControl() == ObjCIvarDecl::Package;
6622
6623 if (ID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
6624 IvarOffsetGV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
6625 else if (ID->hasAttr<DLLImportAttr>())
6626 IvarOffsetGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
6627 }
6628 }
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006629 return IvarOffsetGV;
6630}
6631
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006632llvm::Constant *
6633CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6634 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00006635 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006636 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Tim Northover238b5082014-03-29 13:42:40 +00006637 IvarOffsetGV->setInitializer(
6638 llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006639 IvarOffsetGV->setAlignment(
Tim Northover238b5082014-03-29 13:42:40 +00006640 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006641
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006642 if (!CGM.getTriple().isOSBinFormatCOFF()) {
6643 // FIXME: This matches gcc, but shouldn't the visibility be set on the use
6644 // as well (i.e., in ObjCIvarOffsetVariable).
6645 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6646 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6647 ID->getVisibility() == HiddenVisibility)
6648 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6649 else
6650 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
6651 }
6652
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006653 if (CGM.getTriple().isOSBinFormatMachO())
6654 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006655 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006656}
6657
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006658/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006659/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006660/// IvarListnfABIPtrTy.
6661/// struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00006662/// unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006663/// char *name;
6664/// char *type;
6665/// uint32_t alignment;
6666/// uint32_t size;
6667/// }
6668/// struct _ivar_list_t {
6669/// uint32 entsize; // sizeof(struct _ivar_t)
6670/// uint32 count;
6671/// struct _iver_t list[count];
6672/// }
6673///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00006674
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006675llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006676 const ObjCImplementationDecl *ID) {
6677
John McCall176f8922016-11-30 02:39:18 +00006678 ConstantInitBuilder builder(CGM);
6679 auto ivarList = builder.beginStruct();
6680 ivarList.addInt(ObjCTypes.IntTy,
6681 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
6682 auto ivarCountSlot = ivarList.addPlaceholder();
6683 auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006684
Jordy Rosea91768e2011-07-22 02:08:32 +00006685 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006686 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006687
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006688 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006689
Jordy Rosea91768e2011-07-22 02:08:32 +00006690 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00006691 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00006692 // Ignore unnamed bit-fields.
6693 if (!IVD->getDeclName())
6694 continue;
John McCall176f8922016-11-30 02:39:18 +00006695
6696 auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
6697 ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
6698 ComputeIvarBaseOffset(CGM, ID, IVD)));
6699 ivar.add(GetMethodVarName(IVD->getIdentifier()));
6700 ivar.add(GetMethodVarType(IVD));
Chris Lattner2192fe52011-07-18 04:24:23 +00006701 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006702 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmowdd31ca12012-10-08 16:25:52 +00006703 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006704 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006705 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006706 Align = llvm::Log2_32(Align);
John McCall176f8922016-11-30 02:39:18 +00006707 ivar.addInt(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00006708 // NOTE. Size of a bitfield does not match gcc's, because of the
6709 // way bitfields are treated special in each. But I am told that
6710 // 'size' for bitfield ivars is ignored by the runtime so it does
6711 // not matter. If it matters, there is enough info to get the
6712 // bitfield right!
John McCall176f8922016-11-30 02:39:18 +00006713 ivar.addInt(ObjCTypes.IntTy, Size);
6714 ivar.finishAndAddTo(ivars);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006715 }
6716 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006717 if (ivars.empty()) {
6718 ivars.abandon();
6719 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00006720 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCall176f8922016-11-30 02:39:18 +00006721 }
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006722
John McCall176f8922016-11-30 02:39:18 +00006723 auto ivarCount = ivars.size();
6724 ivars.finishAndAddTo(ivarList);
6725 ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
6726
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006727 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
6728 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00006729 ivarList.finishAndCreateGlobal(Prefix + OID->getObjCRuntimeNameAsString(),
6730 CGM.getPointerAlign(), /*constant*/ false,
6731 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006732 if (CGM.getTriple().isOSBinFormatMachO())
6733 GV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006734 CGM.addCompilerUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00006735 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006736}
6737
6738llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006739 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006740 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006741
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006742 if (!Entry) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006743 // We use the initializer as a marker of whether this is a forward
6744 // reference or not. At module finalization we add the empty
6745 // contents for protocols which were referenced but never defined.
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006746 llvm::SmallString<64> Protocol;
6747 llvm::raw_svector_ostream(Protocol) << "\01l_OBJC_PROTOCOL_$_"
6748 << PD->getObjCRuntimeNameAsString();
6749
6750 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6751 false, llvm::GlobalValue::ExternalLinkage,
6752 nullptr, Protocol);
6753 if (!CGM.getTriple().isOSBinFormatMachO())
6754 Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
6755 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006756
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006757 return Entry;
6758}
6759
6760/// GetOrEmitProtocol - Generate the protocol meta-data:
6761/// @code
6762/// struct _protocol_t {
6763/// id isa; // NULL
6764/// const char * const protocol_name;
6765/// const struct _protocol_list_t * protocol_list; // super protocols
6766/// const struct method_list_t * const instance_methods;
6767/// const struct method_list_t * const class_methods;
6768/// const struct method_list_t *optionalInstanceMethods;
6769/// const struct method_list_t *optionalClassMethods;
6770/// const struct _prop_list_t * properties;
6771/// const uint32_t size; // sizeof(struct _protocol_t)
6772/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006773/// const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006774/// const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00006775/// const struct _prop_list_t * class_properties;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006776/// }
6777/// @endcode
6778///
6779
6780llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006781 const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00006782 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006783
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006784 // Early exit if a defining object has already been generated.
6785 if (Entry && Entry->hasInitializer())
6786 return Entry;
6787
Douglas Gregora715bff2012-01-01 19:51:50 +00006788 // Use the protocol definition, if there is one.
6789 if (const ObjCProtocolDecl *Def = PD->getDefinition())
6790 PD = Def;
6791
John McCall176f8922016-11-30 02:39:18 +00006792 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006793
John McCall176f8922016-11-30 02:39:18 +00006794 ConstantInitBuilder builder(CGM);
6795 auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
Douglas Gregora9d84932011-05-27 01:19:52 +00006796
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006797 // isa is NULL
John McCall176f8922016-11-30 02:39:18 +00006798 values.addNullPointer(ObjCTypes.ObjectPtrTy);
6799 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
6800 values.add(EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_"
6801 + PD->getObjCRuntimeNameAsString(),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006802 PD->protocol_begin(),
John McCall176f8922016-11-30 02:39:18 +00006803 PD->protocol_end()));
6804 values.add(methodLists.emitMethodList(this, PD,
6805 ProtocolMethodLists::RequiredInstanceMethods));
6806 values.add(methodLists.emitMethodList(this, PD,
6807 ProtocolMethodLists::RequiredClassMethods));
6808 values.add(methodLists.emitMethodList(this, PD,
6809 ProtocolMethodLists::OptionalInstanceMethods));
6810 values.add(methodLists.emitMethodList(this, PD,
6811 ProtocolMethodLists::OptionalClassMethods));
6812 values.add(EmitPropertyList(
6813 "\01l_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
6814 nullptr, PD, ObjCTypes, false));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006815 uint32_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006816 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
John McCall176f8922016-11-30 02:39:18 +00006817 values.addInt(ObjCTypes.IntTy, Size);
6818 values.addInt(ObjCTypes.IntTy, 0);
6819 values.add(EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006820 + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006821 methodLists.emitExtendedTypesArray(this),
6822 ObjCTypes));
6823
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006824 // const char *demangledName;
John McCall176f8922016-11-30 02:39:18 +00006825 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Rence7bff52016-01-29 23:46:55 +00006826
John McCall176f8922016-11-30 02:39:18 +00006827 values.add(EmitPropertyList(
Manman Rence7bff52016-01-29 23:46:55 +00006828 "\01l_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006829 nullptr, PD, ObjCTypes, true));
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006830
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006831 if (Entry) {
Rafael Espindola24615092014-09-12 20:14:20 +00006832 // Already created, fix the linkage and update the initializer.
6833 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
John McCall176f8922016-11-30 02:39:18 +00006834 values.finishAndSetAsInitializer(Entry);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006835 } else {
John McCall176f8922016-11-30 02:39:18 +00006836 llvm::SmallString<64> symbolName;
6837 llvm::raw_svector_ostream(symbolName)
6838 << "\01l_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006839
John McCall176f8922016-11-30 02:39:18 +00006840 Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
6841 /*constant*/ false,
6842 llvm::GlobalValue::WeakAnyLinkage);
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006843 if (!CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00006844 Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
John McCallf9582a72012-03-30 21:29:05 +00006845
6846 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006847 }
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006848 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Rafael Espindola060062a2014-03-06 22:15:10 +00006849 CGM.addCompilerUsedGlobal(Entry);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006850
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006851 // Use this protocol meta-data to build protocol list table in section
6852 // __DATA, __objc_protolist
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006853 llvm::SmallString<64> ProtocolRef;
6854 llvm::raw_svector_ostream(ProtocolRef) << "\01l_OBJC_LABEL_PROTOCOL_$_"
6855 << PD->getObjCRuntimeNameAsString();
6856
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006857 llvm::GlobalVariable *PTGV =
6858 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006859 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006860 ProtocolRef);
6861 if (!CGM.getTriple().isOSBinFormatMachO())
6862 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006863 PTGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006864 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006865 if (CGM.getTriple().isOSBinFormatMachO())
6866 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006867 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Rafael Espindola060062a2014-03-06 22:15:10 +00006868 CGM.addCompilerUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006869 return Entry;
6870}
6871
6872/// EmitProtocolList - Generate protocol list meta-data:
6873/// @code
6874/// struct _protocol_list_t {
6875/// long protocol_count; // Note, this is 32/64 bit
6876/// struct _protocol_t[protocol_count];
6877/// }
6878/// @endcode
6879///
6880llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006881CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006882 ObjCProtocolDecl::protocol_iterator begin,
6883 ObjCProtocolDecl::protocol_iterator end) {
Dmitri Gribenkof8579502013-01-12 19:30:44 +00006884 SmallVector<llvm::Constant *, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006885
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006886 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006887 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00006888 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006889
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006890 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006891 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006892 Name.toVector(TmpName);
6893 llvm::GlobalVariable *GV =
6894 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006895 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006896 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006897
John McCall176f8922016-11-30 02:39:18 +00006898 ConstantInitBuilder builder(CGM);
6899 auto values = builder.beginStruct();
6900 auto countSlot = values.addPlaceholder();
6901
6902 // A null-terminated array of protocols.
6903 auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006904 for (; begin != end; ++begin)
John McCall176f8922016-11-30 02:39:18 +00006905 array.add(GetProtocolRef(*begin)); // Implemented???
6906 auto count = array.size();
6907 array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006908
John McCall176f8922016-11-30 02:39:18 +00006909 array.finishAndAddTo(values);
6910 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006911
John McCall176f8922016-11-30 02:39:18 +00006912 GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
6913 /*constant*/ false,
6914 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006915 if (CGM.getTriple().isOSBinFormatMachO())
6916 GV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006917 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006918 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006919 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006920}
6921
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006922/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
6923/// This code gen. amounts to generating code for:
6924/// @code
6925/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
6926/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006927///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00006928LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00006929 CodeGen::CodeGenFunction &CGF,
6930 QualType ObjectTy,
6931 llvm::Value *BaseValue,
6932 const ObjCIvarDecl *Ivar,
6933 unsigned CVRQualifiers) {
6934 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006935 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00006936 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006937 Offset);
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006938}
6939
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006940llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006941 CodeGen::CodeGenFunction &CGF,
6942 const ObjCInterfaceDecl *Interface,
6943 const ObjCIvarDecl *Ivar) {
Tim Northover238b5082014-03-29 13:42:40 +00006944 llvm::Value *IvarOffsetValue = ObjCIvarOffsetVariable(Interface, Ivar);
John McCall7f416cc2015-09-08 08:05:57 +00006945 IvarOffsetValue = CGF.Builder.CreateAlignedLoad(IvarOffsetValue,
6946 CGF.getSizeAlign(), "ivar");
Tim Northover238b5082014-03-29 13:42:40 +00006947 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
6948 cast<llvm::LoadInst>(IvarOffsetValue)
6949 ->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
Craig Topper5fc8fc22014-08-27 06:28:36 +00006950 llvm::MDNode::get(VMContext, None));
Tim Northover238b5082014-03-29 13:42:40 +00006951
6952 // This could be 32bit int or 64bit integer depending on the architecture.
6953 // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
6954 // as this is what caller always expectes.
6955 if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
6956 IvarOffsetValue = CGF.Builder.CreateIntCast(
6957 IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
6958 return IvarOffsetValue;
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006959}
6960
John McCall234eac82011-05-13 23:16:18 +00006961static void appendSelectorForMessageRefTable(std::string &buffer,
6962 Selector selector) {
6963 if (selector.isUnarySelector()) {
6964 buffer += selector.getNameForSlot(0);
6965 return;
6966 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006967
John McCall234eac82011-05-13 23:16:18 +00006968 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
6969 buffer += selector.getNameForSlot(i);
6970 buffer += '_';
6971 }
6972}
6973
Eric Christopherd160c502016-01-29 01:35:53 +00006974/// Emit a "vtable" message send. We emit a weak hidden-visibility
John McCall9e8bb002011-05-14 03:10:52 +00006975/// struct, initially containing the selector pointer and a pointer to
6976/// a "fixup" variant of the appropriate objc_msgSend. To call, we
6977/// load and call the function pointer, passing the address of the
6978/// struct as the second parameter. The runtime determines whether
6979/// the selector is currently emitted using vtable dispatch; if so, it
6980/// substitutes a stub function which simply tail-calls through the
6981/// appropriate vtable slot, and if not, it substitues a stub function
6982/// which tail-calls objc_msgSend. Both stubs adjust the selector
6983/// argument to correctly point to the selector.
6984RValue
6985CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
6986 ReturnValueSlot returnSlot,
6987 QualType resultType,
6988 Selector selector,
6989 llvm::Value *arg0,
6990 QualType arg0Type,
6991 bool isSuper,
6992 const CallArgList &formalArgs,
6993 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00006994 // Compute the actual arguments.
6995 CallArgList args;
6996
John McCall9e8bb002011-05-14 03:10:52 +00006997 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00006998 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00006999 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
7000 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00007001
John McCall9e8bb002011-05-14 03:10:52 +00007002 // Second argument: a pointer to the message ref structure. Leave
7003 // the actual argument value blank for now.
Craig Topper8a13c412014-05-21 05:09:00 +00007004 args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
John McCall234eac82011-05-13 23:16:18 +00007005
7006 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
7007
John McCalla729c622012-02-17 03:33:10 +00007008 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCall234eac82011-05-13 23:16:18 +00007009
John McCall5880fb82011-05-14 21:12:11 +00007010 NullReturnState nullReturn;
7011
John McCall9e8bb002011-05-14 03:10:52 +00007012 // Find the function to call and the mangled name for the message
7013 // ref structure. Using a different mangled name wouldn't actually
7014 // be a problem; it would just be a waste.
7015 //
7016 // The runtime currently never uses vtable dispatch for anything
7017 // except normal, non-super message-sends.
7018 // FIXME: don't use this for that.
Craig Topper8a13c412014-05-21 05:09:00 +00007019 llvm::Constant *fn = nullptr;
John McCall234eac82011-05-13 23:16:18 +00007020 std::string messageRefName("\01l_");
Tim Northovere77cc392014-03-29 13:28:05 +00007021 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
John McCall234eac82011-05-13 23:16:18 +00007022 if (isSuper) {
7023 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
7024 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007025 } else {
John McCall5880fb82011-05-14 21:12:11 +00007026 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00007027 fn = ObjCTypes.getMessageSendStretFixupFn();
7028 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007029 }
John McCall234eac82011-05-13 23:16:18 +00007030 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
7031 fn = ObjCTypes.getMessageSendFpretFixupFn();
7032 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00007033 } else {
John McCall234eac82011-05-13 23:16:18 +00007034 if (isSuper) {
7035 fn = ObjCTypes.getMessageSendSuper2FixupFn();
7036 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007037 } else {
John McCall234eac82011-05-13 23:16:18 +00007038 fn = ObjCTypes.getMessageSendFixupFn();
7039 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007040 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00007041 }
John McCall234eac82011-05-13 23:16:18 +00007042 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
7043 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007044
John McCall234eac82011-05-13 23:16:18 +00007045 // Append the selector name, except use underscores anywhere we
7046 // would have used colons.
7047 appendSelectorForMessageRefTable(messageRefName, selector);
7048
7049 llvm::GlobalVariable *messageRef
7050 = CGM.getModule().getGlobalVariable(messageRefName);
7051 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00007052 // Build the message ref structure.
John McCall176f8922016-11-30 02:39:18 +00007053 ConstantInitBuilder builder(CGM);
7054 auto values = builder.beginStruct();
7055 values.add(fn);
7056 values.add(GetMethodVarName(selector));
7057 messageRef = values.finishAndCreateGlobal(messageRefName,
7058 CharUnits::fromQuantity(16),
7059 /*constant*/ false,
7060 llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007061 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
John McCall234eac82011-05-13 23:16:18 +00007062 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
7063 }
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007064
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00007065 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00007066 if (CGM.getLangOpts().ObjCAutoRefCount && method)
David Majnemer59f77922016-06-24 04:05:48 +00007067 for (const auto *ParamDecl : method->parameters()) {
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00007068 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
7069 if (!nullReturn.NullBB)
7070 nullReturn.init(CGF, arg0);
7071 requiresnullCheck = true;
7072 break;
7073 }
7074 }
7075
John McCall7f416cc2015-09-08 08:05:57 +00007076 Address mref =
7077 Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
7078 CGF.getPointerAlign());
John McCall234eac82011-05-13 23:16:18 +00007079
John McCall9e8bb002011-05-14 03:10:52 +00007080 // Update the message ref argument.
John McCall7f416cc2015-09-08 08:05:57 +00007081 args[1].RV = RValue::get(mref.getPointer());
John McCall234eac82011-05-13 23:16:18 +00007082
7083 // Load the function to call from the message ref table.
John McCall7f416cc2015-09-08 08:05:57 +00007084 Address calleeAddr =
7085 CGF.Builder.CreateStructGEP(mref, 0, CharUnits::Zero());
John McCallb92ab1a2016-10-26 23:46:34 +00007086 llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
John McCall234eac82011-05-13 23:16:18 +00007087
John McCallb92ab1a2016-10-26 23:46:34 +00007088 calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
7089 CGCallee callee(CGCalleeInfo(), calleePtr);
John McCall234eac82011-05-13 23:16:18 +00007090
John McCalla729c622012-02-17 03:33:10 +00007091 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Craig Topper8a13c412014-05-21 05:09:00 +00007092 return nullReturn.complete(CGF, result, resultType, formalArgs,
7093 requiresnullCheck ? method : nullptr);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007094}
7095
7096/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007097CodeGen::RValue
7098CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007099 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007100 QualType ResultType,
7101 Selector Sel,
7102 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007103 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00007104 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007105 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00007106 return isVTableDispatchedSelector(Sel)
7107 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007108 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00007109 false, CallArgs, Method)
7110 : EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00007111 EmitSelector(CGF, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007112 Receiver, CGF.getContext().getObjCIdType(),
John McCall1e3157b2015-09-10 22:27:50 +00007113 false, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007114}
7115
John McCalldba63a72016-11-30 23:54:50 +00007116llvm::Constant *
7117CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
7118 bool metaclass,
7119 ForDefinition_t isForDefinition) {
7120 auto prefix =
7121 (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
7122 return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
7123 isForDefinition,
7124 ID->isWeakImported(),
7125 !isForDefinition
7126 && CGM.getTriple().isOSBinFormatCOFF()
7127 && ID->hasAttr<DLLImportAttr>());
7128}
7129
7130llvm::Constant *
7131CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
7132 ForDefinition_t IsForDefinition,
7133 bool Weak, bool DLLImport) {
Rafael Espindola554256c2014-02-26 22:25:45 +00007134 llvm::GlobalValue::LinkageTypes L =
7135 Weak ? llvm::GlobalValue::ExternalWeakLinkage
7136 : llvm::GlobalValue::ExternalLinkage;
7137
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007138
John McCalldba63a72016-11-30 23:54:50 +00007139
7140 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
7141 if (!GV) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007142 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Craig Topper8a13c412014-05-21 05:09:00 +00007143 false, L, nullptr, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007144
John McCalldba63a72016-11-30 23:54:50 +00007145 if (DLLImport)
7146 GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
7147 }
7148
Rafael Espindola554256c2014-02-26 22:25:45 +00007149 assert(GV->getLinkage() == L);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007150 return GV;
7151}
7152
John McCalldba63a72016-11-30 23:54:50 +00007153llvm::Value *
7154CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
7155 IdentifierInfo *II,
7156 const ObjCInterfaceDecl *ID) {
John McCall7f416cc2015-09-08 08:05:57 +00007157 CharUnits Align = CGF.getPointerAlign();
John McCall31168b02011-06-15 23:02:42 +00007158 llvm::GlobalVariable *&Entry = ClassReferences[II];
7159
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007160 if (!Entry) {
John McCalldba63a72016-11-30 23:54:50 +00007161 llvm::Constant *ClassGV;
7162 if (ID) {
7163 ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
7164 } else {
7165 ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
7166 NotForDefinition);
7167 }
7168
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007169 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
7170 false, llvm::GlobalValue::PrivateLinkage,
7171 ClassGV, "OBJC_CLASSLIST_REFERENCES_$_");
John McCall7f416cc2015-09-08 08:05:57 +00007172 Entry->setAlignment(Align.getQuantity());
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007173 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00007174 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007175 }
John McCall7f416cc2015-09-08 08:05:57 +00007176 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007177}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007178
John McCall882987f2013-02-28 19:01:20 +00007179llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00007180 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00007181 // If the class has the objc_runtime_visible attribute, we need to
7182 // use the Objective-C runtime to get the class.
7183 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
7184 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
7185
John McCalldba63a72016-11-30 23:54:50 +00007186 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
John McCall31168b02011-06-15 23:02:42 +00007187}
7188
7189llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
John McCall882987f2013-02-28 19:01:20 +00007190 CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00007191 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
John McCalldba63a72016-11-30 23:54:50 +00007192 return EmitClassRefFromId(CGF, II, nullptr);
John McCall31168b02011-06-15 23:02:42 +00007193}
7194
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007195llvm::Value *
John McCall882987f2013-02-28 19:01:20 +00007196CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007197 const ObjCInterfaceDecl *ID) {
John McCall7f416cc2015-09-08 08:05:57 +00007198 CharUnits Align = CGF.getPointerAlign();
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007199 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007200
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007201 if (!Entry) {
John McCalldba63a72016-11-30 23:54:50 +00007202 auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007203 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
7204 false, llvm::GlobalValue::PrivateLinkage,
7205 ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
John McCall7f416cc2015-09-08 08:05:57 +00007206 Entry->setAlignment(Align.getQuantity());
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007207 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00007208 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007209 }
John McCall7f416cc2015-09-08 08:05:57 +00007210 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007211}
7212
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007213/// EmitMetaClassRef - Return a Value * of the address of _class_t
7214/// meta-data
7215///
John McCall882987f2013-02-28 19:01:20 +00007216llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00007217 const ObjCInterfaceDecl *ID,
7218 bool Weak) {
John McCall7f416cc2015-09-08 08:05:57 +00007219 CharUnits Align = CGF.getPointerAlign();
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007220 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
Rafael Espindola21039aa2014-02-27 16:26:32 +00007221 if (!Entry) {
John McCalldba63a72016-11-30 23:54:50 +00007222 auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007223
Rafael Espindola21039aa2014-02-27 16:26:32 +00007224 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00007225 false, llvm::GlobalValue::PrivateLinkage,
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007226 MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
John McCall7f416cc2015-09-08 08:05:57 +00007227 Entry->setAlignment(Align.getQuantity());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007228
Rafael Espindola21039aa2014-02-27 16:26:32 +00007229 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00007230 CGM.addCompilerUsedGlobal(Entry);
Rafael Espindola21039aa2014-02-27 16:26:32 +00007231 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007232
John McCall7f416cc2015-09-08 08:05:57 +00007233 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007234}
7235
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007236/// GetClass - Return a reference to the class for the given interface
7237/// decl.
John McCall882987f2013-02-28 19:01:20 +00007238llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007239 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00007240 if (ID->isWeakImported()) {
John McCalldba63a72016-11-30 23:54:50 +00007241 auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
Nick Lewycky9a441642014-02-27 00:36:00 +00007242 (void)ClassGV;
John McCalldba63a72016-11-30 23:54:50 +00007243 assert(!isa<llvm::GlobalVariable>(ClassGV) ||
7244 cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
Fariborz Jahanian95ace552009-11-17 22:42:00 +00007245 }
7246
John McCall882987f2013-02-28 19:01:20 +00007247 return EmitClassRef(CGF, ID);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007248}
7249
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007250/// Generates a message send where the super is the receiver. This is
7251/// a message send to self with special delivery semantics indicating
7252/// which class's method should be called.
7253CodeGen::RValue
7254CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007255 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007256 QualType ResultType,
7257 Selector Sel,
7258 const ObjCInterfaceDecl *Class,
7259 bool isCategoryImpl,
7260 llvm::Value *Receiver,
7261 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007262 const CodeGen::CallArgList &CallArgs,
7263 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007264 // ...
7265 // Create and init a super structure; this is a (receiver, class)
7266 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00007267 Address ObjCSuper =
7268 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
7269 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007270
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007271 llvm::Value *ReceiverAsObject =
7272 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
David Blaikie1ed728c2015-04-05 22:45:47 +00007273 CGF.Builder.CreateStore(
7274 ReceiverAsObject,
John McCall7f416cc2015-09-08 08:05:57 +00007275 CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007276
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007277 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00007278 llvm::Value *Target;
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007279 if (IsClassMessage)
Fariborz Jahanian85b99da2014-08-28 17:05:17 +00007280 Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007281 else
John McCall882987f2013-02-28 19:01:20 +00007282 Target = EmitSuperClassRef(CGF, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007283
Mike Stump18bb9282009-05-16 07:57:57 +00007284 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
7285 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00007286 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007287 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
7288 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
David Blaikie1ed728c2015-04-05 22:45:47 +00007289 CGF.Builder.CreateStore(
John McCall7f416cc2015-09-08 08:05:57 +00007290 Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007291
John McCall9e8bb002011-05-14 03:10:52 +00007292 return (isVTableDispatchedSelector(Sel))
7293 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
John McCall7f416cc2015-09-08 08:05:57 +00007294 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00007295 true, CallArgs, Method)
7296 : EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00007297 EmitSelector(CGF, Sel),
John McCall7f416cc2015-09-08 08:05:57 +00007298 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall1e3157b2015-09-10 22:27:50 +00007299 true, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007300}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007301
John McCall882987f2013-02-28 19:01:20 +00007302llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007303 Selector Sel) {
7304 Address Addr = EmitSelectorAddr(CGF, Sel);
7305
7306 llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
7307 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
7308 llvm::MDNode::get(VMContext, None));
7309 return LI;
7310}
7311
7312Address CGObjCNonFragileABIMac::EmitSelectorAddr(CodeGenFunction &CGF,
7313 Selector Sel) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007314 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007315
John McCall7f416cc2015-09-08 08:05:57 +00007316 CharUnits Align = CGF.getPointerAlign();
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007317 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007318 llvm::Constant *Casted =
7319 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
7320 ObjCTypes.SelectorPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007321 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy,
7322 false, llvm::GlobalValue::PrivateLinkage,
7323 Casted, "OBJC_SELECTOR_REFERENCES_");
Michael Gottesman5c205962013-02-05 23:08:45 +00007324 Entry->setExternallyInitialized(true);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00007325 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
John McCall7f416cc2015-09-08 08:05:57 +00007326 Entry->setAlignment(Align.getQuantity());
Rafael Espindola060062a2014-03-06 22:15:10 +00007327 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007328 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007329
John McCall7f416cc2015-09-08 08:05:57 +00007330 return Address(Entry, Align);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007331}
John McCall7f416cc2015-09-08 08:05:57 +00007332
Fariborz Jahanian06292952009-02-16 22:52:32 +00007333/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007334/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00007335///
7336void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00007337 llvm::Value *src,
John McCall7f416cc2015-09-08 08:05:57 +00007338 Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007339 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007340 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007341 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007342 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007343 assert(Size <= 8 && "does not support size > 8");
7344 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7345 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007346 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7347 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007348 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7349 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007350 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00007351 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007352}
7353
7354/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
7355/// objc_assign_strongCast (id src, id *dst)
7356///
7357void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007358 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007359 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007360 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007361 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007362 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007363 assert(Size <= 8 && "does not support size > 8");
7364 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007365 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007366 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7367 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007368 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7369 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007370 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007371 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
7372 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007373}
7374
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007375void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007376 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007377 Address DestPtr,
7378 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00007379 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007380 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
7381 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007382 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size };
John McCall882987f2013-02-28 19:01:20 +00007383 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007384}
7385
Fariborz Jahanian06292952009-02-16 22:52:32 +00007386/// EmitObjCWeakRead - Code gen for loading value of a __weak
7387/// object: objc_read_weak (id *src)
7388///
7389llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007390 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007391 Address AddrWeakObj) {
7392 llvm::Type *DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007393 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00007394 llvm::Value *read_weak =
7395 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00007396 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00007397 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007398 return read_weak;
7399}
7400
7401/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
7402/// objc_assign_weak (id src, id *dst)
7403///
7404void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007405 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007406 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007407 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007408 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007409 assert(Size <= 8 && "does not support size > 8");
7410 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7411 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007412 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7413 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007414 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7415 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007416 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007417 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
7418 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007419}
7420
7421/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
7422/// objc_assign_global (id src, id *dst)
7423///
7424void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007425 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00007426 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007427 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007428 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007429 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007430 assert(Size <= 8 && "does not support size > 8");
7431 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7432 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007433 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7434 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007435 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7436 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007437 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00007438 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00007439 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
7440 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00007441 else
John McCall882987f2013-02-28 19:01:20 +00007442 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
7443 args, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007444}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007445
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007446void
John McCallbd309292010-07-06 01:34:17 +00007447CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
7448 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00007449 EmitAtSynchronizedStmt(CGF, S,
7450 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
7451 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00007452}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007453
John McCall2ca705e2010-07-24 00:37:23 +00007454llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00007455CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00007456 // There's a particular fixed type info for 'id'.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007457 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
7458 auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007459 if (!IDEHType) {
John McCall2ca705e2010-07-24 00:37:23 +00007460 IDEHType =
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007461 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
7462 llvm::GlobalValue::ExternalLinkage, nullptr,
7463 "OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007464 if (CGM.getTriple().isOSBinFormatCOFF())
7465 IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id"));
7466 }
John McCall2ca705e2010-07-24 00:37:23 +00007467 return IDEHType;
7468 }
7469
7470 // All other types should be Objective-C interface pointer types.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007471 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
John McCall2ca705e2010-07-24 00:37:23 +00007472 assert(PT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007473
John McCall2ca705e2010-07-24 00:37:23 +00007474 const ObjCInterfaceType *IT = PT->getInterfaceType();
7475 assert(IT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007476
John McCalldba63a72016-11-30 23:54:50 +00007477 return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007478}
John McCall2ca705e2010-07-24 00:37:23 +00007479
John McCallbd309292010-07-06 01:34:17 +00007480void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
7481 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00007482 EmitTryCatchStmt(CGF, S,
7483 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
7484 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
7485 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00007486}
7487
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007488/// EmitThrowStmt - Generate code for a throw statement.
7489void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007490 const ObjCAtThrowStmt &S,
7491 bool ClearInsertionPoint) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007492 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00007493 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00007494 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00007495 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall17afe452010-10-16 08:21:07 +00007496 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007497 } else {
John McCall882987f2013-02-28 19:01:20 +00007498 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall17afe452010-10-16 08:21:07 +00007499 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007500 }
7501
John McCall17afe452010-10-16 08:21:07 +00007502 CGF.Builder.CreateUnreachable();
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007503 if (ClearInsertionPoint)
7504 CGF.Builder.ClearInsertionPoint();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007505}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007506
John McCall2ca705e2010-07-24 00:37:23 +00007507llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007508CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
John McCalldba63a72016-11-30 23:54:50 +00007509 ForDefinition_t IsForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007510 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007511 StringRef ClassName = ID->getObjCRuntimeNameAsString();
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007512
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007513 // If we don't need a definition, return the entry if found or check
7514 // if we use an external reference.
John McCalldba63a72016-11-30 23:54:50 +00007515 if (!IsForDefinition) {
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007516 if (Entry)
7517 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00007518
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007519 // If this type (or a super class) has the __objc_exception__
7520 // attribute, emit an external reference.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007521 if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
7522 std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str();
7523 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
7524 false, llvm::GlobalValue::ExternalLinkage,
7525 nullptr, EHTypeName);
7526 if (CGM.getTriple().isOSBinFormatCOFF()) {
7527 if (ID->hasAttr<DLLExportAttr>())
7528 Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
7529 else if (ID->hasAttr<DLLImportAttr>())
7530 Entry->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
7531 }
7532 return Entry;
7533 }
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007534 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007535
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007536 // Otherwise we need to either make a new entry or fill in the initializer.
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007537 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007538
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007539 std::string VTableName = "objc_ehtype_vtable";
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007540 auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007541 if (!VTableGV) {
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007542 VTableGV =
7543 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false,
7544 llvm::GlobalValue::ExternalLinkage, nullptr,
7545 VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007546 if (CGM.getTriple().isOSBinFormatCOFF())
7547 VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
7548 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007549
Chris Lattnerece04092012-02-07 00:39:47 +00007550 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
John McCall176f8922016-11-30 02:39:18 +00007551 ConstantInitBuilder builder(CGM);
7552 auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
7553 values.add(llvm::ConstantExpr::getGetElementPtr(VTableGV->getValueType(),
7554 VTableGV, VTableIdx));
John McCalldba63a72016-11-30 23:54:50 +00007555 values.add(GetClassName(ClassName));
7556 values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007557
John McCalldba63a72016-11-30 23:54:50 +00007558 llvm::GlobalValue::LinkageTypes L = IsForDefinition
Rafael Espindola554256c2014-02-26 22:25:45 +00007559 ? llvm::GlobalValue::ExternalLinkage
7560 : llvm::GlobalValue::WeakAnyLinkage;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007561 if (Entry) {
John McCall176f8922016-11-30 02:39:18 +00007562 values.finishAndSetAsInitializer(Entry);
7563 Entry->setAlignment(CGM.getPointerAlign().getQuantity());
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007564 } else {
John McCall176f8922016-11-30 02:39:18 +00007565 Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName,
7566 CGM.getPointerAlign(),
7567 /*constant*/ false,
7568 L);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007569 if (CGM.getTriple().isOSBinFormatCOFF())
7570 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
7571 if (ID->hasAttr<DLLExportAttr>())
7572 Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007573 }
Rafael Espindola554256c2014-02-26 22:25:45 +00007574 assert(Entry->getLinkage() == L);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007575
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007576 if (!CGM.getTriple().isOSBinFormatCOFF())
7577 if (ID->getVisibility() == HiddenVisibility)
7578 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007579
John McCalldba63a72016-11-30 23:54:50 +00007580 if (IsForDefinition)
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00007581 if (CGM.getTriple().isOSBinFormatMachO())
7582 Entry->setSection("__DATA,__objc_const");
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007583
7584 return Entry;
7585}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007586
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00007587/* *** */
7588
Daniel Dunbarb036db82008-08-13 03:21:16 +00007589CodeGen::CGObjCRuntime *
7590CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall5fb5df92012-06-20 06:18:46 +00007591 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7592 case ObjCRuntime::FragileMacOSX:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007593 return new CGObjCMac(CGM);
John McCall5fb5df92012-06-20 06:18:46 +00007594
7595 case ObjCRuntime::MacOSX:
7596 case ObjCRuntime::iOS:
Tim Northover756447a2015-10-30 16:30:36 +00007597 case ObjCRuntime::WatchOS:
John McCall5fb5df92012-06-20 06:18:46 +00007598 return new CGObjCNonFragileABIMac(CGM);
7599
David Chisnallb601c962012-07-03 20:49:52 +00007600 case ObjCRuntime::GNUstep:
7601 case ObjCRuntime::GCC:
John McCall775086e2012-07-12 02:07:58 +00007602 case ObjCRuntime::ObjFW:
John McCall5fb5df92012-06-20 06:18:46 +00007603 llvm_unreachable("these runtimes are not Mac runtimes");
7604 }
7605 llvm_unreachable("bad runtime");
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007606}