blob: 338fdee3e348fe4931fffa2625962c709dcb3cda [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
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000891 /// GetNameForMethod - Return a name for the given method.
892 /// \param[out] NameOut - The return value.
893 void GetNameForMethod(const ObjCMethodDecl *OMD,
894 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000895 SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000896
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000897 /// GetMethodVarName - Return a unique constant for the given
898 /// selector's name. The return value has type char *.
899 llvm::Constant *GetMethodVarName(Selector Sel);
900 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000901
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000902 /// GetMethodVarType - Return a unique constant for the given
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000903 /// method's type encoding string. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000904
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000905 // FIXME: This is a horrible name.
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000906 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
907 bool Extended = false);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000908 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000909
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000910 /// GetPropertyName - Return a unique constant for the given
911 /// name. The return value has type char *.
912 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000913
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000914 // FIXME: This can be dropped once string functions are unified.
915 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
916 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000917
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000918 /// GetClassName - Return a unique constant for the given selector's
Fariborz Jahanian451b92a2014-07-16 16:16:04 +0000919 /// runtime name (which may change via use of objc_runtime_name attribute on
920 /// class or protocol definition. The return value has type char *.
921 llvm::Constant *GetClassName(StringRef RuntimeName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000922
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000923 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
924
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000925 /// BuildIvarLayout - Builds ivar layout bitmap for the class
926 /// implementation for the __strong or __weak case.
927 ///
John McCall460ce582015-10-22 18:38:17 +0000928 /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there
929 /// are any weak ivars defined directly in the class. Meaningless unless
930 /// building a weak layout. Does not guarantee that the layout will
931 /// actually have any entries, because the ivar might be under-aligned.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000932 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
John McCall3fd13f062015-10-21 18:06:47 +0000933 CharUnits beginOffset,
934 CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +0000935 bool forStrongLayout,
936 bool hasMRCWeakIvars);
937
938 llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI,
939 CharUnits beginOffset,
940 CharUnits endOffset) {
941 return BuildIvarLayout(OI, beginOffset, endOffset, true, false);
942 }
943
944 llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI,
945 CharUnits beginOffset,
946 CharUnits endOffset,
947 bool hasMRCWeakIvars) {
948 return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
949 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +0000950
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000951 Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
Fariborz Jahanian2dd78192012-11-02 22:51:18 +0000952
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000953 void UpdateRunSkipBlockVars(bool IsByref,
954 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000955 CharUnits FieldOffset,
956 CharUnits FieldSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000957
958 void BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000959 CharUnits BytePos, bool &HasUnion,
960 bool ByrefLayout=false);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000961
962 void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
963 const RecordDecl *RD,
964 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000965 CharUnits BytePos, bool &HasUnion,
966 bool ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000967
Fariborz Jahanian23290b02012-11-01 18:32:55 +0000968 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
969
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000970 llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
971
Fariborz Jahanian01dff422009-03-05 19:17:31 +0000972 /// GetIvarLayoutName - Returns a unique constant for the given
973 /// ivar layout bitmap.
974 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
975 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000976
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000977 /// EmitPropertyList - Emit the given property list. The return
978 /// value has type PropertyListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000979 llvm::Constant *EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000980 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000981 const ObjCContainerDecl *OCD,
Manman Renad0e7912016-01-29 19:22:54 +0000982 const ObjCCommonTypesHelper &ObjCTypes,
983 bool IsClassProperty);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000984
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000985 /// EmitProtocolMethodTypes - Generate the array of extended method type
986 /// strings. The return value has type Int8PtrPtrTy.
987 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +0000988 ArrayRef<llvm::Constant*> MethodTypes,
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000989 const ObjCCommonTypesHelper &ObjCTypes);
990
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000991 /// GetProtocolRef - Return a reference to the internal protocol
992 /// description, creating an empty one if it has not been
993 /// defined. The return value has type ProtocolPtrTy.
994 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +0000995
Douglas Gregor24ae22c2016-04-01 23:23:52 +0000996 /// Return a reference to the given Class using runtime calls rather than
997 /// by a symbol reference.
998 llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
999 const ObjCInterfaceDecl *ID,
1000 ObjCCommonTypesHelper &ObjCTypes);
1001
John McCall3fd13f062015-10-21 18:06:47 +00001002public:
Daniel Dunbar30c65362009-03-09 20:09:19 +00001003 /// CreateMetadataVar - Create a global variable with internal
1004 /// linkage for use by the Objective-C runtime.
1005 ///
1006 /// This is a convenience wrapper which not only creates the
1007 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +00001008 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001009 ///
1010 /// \param Name - The variable name.
1011 /// \param Init - The variable initializer; this is also used to
John McCall176f8922016-11-30 02:39:18 +00001012 /// define the type of the variable.
Alp Toker541d5072014-06-07 23:30:53 +00001013 /// \param Section - The section the variable should go into, or empty.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001014 /// \param Align - The alignment for the variable, or 0.
1015 /// \param AddToUsed - Whether the variable should be added to
John McCall176f8922016-11-30 02:39:18 +00001016 /// "llvm.used".
1017 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1018 ConstantStructBuilder &Init,
1019 StringRef Section, CharUnits Align,
1020 bool AddToUsed);
1021 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1022 llvm::Constant *Init,
John McCall7f416cc2015-09-08 08:05:57 +00001023 StringRef Section, CharUnits Align,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001024 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +00001025
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001026 llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00001027 ObjCLabelType LabelType,
1028 bool ForceNonFragileABI = false,
1029 bool NullTerminate = true);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001030
John McCall3fd13f062015-10-21 18:06:47 +00001031protected:
John McCall9e8bb002011-05-14 03:10:52 +00001032 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1033 ReturnValueSlot Return,
1034 QualType ResultType,
1035 llvm::Value *Sel,
1036 llvm::Value *Arg0,
1037 QualType Arg0Ty,
1038 bool IsSuper,
1039 const CallArgList &CallArgs,
1040 const ObjCMethodDecl *OMD,
John McCall1e3157b2015-09-10 22:27:50 +00001041 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00001042 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +00001043
Daniel Dunbar5e639272010-04-25 20:39:01 +00001044 /// EmitImageInfo - Emit the image info marker used to encode some module
1045 /// level information.
1046 void EmitImageInfo();
1047
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001048public:
Owen Andersonae86c192009-07-13 04:10:07 +00001049 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
John McCalla729c622012-02-17 03:33:10 +00001050 CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001051
John McCall3fd13f062015-10-21 18:06:47 +00001052 bool isNonFragileABI() const {
1053 return ObjCABI == 2;
1054 }
1055
John McCall7f416cc2015-09-08 08:05:57 +00001056 ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001057
Craig Topper4f12f102014-03-12 06:41:41 +00001058 llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
Craig Topper8a13c412014-05-21 05:09:00 +00001059 const ObjCContainerDecl *CD=nullptr) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001060
1061 void GenerateProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001062
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001063 /// GetOrEmitProtocol - Get the protocol object for the given
1064 /// declaration, emitting it if necessary. The return value has type
1065 /// ProtocolPtrTy.
1066 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001067
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001068 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1069 /// object for the given declaration, emitting it if needed. These
1070 /// forward references will be filled in with empty bodies if no
1071 /// definition is seen. The return value has type ProtocolPtrTy.
1072 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
Craig Topper4f12f102014-03-12 06:41:41 +00001073 llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1074 const CGBlockInfo &blockInfo) override;
1075 llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1076 const CGBlockInfo &blockInfo) override;
1077
1078 llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1079 QualType T) override;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001080};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001081
John McCall176f8922016-11-30 02:39:18 +00001082namespace {
1083
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001084enum class MethodListType {
1085 CategoryInstanceMethods,
1086 CategoryClassMethods,
1087 InstanceMethods,
1088 ClassMethods,
1089 ProtocolInstanceMethods,
1090 ProtocolClassMethods,
1091 OptionalProtocolInstanceMethods,
1092 OptionalProtocolClassMethods,
1093};
1094
John McCall176f8922016-11-30 02:39:18 +00001095/// A convenience class for splitting the methods of a protocol into
1096/// the four interesting groups.
1097class ProtocolMethodLists {
1098public:
1099 enum Kind {
1100 RequiredInstanceMethods,
1101 RequiredClassMethods,
1102 OptionalInstanceMethods,
1103 OptionalClassMethods
1104 };
1105 enum {
1106 NumProtocolMethodLists = 4
1107 };
1108
1109 static MethodListType getMethodListKind(Kind kind) {
1110 switch (kind) {
1111 case RequiredInstanceMethods:
1112 return MethodListType::ProtocolInstanceMethods;
1113 case RequiredClassMethods:
1114 return MethodListType::ProtocolClassMethods;
1115 case OptionalInstanceMethods:
1116 return MethodListType::OptionalProtocolInstanceMethods;
1117 case OptionalClassMethods:
1118 return MethodListType::OptionalProtocolClassMethods;
1119 }
1120 llvm_unreachable("bad kind");
1121 }
1122
1123 SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];
1124
1125 static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
1126 ProtocolMethodLists result;
1127
1128 for (auto MD : PD->methods()) {
1129 size_t index = (2 * size_t(MD->isOptional()))
1130 + (size_t(MD->isClassMethod()));
1131 result.Methods[index].push_back(MD);
1132 }
1133
1134 return result;
1135 }
1136
1137 template <class Self>
1138 SmallVector<llvm::Constant*, 8> emitExtendedTypesArray(Self *self) const {
1139 // In both ABIs, the method types list is parallel with the
1140 // concatenation of the methods arrays in the following order:
1141 // instance methods
1142 // class methods
1143 // optional instance methods
1144 // optional class methods
1145 SmallVector<llvm::Constant*, 8> result;
1146
1147 // Methods is already in the correct order for both ABIs.
1148 for (auto &list : Methods) {
1149 for (auto MD : list) {
1150 result.push_back(self->GetMethodVarType(MD, true));
1151 }
1152 }
1153
1154 return result;
1155 }
1156
1157 template <class Self>
1158 llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD,
1159 Kind kind) const {
1160 return self->emitMethodList(PD->getObjCRuntimeNameAsString(),
1161 getMethodListKind(kind), Methods[kind]);
1162 }
1163};
1164
1165} // end anonymous namespace
1166
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001167class CGObjCMac : public CGObjCCommonMac {
1168private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001169 friend ProtocolMethodLists;
John McCall176f8922016-11-30 02:39:18 +00001170
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001171 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001172
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001173 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001174 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001175 void EmitModuleInfo();
1176
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001177 /// EmitModuleSymols - Emit module symbols, the list of defined
1178 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001179 llvm::Constant *EmitModuleSymbols();
1180
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001181 /// FinishModule - Write out global data structures at the end of
1182 /// processing a translation unit.
1183 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +00001184
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001185 /// EmitClassExtension - Generate the class extension structure used
1186 /// to store the weak ivar layout and properties. The return value
1187 /// has type ClassExtensionPtrTy.
John McCall3fd13f062015-10-21 18:06:47 +00001188 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
John McCall460ce582015-10-22 18:38:17 +00001189 CharUnits instanceSize,
Manman Renad0e7912016-01-29 19:22:54 +00001190 bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00001191 bool isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001192
1193 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1194 /// for the given class.
John McCall882987f2013-02-28 19:01:20 +00001195 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001196 const ObjCInterfaceDecl *ID);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001197
John McCall882987f2013-02-28 19:01:20 +00001198 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00001199 IdentifierInfo *II);
Craig Topper4f12f102014-03-12 06:41:41 +00001200
1201 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
1202
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001203 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1204 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001205
1206 /// EmitIvarList - Emit the ivar list for the given
1207 /// implementation. If ForClass is true the list of class ivars
1208 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1209 /// interface ivars will be emitted. The return value has type
1210 /// IvarListPtrTy.
1211 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00001212 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001213
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001214 /// EmitMetaClass - Emit a forward reference to the class structure
1215 /// for the metaclass of the given interface. The return value has
1216 /// type ClassPtrTy.
1217 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1218
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001219 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001220 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001221 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1222 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00001223 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001224
John McCall176f8922016-11-30 02:39:18 +00001225 void emitMethodConstant(ConstantArrayBuilder &builder,
1226 const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001227
John McCall176f8922016-11-30 02:39:18 +00001228 void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
1229 const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001230
1231 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +00001232 /// implementation. The return value has type MethodListPtrTy.
John McCall176f8922016-11-30 02:39:18 +00001233 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1234 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001235
Daniel Dunbarc475d422008-10-29 22:36:39 +00001236 /// GetOrEmitProtocol - Get the protocol object for the given
1237 /// declaration, emitting it if necessary. The return value has type
1238 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001239 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001240
1241 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1242 /// object for the given declaration, emitting it if needed. These
1243 /// forward references will be filled in with empty bodies if no
1244 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001245 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001246
Daniel Dunbarb036db82008-08-13 03:21:16 +00001247 /// EmitProtocolExtension - Generate the protocol extension
1248 /// structure used to store optional instance and class methods, and
1249 /// protocol properties. The return value has type
1250 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001251 llvm::Constant *
1252 EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00001253 const ProtocolMethodLists &methodLists);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001254
1255 /// EmitProtocolList - Generate the list of referenced
1256 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001257 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001258 ObjCProtocolDecl::protocol_iterator begin,
1259 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001260
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001261 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1262 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001263 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1264 Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001265
1266public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001267 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001268
Craig Topper4f12f102014-03-12 06:41:41 +00001269 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001270
Craig Topper4f12f102014-03-12 06:41:41 +00001271 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1272 ReturnValueSlot Return,
1273 QualType ResultType,
1274 Selector Sel, llvm::Value *Receiver,
1275 const CallArgList &CallArgs,
1276 const ObjCInterfaceDecl *Class,
1277 const ObjCMethodDecl *Method) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001278
Craig Topper4f12f102014-03-12 06:41:41 +00001279 CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001280 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001281 ReturnValueSlot Return, QualType ResultType,
1282 Selector Sel, const ObjCInterfaceDecl *Class,
1283 bool isCategoryImpl, llvm::Value *Receiver,
1284 bool IsClassMessage, const CallArgList &CallArgs,
1285 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001286
Craig Topper4f12f102014-03-12 06:41:41 +00001287 llvm::Value *GetClass(CodeGenFunction &CGF,
1288 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001289
John McCall7f416cc2015-09-08 08:05:57 +00001290 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
1291 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001292
1293 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1294 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001295 llvm::Value *GetSelector(CodeGenFunction &CGF,
1296 const ObjCMethodDecl *Method) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001297
Craig Topper4f12f102014-03-12 06:41:41 +00001298 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001299
Craig Topper4f12f102014-03-12 06:41:41 +00001300 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001301
Craig Topper4f12f102014-03-12 06:41:41 +00001302 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001303
Craig Topper4f12f102014-03-12 06:41:41 +00001304 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001305
Craig Topper4f12f102014-03-12 06:41:41 +00001306 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1307 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001308
Craig Topper4f12f102014-03-12 06:41:41 +00001309 llvm::Constant *GetPropertyGetFunction() override;
1310 llvm::Constant *GetPropertySetFunction() override;
1311 llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1312 bool copy) override;
1313 llvm::Constant *GetGetStructFunction() override;
1314 llvm::Constant *GetSetStructFunction() override;
1315 llvm::Constant *GetCppAtomicObjectGetFunction() override;
1316 llvm::Constant *GetCppAtomicObjectSetFunction() override;
1317 llvm::Constant *EnumerationMutationFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001318
Craig Topper4f12f102014-03-12 06:41:41 +00001319 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1320 const ObjCAtTryStmt &S) override;
1321 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1322 const ObjCAtSynchronizedStmt &S) override;
John McCallbd309292010-07-06 01:34:17 +00001323 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Craig Topper4f12f102014-03-12 06:41:41 +00001324 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1325 bool ClearInsertionPoint=true) override;
1326 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001327 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001328 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001329 llvm::Value *src, Address dst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001330 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001331 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001332 bool threadlocal = false) override;
1333 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001334 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001335 llvm::Value *ivarOffset) override;
1336 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001337 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001338 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001339 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001340 llvm::Value *size) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001341
Craig Topper4f12f102014-03-12 06:41:41 +00001342 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1343 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1344 unsigned CVRQualifiers) override;
1345 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1346 const ObjCInterfaceDecl *Interface,
1347 const ObjCIvarDecl *Ivar) override;
1348
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001349 /// GetClassGlobal - Return the global variable for the Objective-C
1350 /// class of the given name.
Benjamin Kramer0772c422016-02-13 13:42:54 +00001351 llvm::GlobalVariable *GetClassGlobal(StringRef Name,
Craig Toppera798a9d2014-03-02 09:32:10 +00001352 bool Weak = false) override {
David Blaikie83d382b2011-09-23 05:06:16 +00001353 llvm_unreachable("CGObjCMac::GetClassGlobal");
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001354 }
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001355};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001356
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001357class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001358private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001359 friend ProtocolMethodLists;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001360 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001361 llvm::GlobalVariable* ObjCEmptyCacheVar;
John McCall176f8922016-11-30 02:39:18 +00001362 llvm::Constant* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001363
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001364 /// SuperClassReferences - uniqued super class references.
1365 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001366
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001367 /// MetaClassReferences - uniqued meta class references.
1368 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001369
1370 /// EHTypeReferences - uniqued class ehtype references.
1371 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001372
John McCall9e8bb002011-05-14 03:10:52 +00001373 /// VTableDispatchMethods - List of methods for which we generate
1374 /// vtable-based message dispatch.
1375 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001376
Fariborz Jahanian67260552009-11-17 21:37:35 +00001377 /// DefinedMetaClasses - List of defined meta-classes.
1378 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1379
John McCall9e8bb002011-05-14 03:10:52 +00001380 /// isVTableDispatchedSelector - Returns true if SEL is a
1381 /// vtable-based selector.
1382 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001383
Fariborz Jahanian71394042009-01-23 23:53:38 +00001384 /// FinishNonFragileABIModule - Write out global data structures at the end of
1385 /// processing a translation unit.
1386 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001387
Daniel Dunbar19573e72009-05-15 21:48:48 +00001388 /// AddModuleClassList - Add the given list of class pointers to the
1389 /// module with the provided symbol and section names.
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001390 void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container,
1391 StringRef SymbolName, StringRef SectionName);
Daniel Dunbar19573e72009-05-15 21:48:48 +00001392
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001393 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1394 unsigned InstanceStart,
1395 unsigned InstanceSize,
1396 const ObjCImplementationDecl *ID);
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00001397 llvm::GlobalVariable * BuildClassMetaData(const std::string &ClassName,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001398 llvm::Constant *IsAGV,
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001399 llvm::Constant *SuperClassGV,
Fariborz Jahanian82208252009-01-31 00:59:10 +00001400 llvm::Constant *ClassRoGV,
Rafael Espindola554256c2014-02-26 22:25:45 +00001401 bool HiddenVisibility,
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00001402 bool Weak);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001403
John McCall176f8922016-11-30 02:39:18 +00001404 void emitMethodConstant(ConstantArrayBuilder &builder,
1405 const ObjCMethodDecl *MD,
1406 bool forProtocol);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001407
John McCall176f8922016-11-30 02:39:18 +00001408 /// Emit the method list for the given implementation. The return value
1409 /// has type MethodListnfABITy.
1410 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1411 ArrayRef<const ObjCMethodDecl *> Methods);
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001412
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001413 /// EmitIvarList - Emit the ivar list for the given
1414 /// implementation. If ForClass is true the list of class ivars
1415 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1416 /// interface ivars will be emitted. The return value has type
1417 /// IvarListnfABIPtrTy.
1418 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001419
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001420 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001421 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00001422 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001423
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001424 /// GetOrEmitProtocol - Get the protocol object for the given
1425 /// declaration, emitting it if necessary. The return value has type
1426 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001427 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001428
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001429 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1430 /// object for the given declaration, emitting it if needed. These
1431 /// forward references will be filled in with empty bodies if no
1432 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001433 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001434
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001435 /// EmitProtocolList - Generate the list of referenced
1436 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001437 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001438 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001439 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001440
John McCall9e8bb002011-05-14 03:10:52 +00001441 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1442 ReturnValueSlot Return,
1443 QualType ResultType,
1444 Selector Sel,
1445 llvm::Value *Receiver,
1446 QualType Arg0Ty,
1447 bool IsSuper,
1448 const CallArgList &CallArgs,
1449 const ObjCMethodDecl *Method);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001450
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001451 /// GetClassGlobal - Return the global variable for the Objective-C
1452 /// class of the given name.
Benjamin Kramer0772c422016-02-13 13:42:54 +00001453 llvm::GlobalVariable *GetClassGlobal(StringRef Name,
Craig Toppera798a9d2014-03-02 09:32:10 +00001454 bool Weak = false) override;
Rafael Espindola554256c2014-02-26 22:25:45 +00001455
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001456 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001457 /// for the given class reference.
John McCall882987f2013-02-28 19:01:20 +00001458 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001459 const ObjCInterfaceDecl *ID);
John McCall31168b02011-06-15 23:02:42 +00001460
John McCall882987f2013-02-28 19:01:20 +00001461 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00001462 IdentifierInfo *II, bool Weak,
1463 const ObjCInterfaceDecl *ID);
Craig Topper4f12f102014-03-12 06:41:41 +00001464
1465 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001466
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001467 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1468 /// for the given super class reference.
John McCall882987f2013-02-28 19:01:20 +00001469 llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001470 const ObjCInterfaceDecl *ID);
1471
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001472 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1473 /// meta-data
John McCall882987f2013-02-28 19:01:20 +00001474 llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00001475 const ObjCInterfaceDecl *ID, bool Weak);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001476
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001477 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1478 /// the given ivar.
1479 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001480 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001481 const ObjCInterfaceDecl *ID,
1482 const ObjCIvarDecl *Ivar);
1483
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001484 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1485 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001486 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1487 Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001488
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001489 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001490 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001491 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001492 bool ForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001493
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001494 StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001495
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001496 StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; }
Daniel Dunbar15894b72009-04-07 05:48:37 +00001497
Daniel Dunbar961202372009-05-03 12:57:56 +00001498 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001499 uint32_t &InstanceStart,
1500 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001501
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001502 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001503 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001504 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1505 return CGM.getContext().Selectors.getSelector(0, &II);
1506 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001507
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001508 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001509 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1510 return CGM.getContext().Selectors.getSelector(1, &II);
1511 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001512
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001513 /// ImplementationIsNonLazy - Check whether the given category or
1514 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001515 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001516
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001517 bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001518 const ObjCIvarDecl *IV) {
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001519 // Annotate the load as an invariant load iff inside an instance method
1520 // and ivar belongs to instance method's class and one of its super class.
1521 // This check is needed because the ivar offset is a lazily
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001522 // initialised value that may depend on objc_msgSend to perform a fixup on
1523 // the first message dispatch.
1524 //
1525 // An additional opportunity to mark the load as invariant arises when the
1526 // base of the ivar access is a parameter to an Objective C method.
1527 // However, because the parameters are not available in the current
1528 // interface, we cannot perform this check.
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001529 if (const ObjCMethodDecl *MD =
1530 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
Fariborz Jahanian7a583022014-03-04 22:57:32 +00001531 if (MD->isInstanceMethod())
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001532 if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
1533 return IV->getContainingInterface()->isSuperClassOf(ID);
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001534 return false;
1535 }
1536
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001537public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001538 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001539 // FIXME. All stubs for now!
Craig Topper4f12f102014-03-12 06:41:41 +00001540 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001541
Craig Topper4f12f102014-03-12 06:41:41 +00001542 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1543 ReturnValueSlot Return,
1544 QualType ResultType, Selector Sel,
1545 llvm::Value *Receiver,
1546 const CallArgList &CallArgs,
1547 const ObjCInterfaceDecl *Class,
1548 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001549
Craig Topper4f12f102014-03-12 06:41:41 +00001550 CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001551 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001552 ReturnValueSlot Return, QualType ResultType,
1553 Selector Sel, const ObjCInterfaceDecl *Class,
1554 bool isCategoryImpl, llvm::Value *Receiver,
1555 bool IsClassMessage, const CallArgList &CallArgs,
1556 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001557
Craig Topper4f12f102014-03-12 06:41:41 +00001558 llvm::Value *GetClass(CodeGenFunction &CGF,
1559 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001560
John McCall7f416cc2015-09-08 08:05:57 +00001561 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override
1562 { return EmitSelector(CGF, Sel); }
1563 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override
1564 { return EmitSelectorAddr(CGF, Sel); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001565
1566 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1567 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001568 llvm::Value *GetSelector(CodeGenFunction &CGF,
1569 const ObjCMethodDecl *Method) override
John McCall882987f2013-02-28 19:01:20 +00001570 { return EmitSelector(CGF, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001571
Craig Topper4f12f102014-03-12 06:41:41 +00001572 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001573
Craig Topper4f12f102014-03-12 06:41:41 +00001574 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
David Chisnall92d436b2012-01-31 18:59:20 +00001575
Craig Topper4f12f102014-03-12 06:41:41 +00001576 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001577
Craig Topper4f12f102014-03-12 06:41:41 +00001578 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1579 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001580
Craig Topper4f12f102014-03-12 06:41:41 +00001581 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001582
Craig Topper4f12f102014-03-12 06:41:41 +00001583 llvm::Constant *GetPropertyGetFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001584 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001585 }
Craig Topper4f12f102014-03-12 06:41:41 +00001586 llvm::Constant *GetPropertySetFunction() override {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001587 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001588 }
Craig Topper4f12f102014-03-12 06:41:41 +00001589
1590 llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1591 bool copy) override {
Ted Kremeneke65b0862012-03-06 20:05:56 +00001592 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1593 }
Craig Topper4f12f102014-03-12 06:41:41 +00001594
1595 llvm::Constant *GetSetStructFunction() override {
David Chisnall168b80f2010-12-26 22:13:16 +00001596 return ObjCTypes.getCopyStructFn();
1597 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001598
Craig Topper4f12f102014-03-12 06:41:41 +00001599 llvm::Constant *GetGetStructFunction() override {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001600 return ObjCTypes.getCopyStructFn();
1601 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001602
Craig Topper4f12f102014-03-12 06:41:41 +00001603 llvm::Constant *GetCppAtomicObjectSetFunction() override {
David Chisnall0d75e062012-12-17 18:54:24 +00001604 return ObjCTypes.getCppAtomicObjectFunction();
1605 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001606
Craig Topper4f12f102014-03-12 06:41:41 +00001607 llvm::Constant *GetCppAtomicObjectGetFunction() override {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001608 return ObjCTypes.getCppAtomicObjectFunction();
1609 }
Craig Topper4f12f102014-03-12 06:41:41 +00001610
1611 llvm::Constant *EnumerationMutationFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001612 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001613 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001614
Craig Topper4f12f102014-03-12 06:41:41 +00001615 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1616 const ObjCAtTryStmt &S) override;
1617 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1618 const ObjCAtSynchronizedStmt &S) override;
1619 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1620 bool ClearInsertionPoint=true) override;
1621 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001622 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001623 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001624 llvm::Value *src, Address edst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001625 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001626 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001627 bool threadlocal = false) override;
1628 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001629 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001630 llvm::Value *ivarOffset) override;
1631 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001632 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001633 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001634 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001635 llvm::Value *size) override;
1636 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1637 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1638 unsigned CVRQualifiers) override;
1639 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1640 const ObjCInterfaceDecl *Interface,
1641 const ObjCIvarDecl *Ivar) override;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001642};
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001643
1644/// A helper class for performing the null-initialization of a return
1645/// value.
1646struct NullReturnState {
1647 llvm::BasicBlock *NullBB;
Craig Topper8a13c412014-05-21 05:09:00 +00001648 NullReturnState() : NullBB(nullptr) {}
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001649
John McCall3d1e2c92013-02-12 05:53:35 +00001650 /// Perform a null-check of the given receiver.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001651 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
John McCall3d1e2c92013-02-12 05:53:35 +00001652 // Make blocks for the null-receiver and call edges.
1653 NullBB = CGF.createBasicBlock("msgSend.null-receiver");
1654 llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001655
1656 // Check for a null receiver and, if there is one, jump to the
John McCall3d1e2c92013-02-12 05:53:35 +00001657 // null-receiver block. There's no point in trying to avoid it:
1658 // we're always going to put *something* there, because otherwise
1659 // we shouldn't have done this null-check in the first place.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001660 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1661 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1662
1663 // Otherwise, start performing the call.
1664 CGF.EmitBlock(callBB);
1665 }
1666
John McCall3d1e2c92013-02-12 05:53:35 +00001667 /// Complete the null-return operation. It is valid to call this
1668 /// regardless of whether 'init' has been called.
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001669 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
1670 const CallArgList &CallArgs,
1671 const ObjCMethodDecl *Method) {
John McCall3d1e2c92013-02-12 05:53:35 +00001672 // If we never had to do a null-check, just use the raw result.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001673 if (!NullBB) return result;
John McCall3d1e2c92013-02-12 05:53:35 +00001674
1675 // The continuation block. This will be left null if we don't have an
1676 // IP, which can happen if the method we're calling is marked noreturn.
Craig Topper8a13c412014-05-21 05:09:00 +00001677 llvm::BasicBlock *contBB = nullptr;
1678
John McCall3d1e2c92013-02-12 05:53:35 +00001679 // Finish the call path.
1680 llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
1681 if (callBB) {
1682 contBB = CGF.createBasicBlock("msgSend.cont");
1683 CGF.Builder.CreateBr(contBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001684 }
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001685
John McCall3d1e2c92013-02-12 05:53:35 +00001686 // Okay, start emitting the null-receiver block.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001687 CGF.EmitBlock(NullBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001688
John McCall3d1e2c92013-02-12 05:53:35 +00001689 // Release any consumed arguments we've got.
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001690 if (Method) {
1691 CallArgList::const_iterator I = CallArgs.begin();
1692 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1693 e = Method->param_end(); i != e; ++i, ++I) {
1694 const ParmVarDecl *ParamDecl = (*i);
1695 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1696 RValue RV = I->RV;
1697 assert(RV.isScalar() &&
1698 "NullReturnState::complete - arg not on object");
John McCallcdda29c2013-03-13 03:10:54 +00001699 CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001700 }
1701 }
1702 }
John McCall3d1e2c92013-02-12 05:53:35 +00001703
1704 // The phi code below assumes that we haven't needed any control flow yet.
1705 assert(CGF.Builder.GetInsertBlock() == NullBB);
1706
1707 // If we've got a void return, just jump to the continuation block.
1708 if (result.isScalar() && resultType->isVoidType()) {
1709 // No jumps required if the message-send was noreturn.
1710 if (contBB) CGF.EmitBlock(contBB);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001711 return result;
1712 }
1713
John McCall3d1e2c92013-02-12 05:53:35 +00001714 // If we've got a scalar return, build a phi.
1715 if (result.isScalar()) {
1716 // Derive the null-initialization value.
1717 llvm::Constant *null = CGF.CGM.EmitNullConstant(resultType);
1718
1719 // If no join is necessary, just flow out.
1720 if (!contBB) return RValue::get(null);
1721
1722 // Otherwise, build a phi.
1723 CGF.EmitBlock(contBB);
1724 llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2);
1725 phi->addIncoming(result.getScalarVal(), callBB);
1726 phi->addIncoming(null, NullBB);
1727 return RValue::get(phi);
1728 }
1729
1730 // If we've got an aggregate return, null the buffer out.
1731 // FIXME: maybe we should be doing things differently for all the
1732 // cases where the ABI has us returning (1) non-agg values in
1733 // memory or (2) agg values in registers.
1734 if (result.isAggregate()) {
1735 assert(result.isAggregate() && "null init of non-aggregate result?");
John McCall7f416cc2015-09-08 08:05:57 +00001736 CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
John McCall3d1e2c92013-02-12 05:53:35 +00001737 if (contBB) CGF.EmitBlock(contBB);
1738 return result;
1739 }
1740
1741 // Complex types.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001742 CGF.EmitBlock(contBB);
John McCall3d1e2c92013-02-12 05:53:35 +00001743 CodeGenFunction::ComplexPairTy callResult = result.getComplexVal();
1744
1745 // Find the scalar type and its zero value.
1746 llvm::Type *scalarTy = callResult.first->getType();
1747 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1748
1749 // Build phis for both coordinates.
1750 llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2);
1751 real->addIncoming(callResult.first, callBB);
1752 real->addIncoming(scalarZero, NullBB);
1753 llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2);
1754 imag->addIncoming(callResult.second, callBB);
1755 imag->addIncoming(scalarZero, NullBB);
1756 return RValue::getComplex(real, imag);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001757 }
1758};
1759
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001760} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001761
1762/* *** Helper Functions *** */
1763
1764/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001765static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
David Blaikiee3b172a2015-04-02 18:55:21 +00001766 llvm::GlobalVariable *C, unsigned idx0,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001767 unsigned idx1) {
1768 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001769 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1770 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001771 };
David Blaikiee3b172a2015-04-02 18:55:21 +00001772 return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001773}
1774
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001775/// hasObjCExceptionAttribute - Return true if this class or any super
1776/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001777static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001778 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001779 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001780 return true;
1781 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001782 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001783 return false;
1784}
1785
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001786/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001787
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001788CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001789 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001790 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001791 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001792}
1793
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001794/// GetClass - Return a reference to the class for the given interface
1795/// decl.
John McCall882987f2013-02-28 19:01:20 +00001796llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001797 const ObjCInterfaceDecl *ID) {
John McCall882987f2013-02-28 19:01:20 +00001798 return EmitClassRef(CGF, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001799}
1800
1801/// GetSelector - Return the pointer to the unique'd string for this selector.
John McCall7f416cc2015-09-08 08:05:57 +00001802llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
1803 return EmitSelector(CGF, Sel);
1804}
1805Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
1806 return EmitSelectorAddr(CGF, Sel);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001807}
John McCall882987f2013-02-28 19:01:20 +00001808llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001809 *Method) {
John McCall882987f2013-02-28 19:01:20 +00001810 return EmitSelector(CGF, Method->getSelector());
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001811}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001812
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001813llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001814 if (T->isObjCIdType() ||
1815 T->isObjCQualifiedIdType()) {
1816 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001817 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001818 }
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001819 if (T->isObjCClassType() ||
1820 T->isObjCQualifiedClassType()) {
1821 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001822 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001823 }
1824 if (T->isObjCObjectPointerType())
1825 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
1826
John McCall2ca705e2010-07-24 00:37:23 +00001827 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall2ca705e2010-07-24 00:37:23 +00001828}
1829
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001830/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001831/*
1832 struct __builtin_CFString {
1833 const int *isa; // point to __CFConstantStringClassReference
1834 int flags;
1835 const char *str;
1836 long length;
1837 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001838*/
1839
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001840/// or Generate a constant NSString object.
1841/*
1842 struct __builtin_NSString {
1843 const int *isa; // point to __NSConstantStringClassReference
1844 const char *str;
1845 unsigned int length;
1846 };
1847*/
1848
John McCall7f416cc2015-09-08 08:05:57 +00001849ConstantAddress CGObjCCommonMac::GenerateConstantString(
David Chisnall481e3a82010-01-23 02:40:42 +00001850 const StringLiteral *SL) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001851 return (CGM.getLangOpts().NoConstantCFStrings == 0 ?
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001852 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian50c925f2010-10-19 17:19:29 +00001853 CGM.GetAddrOfConstantString(SL));
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001854}
1855
Ted Kremeneke65b0862012-03-06 20:05:56 +00001856enum {
1857 kCFTaggedObjectID_Integer = (1 << 1) + 1
1858};
1859
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001860/// Generates a message send where the super is the receiver. This is
1861/// a message send to self with special delivery semantics indicating
1862/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001863CodeGen::RValue
1864CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001865 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001866 QualType ResultType,
1867 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001868 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001869 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001870 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001871 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001872 const CodeGen::CallArgList &CallArgs,
1873 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001874 // Create and init a super structure; this is a (receiver, class)
1875 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00001876 Address ObjCSuper =
1877 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
1878 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001879 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001880 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
David Blaikie1ed728c2015-04-05 22:45:47 +00001881 CGF.Builder.CreateStore(
1882 ReceiverAsObject,
John McCall7f416cc2015-09-08 08:05:57 +00001883 CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero()));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001884
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001885 // If this is a class message the metaclass is passed as the target.
1886 llvm::Value *Target;
1887 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001888 if (isCategoryImpl) {
1889 // Message sent to 'super' in a class method defined in a category
1890 // implementation requires an odd treatment.
1891 // If we are in a class method, we must retrieve the
1892 // _metaclass_ for the current class, pointed at by
1893 // the class's "isa" pointer. The following assumes that
1894 // isa" is the first ivar in a class (which it must be).
John McCall882987f2013-02-28 19:01:20 +00001895 Target = EmitClassRef(CGF, Class->getSuperClass());
David Blaikie1ed728c2015-04-05 22:45:47 +00001896 Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
John McCall7f416cc2015-09-08 08:05:57 +00001897 Target = CGF.Builder.CreateAlignedLoad(Target, CGF.getPointerAlign());
Mike Stump658fe022009-07-30 22:28:39 +00001898 } else {
David Blaikie1ed728c2015-04-05 22:45:47 +00001899 llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
1900 llvm::Value *SuperPtr =
1901 CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00001902 llvm::Value *Super =
1903 CGF.Builder.CreateAlignedLoad(SuperPtr, CGF.getPointerAlign());
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001904 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001905 }
David Blaikie1ed728c2015-04-05 22:45:47 +00001906 } else if (isCategoryImpl)
John McCall882987f2013-02-28 19:01:20 +00001907 Target = EmitClassRef(CGF, Class->getSuperClass());
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00001908 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001909 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
David Blaikie1ed728c2015-04-05 22:45:47 +00001910 ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00001911 Target = CGF.Builder.CreateAlignedLoad(ClassPtr, CGF.getPointerAlign());
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001912 }
Mike Stump18bb9282009-05-16 07:57:57 +00001913 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1914 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00001915 llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00001916 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00001917 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
John McCall7f416cc2015-09-08 08:05:57 +00001918 CGF.Builder.CreateStore(Target,
1919 CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize()));
John McCall9e8bb002011-05-14 03:10:52 +00001920 return EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00001921 EmitSelector(CGF, Sel),
John McCall7f416cc2015-09-08 08:05:57 +00001922 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall1e3157b2015-09-10 22:27:50 +00001923 true, CallArgs, Method, Class, ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001924}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001925
1926/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001927CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001928 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001929 QualType ResultType,
1930 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001931 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001932 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001933 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001934 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00001935 return EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00001936 EmitSelector(CGF, Sel),
John McCall9e8bb002011-05-14 03:10:52 +00001937 Receiver, CGF.getContext().getObjCIdType(),
John McCall1e3157b2015-09-10 22:27:50 +00001938 false, CallArgs, Method, Class, ObjCTypes);
1939}
1940
1941static bool isWeakLinkedClass(const ObjCInterfaceDecl *ID) {
1942 do {
1943 if (ID->isWeakImported())
1944 return true;
1945 } while ((ID = ID->getSuperClass()));
1946
1947 return false;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00001948}
1949
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001950CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00001951CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1952 ReturnValueSlot Return,
1953 QualType ResultType,
1954 llvm::Value *Sel,
1955 llvm::Value *Arg0,
1956 QualType Arg0Ty,
1957 bool IsSuper,
1958 const CallArgList &CallArgs,
1959 const ObjCMethodDecl *Method,
John McCall1e3157b2015-09-10 22:27:50 +00001960 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00001961 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc722b852008-08-30 03:02:31 +00001962 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00001963 if (!IsSuper)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00001964 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman43dca6a2011-05-02 17:57:46 +00001965 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1966 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCall31168b02011-06-15 23:02:42 +00001967 ActualArgs.addFrom(CallArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001968
John McCalla729c622012-02-17 03:33:10 +00001969 // If we're calling a method, use the formal signature.
1970 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001971
Anders Carlsson280e61f12010-06-21 20:59:55 +00001972 if (Method)
Alp Toker314cc812014-01-25 16:55:45 +00001973 assert(CGM.getContext().getCanonicalType(Method->getReturnType()) ==
1974 CGM.getContext().getCanonicalType(ResultType) &&
Anders Carlsson280e61f12010-06-21 20:59:55 +00001975 "Result type mismatch!");
1976
John McCall1e3157b2015-09-10 22:27:50 +00001977 bool ReceiverCanBeNull = true;
1978
1979 // Super dispatch assumes that self is non-null; even the messenger
1980 // doesn't have a null check internally.
1981 if (IsSuper) {
1982 ReceiverCanBeNull = false;
1983
1984 // If this is a direct dispatch of a class method, check whether the class,
1985 // or anything in its hierarchy, was weak-linked.
1986 } else if (ClassReceiver && Method && Method->isClassMethod()) {
1987 ReceiverCanBeNull = isWeakLinkedClass(ClassReceiver);
1988
1989 // If we're emitting a method, and self is const (meaning just ARC, for now),
1990 // and the receiver is a load of self, then self is a valid object.
1991 } else if (auto CurMethod =
1992 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) {
1993 auto Self = CurMethod->getSelfDecl();
1994 if (Self->getType().isConstQualified()) {
1995 if (auto LI = dyn_cast<llvm::LoadInst>(Arg0->stripPointerCasts())) {
1996 llvm::Value *SelfAddr = CGF.GetAddrOfLocalVar(Self).getPointer();
1997 if (SelfAddr == LI->getPointerOperand()) {
1998 ReceiverCanBeNull = false;
1999 }
2000 }
2001 }
2002 }
2003
John McCall5880fb82011-05-14 21:12:11 +00002004 NullReturnState nullReturn;
2005
Craig Topper8a13c412014-05-21 05:09:00 +00002006 llvm::Constant *Fn = nullptr;
Tim Northovere77cc392014-03-29 13:28:05 +00002007 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
John McCall1e3157b2015-09-10 22:27:50 +00002008 if (ReceiverCanBeNull) nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002009 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002010 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00002011 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
2012 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2013 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +00002014 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
2015 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2016 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002017 } else {
Tim Northovere77cc392014-03-29 13:28:05 +00002018 // arm64 uses objc_msgSend for stret methods and yet null receiver check
2019 // must be made for it.
Ahmed Bougachaa3df87b2015-10-02 22:41:59 +00002020 if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
Tim Northovere77cc392014-03-29 13:28:05 +00002021 nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002022 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002023 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002024 }
John McCall1e3157b2015-09-10 22:27:50 +00002025
2026 // Emit a null-check if there's a consumed argument other than the receiver.
2027 bool RequiresNullCheck = false;
2028 if (ReceiverCanBeNull && CGM.getLangOpts().ObjCAutoRefCount && Method) {
David Majnemer59f77922016-06-24 04:05:48 +00002029 for (const auto *ParamDecl : Method->parameters()) {
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002030 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
2031 if (!nullReturn.NullBB)
2032 nullReturn.init(CGF, Arg0);
John McCall1e3157b2015-09-10 22:27:50 +00002033 RequiresNullCheck = true;
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002034 break;
2035 }
2036 }
John McCall1e3157b2015-09-10 22:27:50 +00002037 }
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002038
John McCall1e3157b2015-09-10 22:27:50 +00002039 llvm::Instruction *CallSite;
John McCalla729c622012-02-17 03:33:10 +00002040 Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
John McCallb92ab1a2016-10-26 23:46:34 +00002041 CGCallee Callee = CGCallee::forDirect(Fn);
2042 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2043 &CallSite);
John McCall1e3157b2015-09-10 22:27:50 +00002044
2045 // Mark the call as noreturn if the method is marked noreturn and the
2046 // receiver cannot be null.
2047 if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
2048 llvm::CallSite(CallSite).setDoesNotReturn();
2049 }
2050
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002051 return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
John McCall1e3157b2015-09-10 22:27:50 +00002052 RequiresNullCheck ? Method : nullptr);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002053}
2054
John McCall3fd13f062015-10-21 18:06:47 +00002055static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT,
2056 bool pointee = false) {
2057 // Note that GC qualification applies recursively to C pointer types
2058 // that aren't otherwise decorated. This is weird, but it's probably
2059 // an intentional workaround to the unreliable placement of GC qualifiers.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002060 if (FQT.isObjCGCStrong())
2061 return Qualifiers::Strong;
John McCall3fd13f062015-10-21 18:06:47 +00002062
2063 if (FQT.isObjCGCWeak())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002064 return Qualifiers::Weak;
John McCall3fd13f062015-10-21 18:06:47 +00002065
2066 if (auto ownership = FQT.getObjCLifetime()) {
2067 // Ownership does not apply recursively to C pointer types.
2068 if (pointee) return Qualifiers::GCNone;
2069 switch (ownership) {
2070 case Qualifiers::OCL_Weak: return Qualifiers::Weak;
2071 case Qualifiers::OCL_Strong: return Qualifiers::Strong;
2072 case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone;
2073 case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?");
2074 case Qualifiers::OCL_None: llvm_unreachable("known nonzero");
2075 }
2076 llvm_unreachable("bad objc ownership");
2077 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002078
John McCall3fd13f062015-10-21 18:06:47 +00002079 // Treat unqualified retainable pointers as strong.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002080 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
2081 return Qualifiers::Strong;
2082
John McCall3fd13f062015-10-21 18:06:47 +00002083 // Walk into C pointer types, but only in GC.
2084 if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) {
2085 if (const PointerType *PT = FQT->getAs<PointerType>())
2086 return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true);
2087 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002088
2089 return Qualifiers::GCNone;
2090}
2091
John McCall3fd13f062015-10-21 18:06:47 +00002092namespace {
2093 struct IvarInfo {
2094 CharUnits Offset;
2095 uint64_t SizeInWords;
2096 IvarInfo(CharUnits offset, uint64_t sizeInWords)
2097 : Offset(offset), SizeInWords(sizeInWords) {}
2098
2099 // Allow sorting based on byte pos.
2100 bool operator<(const IvarInfo &other) const {
2101 return Offset < other.Offset;
2102 }
2103 };
2104
2105 /// A helper class for building GC layout strings.
2106 class IvarLayoutBuilder {
2107 CodeGenModule &CGM;
2108
2109 /// The start of the layout. Offsets will be relative to this value,
2110 /// and entries less than this value will be silently discarded.
2111 CharUnits InstanceBegin;
2112
2113 /// The end of the layout. Offsets will never exceed this value.
2114 CharUnits InstanceEnd;
2115
2116 /// Whether we're generating the strong layout or the weak layout.
2117 bool ForStrongLayout;
2118
2119 /// Whether the offsets in IvarsInfo might be out-of-order.
2120 bool IsDisordered = false;
2121
2122 llvm::SmallVector<IvarInfo, 8> IvarsInfo;
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002123
John McCall3fd13f062015-10-21 18:06:47 +00002124 public:
2125 IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
2126 CharUnits instanceEnd, bool forStrongLayout)
2127 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2128 ForStrongLayout(forStrongLayout) {
2129 }
2130
2131 void visitRecord(const RecordType *RT, CharUnits offset);
2132
2133 template <class Iterator, class GetOffsetFn>
2134 void visitAggregate(Iterator begin, Iterator end,
2135 CharUnits aggrOffset,
2136 const GetOffsetFn &getOffset);
2137
2138 void visitField(const FieldDecl *field, CharUnits offset);
2139
2140 /// Add the layout of a block implementation.
2141 void visitBlock(const CGBlockInfo &blockInfo);
2142
2143 /// Is there any information for an interesting bitmap?
2144 bool hasBitmapData() const { return !IvarsInfo.empty(); }
2145
2146 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2147 llvm::SmallVectorImpl<unsigned char> &buffer);
2148
2149 static void dump(ArrayRef<unsigned char> buffer) {
2150 const unsigned char *s = buffer.data();
2151 for (unsigned i = 0, e = buffer.size(); i < e; i++)
2152 if (!(s[i] & 0xf0))
2153 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
2154 else
2155 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
2156 printf("\n");
2157 }
2158 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002159} // end anonymous namespace
John McCall3fd13f062015-10-21 18:06:47 +00002160
John McCall351762c2011-02-07 10:33:21 +00002161llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
2162 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002163
Chris Lattnerece04092012-02-07 00:39:47 +00002164 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
John McCall460ce582015-10-22 18:38:17 +00002165 if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
John McCall351762c2011-02-07 10:33:21 +00002166 return nullPtr;
2167
John McCall3fd13f062015-10-21 18:06:47 +00002168 IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize,
2169 /*for strong layout*/ true);
2170
2171 builder.visitBlock(blockInfo);
2172
2173 if (!builder.hasBitmapData())
2174 return nullPtr;
2175
2176 llvm::SmallVector<unsigned char, 32> buffer;
2177 llvm::Constant *C = builder.buildBitmap(*this, buffer);
John McCallf5ea0722015-10-29 23:36:14 +00002178 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
John McCall3fd13f062015-10-21 18:06:47 +00002179 printf("\n block variable layout for block: ");
2180 builder.dump(buffer);
2181 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002182
John McCall3fd13f062015-10-21 18:06:47 +00002183 return C;
2184}
2185
2186void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00002187 // __isa is the first field in block descriptor and must assume by runtime's
2188 // convention that it is GC'able.
John McCall3fd13f062015-10-21 18:06:47 +00002189 IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1));
John McCall351762c2011-02-07 10:33:21 +00002190
2191 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2192
John McCall351762c2011-02-07 10:33:21 +00002193 // Ignore the optional 'this' capture: C++ objects are not assumed
2194 // to be GC'ed.
2195
John McCall3fd13f062015-10-21 18:06:47 +00002196 CharUnits lastFieldOffset;
2197
John McCall351762c2011-02-07 10:33:21 +00002198 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002199 for (const auto &CI : blockDecl->captures()) {
2200 const VarDecl *variable = CI.getVariable();
John McCall351762c2011-02-07 10:33:21 +00002201 QualType type = variable->getType();
2202
2203 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2204
2205 // Ignore constant captures.
2206 if (capture.isConstant()) continue;
2207
John McCall3fd13f062015-10-21 18:06:47 +00002208 CharUnits fieldOffset = capture.getOffset();
2209
2210 // Block fields are not necessarily ordered; if we detect that we're
2211 // adding them out-of-order, make sure we sort later.
2212 if (fieldOffset < lastFieldOffset)
2213 IsDisordered = true;
2214 lastFieldOffset = fieldOffset;
John McCall351762c2011-02-07 10:33:21 +00002215
2216 // __block variables are passed by their descriptor address.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002217 if (CI.isByRef()) {
John McCall3fd13f062015-10-21 18:06:47 +00002218 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00002219 continue;
John McCall351762c2011-02-07 10:33:21 +00002220 }
2221
2222 assert(!type->isArrayType() && "array variable should not be caught");
2223 if (const RecordType *record = type->getAs<RecordType>()) {
John McCall3fd13f062015-10-21 18:06:47 +00002224 visitRecord(record, fieldOffset);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00002225 continue;
2226 }
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00002227
John McCall351762c2011-02-07 10:33:21 +00002228 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
John McCall351762c2011-02-07 10:33:21 +00002229
John McCall3fd13f062015-10-21 18:06:47 +00002230 if (GCAttr == Qualifiers::Strong) {
2231 assert(CGM.getContext().getTypeSize(type)
2232 == CGM.getTarget().getPointerWidth(0));
2233 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
2234 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002235 }
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00002236}
2237
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00002238/// getBlockCaptureLifetime - This routine returns life time of the captured
2239/// block variable for the purpose of block layout meta-data generation. FQT is
2240/// the type of the variable captured in the block.
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002241Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
2242 bool ByrefLayout) {
John McCall460ce582015-10-22 18:38:17 +00002243 // If it has an ownership qualifier, we're done.
2244 if (auto lifetime = FQT.getObjCLifetime())
2245 return lifetime;
2246
2247 // If it doesn't, and this is ARC, it has no ownership.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002248 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCall460ce582015-10-22 18:38:17 +00002249 return Qualifiers::OCL_None;
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002250
John McCall460ce582015-10-22 18:38:17 +00002251 // In MRC, retainable pointers are owned by non-__block variables.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002252 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002253 return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002254
2255 return Qualifiers::OCL_None;
2256}
2257
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002258void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
2259 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002260 CharUnits FieldOffset,
2261 CharUnits FieldSize) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002262 // __block variables are passed by their descriptor address.
2263 if (IsByref)
2264 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002265 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002266 else if (LifeTime == Qualifiers::OCL_Strong)
2267 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002268 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002269 else if (LifeTime == Qualifiers::OCL_Weak)
2270 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002271 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002272 else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2273 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002274 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002275 else
2276 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2277 FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002278 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002279}
2280
2281void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2282 const RecordDecl *RD,
2283 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002284 CharUnits BytePos, bool &HasUnion,
2285 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002286 bool IsUnion = (RD && RD->isUnion());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002287 CharUnits MaxUnionSize = CharUnits::Zero();
Craig Topper8a13c412014-05-21 05:09:00 +00002288 const FieldDecl *MaxField = nullptr;
2289 const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002290 CharUnits MaxFieldOffset = CharUnits::Zero();
2291 CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002292
2293 if (RecFields.empty())
2294 return;
John McCallc8e01702013-04-16 22:48:15 +00002295 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002296
2297 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2298 const FieldDecl *Field = RecFields[i];
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002299 // Note that 'i' here is actually the field index inside RD of Field,
2300 // although this dependency is hidden.
2301 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002302 CharUnits FieldOffset =
2303 CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002304
2305 // Skip over unnamed or bitfields
2306 if (!Field->getIdentifier() || Field->isBitField()) {
2307 LastFieldBitfieldOrUnnamed = Field;
2308 LastBitfieldOrUnnamedOffset = FieldOffset;
2309 continue;
2310 }
Craig Topper8a13c412014-05-21 05:09:00 +00002311
2312 LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002313 QualType FQT = Field->getType();
2314 if (FQT->isRecordType() || FQT->isUnionType()) {
2315 if (FQT->isUnionType())
2316 HasUnion = true;
2317
2318 BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
2319 BytePos + FieldOffset, HasUnion);
2320 continue;
2321 }
2322
2323 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2324 const ConstantArrayType *CArray =
2325 dyn_cast_or_null<ConstantArrayType>(Array);
2326 uint64_t ElCount = CArray->getSize().getZExtValue();
2327 assert(CArray && "only array with known element size is supported");
2328 FQT = CArray->getElementType();
2329 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2330 const ConstantArrayType *CArray =
2331 dyn_cast_or_null<ConstantArrayType>(Array);
2332 ElCount *= CArray->getSize().getZExtValue();
2333 FQT = CArray->getElementType();
2334 }
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002335 if (FQT->isRecordType() && ElCount) {
2336 int OldIndex = RunSkipBlockVars.size() - 1;
2337 const RecordType *RT = FQT->getAs<RecordType>();
2338 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
2339 HasUnion);
2340
2341 // Replicate layout information for each array element. Note that
2342 // one element is already done.
2343 uint64_t ElIx = 1;
2344 for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002345 CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002346 for (int i = OldIndex+1; i <= FirstIndex; ++i)
2347 RunSkipBlockVars.push_back(
2348 RUN_SKIP(RunSkipBlockVars[i].opcode,
2349 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2350 RunSkipBlockVars[i].block_var_size));
2351 }
2352 continue;
2353 }
2354 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002355 CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002356 if (IsUnion) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002357 CharUnits UnionIvarSize = FieldSize;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002358 if (UnionIvarSize > MaxUnionSize) {
2359 MaxUnionSize = UnionIvarSize;
2360 MaxField = Field;
2361 MaxFieldOffset = FieldOffset;
2362 }
2363 } else {
2364 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002365 getBlockCaptureLifetime(FQT, ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002366 BytePos + FieldOffset,
2367 FieldSize);
2368 }
2369 }
2370
2371 if (LastFieldBitfieldOrUnnamed) {
2372 if (LastFieldBitfieldOrUnnamed->isBitField()) {
2373 // Last field was a bitfield. Must update the info.
2374 uint64_t BitFieldSize
2375 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002376 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
Eli Friedman8cbca202012-11-06 22:15:52 +00002377 ((BitFieldSize % ByteSizeInBits) != 0);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002378 CharUnits Size = CharUnits::fromQuantity(UnsSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002379 Size += LastBitfieldOrUnnamedOffset;
2380 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002381 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2382 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002383 BytePos + LastBitfieldOrUnnamedOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002384 Size);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002385 } else {
2386 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2387 // Last field was unnamed. Must update skip info.
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002388 CharUnits FieldSize
2389 = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002390 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002391 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2392 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002393 BytePos + LastBitfieldOrUnnamedOffset,
2394 FieldSize);
2395 }
2396 }
2397
2398 if (MaxField)
2399 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002400 getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002401 BytePos + MaxFieldOffset,
2402 MaxUnionSize);
2403}
2404
2405void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002406 CharUnits BytePos,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002407 bool &HasUnion,
2408 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002409 const RecordDecl *RD = RT->getDecl();
Aaron Ballman62e47c42014-03-10 13:43:55 +00002410 SmallVector<const FieldDecl*, 16> Fields(RD->fields());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002411 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
2412 const llvm::StructLayout *RecLayout =
2413 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2414
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002415 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002416}
2417
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002418/// InlineLayoutInstruction - This routine produce an inline instruction for the
2419/// block variable layout if it can. If not, it returns 0. Rules are as follow:
2420/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
2421/// an inline layout of value 0x0000000000000xyz is interpreted as follows:
2422/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
2423/// y captured object of BLOCK_LAYOUT_BYREF. Followed by
2424/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
2425/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
2426/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
2427uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2428 SmallVectorImpl<unsigned char> &Layout) {
2429 uint64_t Result = 0;
2430 if (Layout.size() <= 3) {
2431 unsigned size = Layout.size();
2432 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2433 unsigned char inst;
2434 enum BLOCK_LAYOUT_OPCODE opcode ;
2435 switch (size) {
2436 case 3:
2437 inst = Layout[0];
2438 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2439 if (opcode == BLOCK_LAYOUT_STRONG)
2440 strong_word_count = (inst & 0xF)+1;
2441 else
2442 return 0;
2443 inst = Layout[1];
2444 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2445 if (opcode == BLOCK_LAYOUT_BYREF)
2446 byref_word_count = (inst & 0xF)+1;
2447 else
2448 return 0;
2449 inst = Layout[2];
2450 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2451 if (opcode == BLOCK_LAYOUT_WEAK)
2452 weak_word_count = (inst & 0xF)+1;
2453 else
2454 return 0;
2455 break;
2456
2457 case 2:
2458 inst = Layout[0];
2459 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2460 if (opcode == BLOCK_LAYOUT_STRONG) {
2461 strong_word_count = (inst & 0xF)+1;
2462 inst = Layout[1];
2463 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2464 if (opcode == BLOCK_LAYOUT_BYREF)
2465 byref_word_count = (inst & 0xF)+1;
2466 else if (opcode == BLOCK_LAYOUT_WEAK)
2467 weak_word_count = (inst & 0xF)+1;
2468 else
2469 return 0;
2470 }
2471 else if (opcode == BLOCK_LAYOUT_BYREF) {
2472 byref_word_count = (inst & 0xF)+1;
2473 inst = Layout[1];
2474 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2475 if (opcode == BLOCK_LAYOUT_WEAK)
2476 weak_word_count = (inst & 0xF)+1;
2477 else
2478 return 0;
2479 }
2480 else
2481 return 0;
2482 break;
2483
2484 case 1:
2485 inst = Layout[0];
2486 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2487 if (opcode == BLOCK_LAYOUT_STRONG)
2488 strong_word_count = (inst & 0xF)+1;
2489 else if (opcode == BLOCK_LAYOUT_BYREF)
2490 byref_word_count = (inst & 0xF)+1;
2491 else if (opcode == BLOCK_LAYOUT_WEAK)
2492 weak_word_count = (inst & 0xF)+1;
2493 else
2494 return 0;
2495 break;
2496
2497 default:
2498 return 0;
2499 }
2500
2501 // Cannot inline when any of the word counts is 15. Because this is one less
2502 // than the actual work count (so 15 means 16 actual word counts),
2503 // and we can only display 0 thru 15 word counts.
2504 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2505 return 0;
2506
2507 unsigned count =
2508 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2509
2510 if (size == count) {
2511 if (strong_word_count)
2512 Result = strong_word_count;
2513 Result <<= 4;
2514 if (byref_word_count)
2515 Result += byref_word_count;
2516 Result <<= 4;
2517 if (weak_word_count)
2518 Result += weak_word_count;
2519 }
2520 }
2521 return Result;
2522}
2523
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002524llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
2525 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2526 if (RunSkipBlockVars.empty())
2527 return nullPtr;
John McCallc8e01702013-04-16 22:48:15 +00002528 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2529 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002530 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2531
2532 // Sort on byte position; captures might not be allocated in order,
2533 // and unions can do funny things.
2534 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2535 SmallVector<unsigned char, 16> Layout;
2536
2537 unsigned size = RunSkipBlockVars.size();
2538 for (unsigned i = 0; i < size; i++) {
2539 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2540 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2541 CharUnits end_byte_pos = start_byte_pos;
2542 unsigned j = i+1;
2543 while (j < size) {
2544 if (opcode == RunSkipBlockVars[j].opcode) {
2545 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2546 i++;
2547 }
2548 else
2549 break;
2550 }
2551 CharUnits size_in_bytes =
2552 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2553 if (j < size) {
2554 CharUnits gap =
2555 RunSkipBlockVars[j].block_var_bytepos -
2556 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2557 size_in_bytes += gap;
2558 }
2559 CharUnits residue_in_bytes = CharUnits::Zero();
2560 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2561 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2562 size_in_bytes -= residue_in_bytes;
2563 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2564 }
2565
2566 unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
2567 while (size_in_words >= 16) {
2568 // Note that value in imm. is one less that the actual
2569 // value. So, 0xf means 16 words follow!
2570 unsigned char inst = (opcode << 4) | 0xf;
2571 Layout.push_back(inst);
2572 size_in_words -= 16;
2573 }
2574 if (size_in_words > 0) {
2575 // Note that value in imm. is one less that the actual
2576 // value. So, we subtract 1 away!
2577 unsigned char inst = (opcode << 4) | (size_in_words-1);
2578 Layout.push_back(inst);
2579 }
2580 if (residue_in_bytes > CharUnits::Zero()) {
2581 unsigned char inst =
2582 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
2583 Layout.push_back(inst);
2584 }
2585 }
2586
John McCall7f416cc2015-09-08 08:05:57 +00002587 while (!Layout.empty()) {
2588 unsigned char inst = Layout.back();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002589 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2590 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2591 Layout.pop_back();
2592 else
2593 break;
2594 }
2595
2596 uint64_t Result = InlineLayoutInstruction(Layout);
2597 if (Result != 0) {
2598 // Block variable layout instruction has been inlined.
2599 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2600 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002601 printf("\n Inline BYREF variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002602 else
John McCall7f416cc2015-09-08 08:05:57 +00002603 printf("\n Inline block variable layout: ");
2604 printf("0x0%" PRIx64 "", Result);
2605 if (auto numStrong = (Result & 0xF00) >> 8)
2606 printf(", BL_STRONG:%d", (int) numStrong);
2607 if (auto numByref = (Result & 0x0F0) >> 4)
2608 printf(", BL_BYREF:%d", (int) numByref);
2609 if (auto numWeak = (Result & 0x00F) >> 0)
2610 printf(", BL_WEAK:%d", (int) numWeak);
2611 printf(", BL_OPERATOR:0\n");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002612 }
Vedant Kumar3ed0df02015-12-21 19:43:25 +00002613 return llvm::ConstantInt::get(CGM.IntPtrTy, Result);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002614 }
2615
2616 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2617 Layout.push_back(inst);
2618 std::string BitMap;
2619 for (unsigned i = 0, e = Layout.size(); i != e; i++)
2620 BitMap += Layout[i];
2621
2622 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2623 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002624 printf("\n Byref variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002625 else
John McCall7f416cc2015-09-08 08:05:57 +00002626 printf("\n Block variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002627 for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
2628 unsigned char inst = BitMap[i];
2629 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2630 unsigned delta = 1;
2631 switch (opcode) {
2632 case BLOCK_LAYOUT_OPERATOR:
2633 printf("BL_OPERATOR:");
2634 delta = 0;
2635 break;
2636 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2637 printf("BL_NON_OBJECT_BYTES:");
2638 break;
2639 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2640 printf("BL_NON_OBJECT_WORD:");
2641 break;
2642 case BLOCK_LAYOUT_STRONG:
2643 printf("BL_STRONG:");
2644 break;
2645 case BLOCK_LAYOUT_BYREF:
2646 printf("BL_BYREF:");
2647 break;
2648 case BLOCK_LAYOUT_WEAK:
2649 printf("BL_WEAK:");
2650 break;
2651 case BLOCK_LAYOUT_UNRETAINED:
2652 printf("BL_UNRETAINED:");
2653 break;
2654 }
2655 // Actual value of word count is one more that what is in the imm.
2656 // field of the instruction
2657 printf("%d", (inst & 0xf) + delta);
2658 if (i < e-1)
2659 printf(", ");
2660 else
2661 printf("\n");
2662 }
2663 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00002664
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00002665 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2666 /*ForceNonFragileABI=*/true,
2667 /*NullTerminate=*/false);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002668 return getConstantGEP(VMContext, Entry, 0, 0);
2669}
2670
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002671llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2672 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002673 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2674
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002675 RunSkipBlockVars.clear();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002676 bool hasUnion = false;
2677
John McCallc8e01702013-04-16 22:48:15 +00002678 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2679 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002680 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2681
2682 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2683
2684 // Calculate the basic layout of the block structure.
2685 const llvm::StructLayout *layout =
2686 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
2687
2688 // Ignore the optional 'this' capture: C++ objects are not assumed
2689 // to be GC'ed.
Fariborz Jahanian4cf177e2012-12-04 17:20:57 +00002690 if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
2691 UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
2692 blockInfo.BlockHeaderForcedGapOffset,
2693 blockInfo.BlockHeaderForcedGapSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002694 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002695 for (const auto &CI : blockDecl->captures()) {
2696 const VarDecl *variable = CI.getVariable();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002697 QualType type = variable->getType();
2698
2699 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2700
2701 // Ignore constant captures.
2702 if (capture.isConstant()) continue;
2703
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002704 CharUnits fieldOffset =
2705 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002706
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002707 assert(!type->isArrayType() && "array variable should not be caught");
Aaron Ballman9371dd22014-03-14 18:34:04 +00002708 if (!CI.isByRef())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002709 if (const RecordType *record = type->getAs<RecordType>()) {
2710 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2711 continue;
2712 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002713 CharUnits fieldSize;
Aaron Ballman9371dd22014-03-14 18:34:04 +00002714 if (CI.isByRef())
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002715 fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2716 else
2717 fieldSize = CGM.getContext().getTypeSizeInChars(type);
Aaron Ballman9371dd22014-03-14 18:34:04 +00002718 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002719 fieldOffset, fieldSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002720 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002721 return getBitmapBlockLayout(false);
2722}
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002723
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002724llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2725 QualType T) {
2726 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2727 assert(!T->isArrayType() && "__block array variable should not be caught");
2728 CharUnits fieldOffset;
2729 RunSkipBlockVars.clear();
2730 bool hasUnion = false;
2731 if (const RecordType *record = T->getAs<RecordType>()) {
2732 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
2733 llvm::Constant *Result = getBitmapBlockLayout(true);
Vedant Kumar2f5bb1152015-12-21 20:21:15 +00002734 if (isa<llvm::ConstantInt>(Result))
2735 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002736 return Result;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002737 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002738 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2739 return nullPtr;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002740}
2741
John McCall882987f2013-02-28 19:01:20 +00002742llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00002743 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00002744 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002745 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00002746 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2747
Owen Andersonade90fd2009-07-29 18:54:39 +00002748 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00002749 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002750}
2751
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002752void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00002753 // FIXME: We shouldn't need this, the protocol decl should contain enough
2754 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00002755 DefinedProtocols.insert(PD->getIdentifier());
2756
2757 // If we have generated a forward reference to this protocol, emit
2758 // it now. Otherwise do nothing, the protocol objects are lazily
2759 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002760 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00002761 GetOrEmitProtocol(PD);
2762}
2763
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002764llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002765 if (DefinedProtocols.count(PD->getIdentifier()))
2766 return GetOrEmitProtocol(PD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002767
Daniel Dunbarc475d422008-10-29 22:36:39 +00002768 return GetOrEmitProtocolRef(PD);
2769}
2770
Douglas Gregor24ae22c2016-04-01 23:23:52 +00002771llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
2772 CodeGenFunction &CGF,
2773 const ObjCInterfaceDecl *ID,
2774 ObjCCommonTypesHelper &ObjCTypes) {
2775 llvm::Constant *lookUpClassFn = ObjCTypes.getLookUpClassFn();
2776
2777 llvm::Value *className =
2778 CGF.CGM.GetAddrOfConstantCString(ID->getObjCRuntimeNameAsString())
2779 .getPointer();
2780 ASTContext &ctx = CGF.CGM.getContext();
2781 className =
2782 CGF.Builder.CreateBitCast(className,
2783 CGF.ConvertType(
2784 ctx.getPointerType(ctx.CharTy.withConst())));
2785 llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className);
2786 call->setDoesNotThrow();
2787 return call;
2788}
2789
Daniel Dunbarb036db82008-08-13 03:21:16 +00002790/*
Rafael Espindolaf9e1e5e2014-02-20 14:09:04 +00002791// Objective-C 1.0 extensions
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002792struct _objc_protocol {
2793struct _objc_protocol_extension *isa;
2794char *protocol_name;
2795struct _objc_protocol_list *protocol_list;
2796struct _objc__method_prototype_list *instance_methods;
2797struct _objc__method_prototype_list *class_methods
2798};
Daniel Dunbarb036db82008-08-13 03:21:16 +00002799
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002800See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00002801*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00002802llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00002803 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbarc475d422008-10-29 22:36:39 +00002804
2805 // Early exit if a defining object has already been generated.
2806 if (Entry && Entry->hasInitializer())
2807 return Entry;
2808
Douglas Gregora715bff2012-01-01 19:51:50 +00002809 // Use the protocol definition, if there is one.
2810 if (const ObjCProtocolDecl *Def = PD->getDefinition())
2811 PD = Def;
2812
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002813 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002814 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002815 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2816
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002817 // Construct method lists.
John McCall176f8922016-11-30 02:39:18 +00002818 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002819
John McCall176f8922016-11-30 02:39:18 +00002820 ConstantInitBuilder builder(CGM);
2821 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
2822 values.add(EmitProtocolExtension(PD, methodLists));
2823 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
2824 values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
2825 PD->protocol_begin(), PD->protocol_end()));
2826 values.add(methodLists.emitMethodList(this, PD,
2827 ProtocolMethodLists::RequiredInstanceMethods));
2828 values.add(methodLists.emitMethodList(this, PD,
2829 ProtocolMethodLists::RequiredClassMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002830
Daniel Dunbarb036db82008-08-13 03:21:16 +00002831 if (Entry) {
Rafael Espindola5d117f32014-03-06 01:10:46 +00002832 // Already created, update the initializer.
Rafael Espindolab3262952014-05-09 00:43:37 +00002833 assert(Entry->hasPrivateLinkage());
John McCall176f8922016-11-30 02:39:18 +00002834 values.finishAndSetAsInitializer(Entry);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002835 } else {
John McCall176f8922016-11-30 02:39:18 +00002836 Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(),
2837 CGM.getPointerAlign(),
2838 /*constant*/ false,
2839 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002840 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
John McCallf9582a72012-03-30 21:29:05 +00002841
2842 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002843 }
Rafael Espindola060062a2014-03-06 22:15:10 +00002844 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00002845
2846 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002847}
2848
Daniel Dunbarc475d422008-10-29 22:36:39 +00002849llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002850 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
2851
2852 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002853 // We use the initializer as a marker of whether this is a forward
2854 // reference or not. At module finalization we add the empty
2855 // contents for protocols which were referenced but never defined.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00002856 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
2857 false, llvm::GlobalValue::PrivateLinkage,
2858 nullptr, "OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002859 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002860 // FIXME: Is this necessary? Why only for protocol?
2861 Entry->setAlignment(4);
2862 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002863
Daniel Dunbarb036db82008-08-13 03:21:16 +00002864 return Entry;
2865}
2866
2867/*
2868 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002869 uint32_t size;
2870 struct objc_method_description_list *optional_instance_methods;
2871 struct objc_method_description_list *optional_class_methods;
2872 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002873 const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00002874 struct objc_property_list *class_properties;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002875 };
2876*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002877llvm::Constant *
2878CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00002879 const ProtocolMethodLists &methodLists) {
2880 auto optInstanceMethods =
2881 methodLists.emitMethodList(this, PD,
2882 ProtocolMethodLists::OptionalInstanceMethods);
2883 auto optClassMethods =
2884 methodLists.emitMethodList(this, PD,
2885 ProtocolMethodLists::OptionalClassMethods);
2886
2887 auto extendedMethodTypes =
2888 EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
2889 methodLists.emitExtendedTypesArray(this),
2890 ObjCTypes);
2891
2892 auto instanceProperties =
2893 EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD,
2894 ObjCTypes, false);
2895 auto classProperties =
2896 EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr,
2897 PD, ObjCTypes, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002898
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002899 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00002900 if (optInstanceMethods->isNullValue() &&
2901 optClassMethods->isNullValue() &&
2902 extendedMethodTypes->isNullValue() &&
2903 instanceProperties->isNullValue() &&
2904 classProperties->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00002905 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00002906 }
Daniel Dunbarb036db82008-08-13 03:21:16 +00002907
John McCall176f8922016-11-30 02:39:18 +00002908 uint64_t size =
2909 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
2910
2911 ConstantInitBuilder builder(CGM);
2912 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
2913 values.addInt(ObjCTypes.IntTy, size);
2914 values.add(optInstanceMethods);
2915 values.add(optClassMethods);
2916 values.add(instanceProperties);
2917 values.add(extendedMethodTypes);
2918 values.add(classProperties);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002919
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002920 // No special section, but goes in llvm.used
John McCall176f8922016-11-30 02:39:18 +00002921 return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00002922 StringRef(), CGM.getPointerAlign(), true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002923}
2924
2925/*
2926 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002927 struct objc_protocol_list *next;
2928 long count;
2929 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002930 };
2931*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00002932llvm::Constant *
John McCall176f8922016-11-30 02:39:18 +00002933CGObjCMac::EmitProtocolList(Twine name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00002934 ObjCProtocolDecl::protocol_iterator begin,
2935 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002936 // Just return null for empty protocol lists
John McCall176f8922016-11-30 02:39:18 +00002937 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00002938 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002939
John McCall176f8922016-11-30 02:39:18 +00002940 ConstantInitBuilder builder(CGM);
2941 auto values = builder.beginStruct();
Daniel Dunbarb036db82008-08-13 03:21:16 +00002942
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002943 // This field is only used by the runtime.
John McCall176f8922016-11-30 02:39:18 +00002944 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002945
John McCall176f8922016-11-30 02:39:18 +00002946 // Reserve a slot for the count.
2947 auto countSlot = values.addPlaceholder();
2948
2949 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
2950 for (; begin != end; ++begin) {
2951 refsArray.add(GetProtocolRef(*begin));
2952 }
2953 auto count = refsArray.size();
2954
2955 // This list is null terminated.
2956 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
2957
2958 refsArray.finishAndAddTo(values);
2959 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
2960
2961 StringRef section;
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00002962 if (CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00002963 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00002964
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002965 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00002966 CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false);
Owen Andersonade90fd2009-07-29 18:54:39 +00002967 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002968}
2969
John McCall176f8922016-11-30 02:39:18 +00002970static void
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002971PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
John McCall176f8922016-11-30 02:39:18 +00002972 SmallVectorImpl<const ObjCPropertyDecl *> &Properties,
Aaron Ballmandc4bea42014-03-13 18:47:37 +00002973 const ObjCProtocolDecl *Proto,
Manman Renad0e7912016-01-29 19:22:54 +00002974 bool IsClassProperty) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00002975 for (const auto *P : Proto->protocols())
John McCall176f8922016-11-30 02:39:18 +00002976 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Manman Renad0e7912016-01-29 19:22:54 +00002977
2978 for (const auto *PD : Proto->properties()) {
2979 if (IsClassProperty != PD->isClassProperty())
2980 continue;
David Blaikie82e95a32014-11-19 07:49:47 +00002981 if (!PropertySet.insert(PD->getIdentifier()).second)
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002982 continue;
John McCall176f8922016-11-30 02:39:18 +00002983 Properties.push_back(PD);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002984 }
2985}
2986
Daniel Dunbarb036db82008-08-13 03:21:16 +00002987/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002988 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00002989 const char * const name;
2990 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002991 };
2992
2993 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002994 uint32_t entsize; // sizeof (struct _objc_property)
2995 uint32_t prop_count;
2996 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002997 };
2998*/
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002999llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003000 const Decl *Container,
3001 const ObjCContainerDecl *OCD,
Manman Renad0e7912016-01-29 19:22:54 +00003002 const ObjCCommonTypesHelper &ObjCTypes,
3003 bool IsClassProperty) {
Manman Ren01b705e2016-04-19 19:05:03 +00003004 if (IsClassProperty) {
3005 // Make this entry NULL for OS X with deployment target < 10.11, for iOS
3006 // with deployment target < 9.0.
3007 const llvm::Triple &Triple = CGM.getTarget().getTriple();
3008 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3009 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3010 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3011 }
3012
John McCall176f8922016-11-30 02:39:18 +00003013 SmallVector<const ObjCPropertyDecl *, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003014 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Nico Weber08c93332015-12-03 17:44:51 +00003015
Nico Weber08c93332015-12-03 17:44:51 +00003016 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3017 for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
Manman Renad0e7912016-01-29 19:22:54 +00003018 for (auto *PD : ClassExt->properties()) {
3019 if (IsClassProperty != PD->isClassProperty())
3020 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003021 PropertySet.insert(PD->getIdentifier());
John McCall176f8922016-11-30 02:39:18 +00003022 Properties.push_back(PD);
Nico Weber08c93332015-12-03 17:44:51 +00003023 }
Manman Renad0e7912016-01-29 19:22:54 +00003024
3025 for (const auto *PD : OCD->properties()) {
3026 if (IsClassProperty != PD->isClassProperty())
3027 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003028 // Don't emit duplicate metadata for properties that were already in a
3029 // class extension.
3030 if (!PropertySet.insert(PD->getIdentifier()).second)
3031 continue;
John McCall176f8922016-11-30 02:39:18 +00003032 Properties.push_back(PD);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003033 }
Nico Weber08c93332015-12-03 17:44:51 +00003034
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003035 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003036 for (const auto *P : OID->all_referenced_protocols())
John McCall176f8922016-11-30 02:39:18 +00003037 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003038 }
3039 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
Aaron Ballman19a41762014-03-14 12:55:57 +00003040 for (const auto *P : CD->protocols())
John McCall176f8922016-11-30 02:39:18 +00003041 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003042 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003043
3044 // Return null for empty list.
3045 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003046 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003047
John McCall176f8922016-11-30 02:39:18 +00003048 unsigned propertySize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00003049 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
John McCall176f8922016-11-30 02:39:18 +00003050
3051 ConstantInitBuilder builder(CGM);
3052 auto values = builder.beginStruct();
3053 values.addInt(ObjCTypes.IntTy, propertySize);
3054 values.addInt(ObjCTypes.IntTy, Properties.size());
3055 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3056 for (auto PD : Properties) {
3057 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3058 property.add(GetPropertyName(PD->getIdentifier()));
3059 property.add(GetPropertyTypeString(PD, Container));
3060 property.finishAndAddTo(propertiesArray);
3061 }
3062 propertiesArray.finishAndAddTo(values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003063
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003064 StringRef Section;
3065 if (CGM.getTriple().isOSBinFormatMachO())
3066 Section = (ObjCABI == 2) ? "__DATA, __objc_const"
3067 : "__OBJC,__property,regular,no_dead_strip";
3068
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003069 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003070 CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003071 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003072}
3073
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003074llvm::Constant *
3075CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
3076 ArrayRef<llvm::Constant*> MethodTypes,
3077 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003078 // Return null for empty list.
3079 if (MethodTypes.empty())
3080 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3081
3082 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3083 MethodTypes.size());
3084 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
3085
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003086 StringRef Section;
3087 if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3088 Section = "__DATA, __objc_const";
3089
3090 llvm::GlobalVariable *GV =
3091 CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003092 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
3093}
3094
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003095/*
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003096 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003097 char *category_name;
3098 char *class_name;
3099 struct _objc_method_list *instance_methods;
3100 struct _objc_method_list *class_methods;
3101 struct _objc_protocol_list *protocols;
3102 uint32_t size; // <rdar://4585769>
3103 struct _objc_property_list *instance_properties;
Manman Ren96df0b32016-01-29 23:45:01 +00003104 struct _objc_property_list *class_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003105 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003106*/
Daniel Dunbar92992502008-08-15 22:20:32 +00003107void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00003108 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003109
Mike Stump18bb9282009-05-16 07:57:57 +00003110 // FIXME: This is poor design, the OCD should have a pointer to the category
3111 // decl. Additionally, note that Category can be null for the @implementation
3112 // w/o an @interface case. Sema should just create one for us as it does for
3113 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003114 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003115 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003116 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003117
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003118 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003119 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
3120 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003121
John McCall176f8922016-11-30 02:39:18 +00003122 ConstantInitBuilder Builder(CGM);
3123 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
Aaron Ballmanf26acce2014-03-13 19:50:17 +00003124
John McCall176f8922016-11-30 02:39:18 +00003125 enum {
3126 InstanceMethods,
3127 ClassMethods,
3128 NumMethodLists
3129 };
3130 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3131 for (const auto *MD : OCD->methods()) {
3132 Methods[unsigned(MD->isClassMethod())].push_back(MD);
3133 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003134
John McCall176f8922016-11-30 02:39:18 +00003135 Values.add(GetClassName(OCD->getName()));
3136 Values.add(GetClassName(Interface->getObjCRuntimeNameAsString()));
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00003137 LazySymbols.insert(Interface->getIdentifier());
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003138
John McCall176f8922016-11-30 02:39:18 +00003139 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3140 Methods[InstanceMethods]));
3141 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3142 Methods[ClassMethods]));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003143 if (Category) {
John McCall176f8922016-11-30 02:39:18 +00003144 Values.add(
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003145 EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003146 Category->protocol_begin(), Category->protocol_end()));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003147 } else {
John McCall176f8922016-11-30 02:39:18 +00003148 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003149 }
John McCall176f8922016-11-30 02:39:18 +00003150 Values.addInt(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003151
3152 // If there is no category @interface then there can be no properties.
3153 if (Category) {
John McCall176f8922016-11-30 02:39:18 +00003154 Values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
3155 OCD, Category, ObjCTypes, false));
3156 Values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
3157 OCD, Category, ObjCTypes, true));
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003158 } else {
John McCall176f8922016-11-30 02:39:18 +00003159 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3160 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003161 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003162
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003163 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003164 CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values,
John McCall7f416cc2015-09-08 08:05:57 +00003165 "__OBJC,__category,regular,no_dead_strip",
3166 CGM.getPointerAlign(), true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003167 DefinedCategories.push_back(GV);
Justin Lebar5e83dfe2016-10-21 21:45:01 +00003168 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003169 // method definition entries must be clear for next implementation.
3170 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003171}
3172
John McCallef19dbb2012-10-17 04:53:23 +00003173enum FragileClassFlags {
John McCall460ce582015-10-22 18:38:17 +00003174 /// Apparently: is not a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003175 FragileABI_Class_Factory = 0x00001,
John McCall460ce582015-10-22 18:38:17 +00003176
3177 /// Is a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003178 FragileABI_Class_Meta = 0x00002,
John McCall460ce582015-10-22 18:38:17 +00003179
3180 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003181 FragileABI_Class_HasCXXStructors = 0x02000,
John McCall460ce582015-10-22 18:38:17 +00003182
3183 /// Has hidden visibility.
John McCall09ec1ec2015-10-21 22:06:03 +00003184 FragileABI_Class_Hidden = 0x20000,
John McCall460ce582015-10-22 18:38:17 +00003185
3186 /// Class implementation was compiled under ARC.
3187 FragileABI_Class_CompiledByARC = 0x04000000,
3188
3189 /// Class implementation was compiled under MRC and has MRC weak ivars.
3190 /// Exclusive with CompiledByARC.
3191 FragileABI_Class_HasMRCWeakIvars = 0x08000000,
John McCallef19dbb2012-10-17 04:53:23 +00003192};
3193
3194enum NonFragileClassFlags {
3195 /// Is a meta-class.
3196 NonFragileABI_Class_Meta = 0x00001,
3197
3198 /// Is a root class.
3199 NonFragileABI_Class_Root = 0x00002,
3200
John McCall460ce582015-10-22 18:38:17 +00003201 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003202 NonFragileABI_Class_HasCXXStructors = 0x00004,
3203
3204 /// Has hidden visibility.
3205 NonFragileABI_Class_Hidden = 0x00010,
3206
3207 /// Has the exception attribute.
3208 NonFragileABI_Class_Exception = 0x00020,
3209
3210 /// (Obsolete) ARC-specific: this class has a .release_ivars method
3211 NonFragileABI_Class_HasIvarReleaser = 0x00040,
3212
3213 /// Class implementation was compiled under ARC.
John McCall0d54a172012-10-17 04:53:31 +00003214 NonFragileABI_Class_CompiledByARC = 0x00080,
3215
3216 /// Class has non-trivial destructors, but zero-initialization is okay.
John McCall460ce582015-10-22 18:38:17 +00003217 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100,
3218
3219 /// Class implementation was compiled under MRC and has MRC weak ivars.
3220 /// Exclusive with CompiledByARC.
3221 NonFragileABI_Class_HasMRCWeakIvars = 0x00200,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003222};
3223
John McCall460ce582015-10-22 18:38:17 +00003224static bool hasWeakMember(QualType type) {
3225 if (type.getObjCLifetime() == Qualifiers::OCL_Weak) {
3226 return true;
3227 }
3228
3229 if (auto recType = type->getAs<RecordType>()) {
3230 for (auto field : recType->getDecl()->fields()) {
3231 if (hasWeakMember(field->getType()))
3232 return true;
3233 }
3234 }
3235
3236 return false;
3237}
3238
3239/// For compatibility, we only want to set the "HasMRCWeakIvars" flag
3240/// (and actually fill in a layout string) if we really do have any
3241/// __weak ivars.
3242static bool hasMRCWeakIvars(CodeGenModule &CGM,
3243 const ObjCImplementationDecl *ID) {
3244 if (!CGM.getLangOpts().ObjCWeak) return false;
3245 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
3246
3247 for (const ObjCIvarDecl *ivar =
3248 ID->getClassInterface()->all_declared_ivar_begin();
3249 ivar; ivar = ivar->getNextIvar()) {
3250 if (hasWeakMember(ivar->getType()))
3251 return true;
3252 }
3253
3254 return false;
3255}
3256
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003257/*
3258 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003259 Class isa;
3260 Class super_class;
3261 const char *name;
3262 long version;
3263 long info;
3264 long instance_size;
3265 struct _objc_ivar_list *ivars;
3266 struct _objc_method_list *methods;
3267 struct _objc_cache *cache;
3268 struct _objc_protocol_list *protocols;
3269 // Objective-C 1.0 extensions (<rdr://4585769>)
3270 const char *ivar_layout;
3271 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003272 };
3273
3274 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003275*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003276void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003277 DefinedSymbols.insert(ID->getIdentifier());
3278
Chris Lattner86d7d912008-11-24 03:54:41 +00003279 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003280 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003281 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003282 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003283 llvm::Constant *Protocols =
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003284 EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(),
3285 Interface->all_referenced_protocol_begin(),
3286 Interface->all_referenced_protocol_end());
John McCallef19dbb2012-10-17 04:53:23 +00003287 unsigned Flags = FragileABI_Class_Factory;
John McCall0d54a172012-10-17 04:53:31 +00003288 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCallef19dbb2012-10-17 04:53:23 +00003289 Flags |= FragileABI_Class_HasCXXStructors;
John McCall09ec1ec2015-10-21 22:06:03 +00003290
John McCall460ce582015-10-22 18:38:17 +00003291 bool hasMRCWeak = false;
3292
John McCall09ec1ec2015-10-21 22:06:03 +00003293 if (CGM.getLangOpts().ObjCAutoRefCount)
3294 Flags |= FragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00003295 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
3296 Flags |= FragileABI_Class_HasMRCWeakIvars;
John McCall09ec1ec2015-10-21 22:06:03 +00003297
John McCall3fd13f062015-10-21 18:06:47 +00003298 CharUnits Size =
3299 CGM.getContext().getASTObjCImplementationLayout(ID).getSize();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003300
3301 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00003302 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003303 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003304
John McCall176f8922016-11-30 02:39:18 +00003305 enum {
3306 InstanceMethods,
3307 ClassMethods,
3308 NumMethodLists
3309 };
3310 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3311 for (const auto *MD : ID->methods()) {
3312 Methods[unsigned(MD->isClassMethod())].push_back(MD);
3313 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003314
Aaron Ballmand85eff42014-03-14 15:02:45 +00003315 for (const auto *PID : ID->property_impls()) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003316 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3317 ObjCPropertyDecl *PD = PID->getPropertyDecl();
3318
3319 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003320 if (GetMethodDefinition(MD))
3321 Methods[InstanceMethods].push_back(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003322 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003323 if (GetMethodDefinition(MD))
3324 Methods[InstanceMethods].push_back(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003325 }
3326 }
3327
John McCall176f8922016-11-30 02:39:18 +00003328 ConstantInitBuilder builder(CGM);
3329 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3330 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003331 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003332 // Record a reference to the super class.
3333 LazySymbols.insert(Super->getIdentifier());
3334
John McCall176f8922016-11-30 02:39:18 +00003335 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3336 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003337 } else {
John McCall176f8922016-11-30 02:39:18 +00003338 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003339 }
John McCall176f8922016-11-30 02:39:18 +00003340 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003341 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003342 values.addInt(ObjCTypes.LongTy, 0);
3343 values.addInt(ObjCTypes.LongTy, Flags);
3344 values.addInt(ObjCTypes.LongTy, Size.getQuantity());
3345 values.add(EmitIvarList(ID, false));
3346 values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods,
3347 Methods[InstanceMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003348 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003349 values.addNullPointer(ObjCTypes.CachePtrTy);
3350 values.add(Protocols);
3351 values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size));
3352 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3353 /*isMetaclass*/ false));
3354
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003355 std::string Name("OBJC_CLASS_");
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003356 Name += ClassName;
3357 const char *Section = "__OBJC,__class,regular,no_dead_strip";
3358 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003359 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003360 if (GV) {
3361 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3362 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003363 values.finishAndSetAsInitializer(GV);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003364 GV->setSection(Section);
John McCall7f416cc2015-09-08 08:05:57 +00003365 GV->setAlignment(CGM.getPointerAlign().getQuantity());
Rafael Espindola060062a2014-03-06 22:15:10 +00003366 CGM.addCompilerUsedGlobal(GV);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003367 } else
John McCall176f8922016-11-30 02:39:18 +00003368 GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003369 DefinedClasses.push_back(GV);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00003370 ImplementedClasses.push_back(Interface);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003371 // method definition entries must be clear for next implementation.
3372 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003373}
3374
3375llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3376 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00003377 ArrayRef<const ObjCMethodDecl*> Methods) {
John McCallef19dbb2012-10-17 04:53:23 +00003378 unsigned Flags = FragileABI_Class_Meta;
Micah Villmowdd31ca12012-10-08 16:25:52 +00003379 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003380
John McCall457a04e2010-10-22 21:05:15 +00003381 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003382 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003383
John McCall176f8922016-11-30 02:39:18 +00003384 ConstantInitBuilder builder(CGM);
3385 auto values = builder.beginStruct(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003386 // The isa for the metaclass is the root of the hierarchy.
3387 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3388 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3389 Root = Super;
John McCall176f8922016-11-30 02:39:18 +00003390 values.addBitCast(GetClassName(Root->getObjCRuntimeNameAsString()),
3391 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003392 // The super class for the metaclass is emitted as the name of the
3393 // super class. The runtime fixes this up to point to the
3394 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003395 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
John McCall176f8922016-11-30 02:39:18 +00003396 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3397 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003398 } else {
John McCall176f8922016-11-30 02:39:18 +00003399 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003400 }
John McCall176f8922016-11-30 02:39:18 +00003401 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003402 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003403 values.addInt(ObjCTypes.LongTy, 0);
3404 values.addInt(ObjCTypes.LongTy, Flags);
3405 values.addInt(ObjCTypes.LongTy, Size);
3406 values.add(EmitIvarList(ID, true));
3407 values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods,
3408 Methods));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003409 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003410 values.addNullPointer(ObjCTypes.CachePtrTy);
3411 values.add(Protocols);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003412 // ivar_layout for metaclass is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003413 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Renad0e7912016-01-29 19:22:54 +00003414 // The class extension is used to store class properties for metaclasses.
John McCall176f8922016-11-30 02:39:18 +00003415 values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/,
3416 /*isMetaclass*/true));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003417
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003418 std::string Name("OBJC_METACLASS_");
Benjamin Kramer1bbcbd02012-07-31 11:45:39 +00003419 Name += ID->getName();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003420
3421 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003422 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003423 if (GV) {
3424 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3425 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003426 values.finishAndSetAsInitializer(GV);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003427 } else {
John McCall176f8922016-11-30 02:39:18 +00003428 GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
3429 /*constant*/ false,
3430 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003431 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003432 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00003433 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003434
3435 return GV;
3436}
3437
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003438llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003439 std::string Name = "OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003440
Mike Stump18bb9282009-05-16 07:57:57 +00003441 // FIXME: Should we look these up somewhere other than the module. Its a bit
3442 // silly since we only generate these while processing an implementation, so
3443 // exactly one pointer would work if know when we entered/exitted an
3444 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003445
3446 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00003447 // Previously, metaclass with internal linkage may have been defined.
3448 // pass 'true' as 2nd argument so it is returned.
Rafael Espindola21039aa2014-02-27 16:26:32 +00003449 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3450 if (!GV)
3451 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003452 llvm::GlobalValue::PrivateLinkage, nullptr,
3453 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003454
3455 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3456 "Forward metaclass reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003457 return GV;
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003458}
3459
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003460llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003461 std::string Name = "OBJC_CLASS_" + ID->getNameAsString();
Rafael Espindola21039aa2014-02-27 16:26:32 +00003462 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3463
3464 if (!GV)
3465 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003466 llvm::GlobalValue::PrivateLinkage, nullptr,
3467 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003468
3469 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3470 "Forward class metadata reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003471 return GV;
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003472}
3473
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003474/*
John McCall3fd13f062015-10-21 18:06:47 +00003475 Emit a "class extension", which in this specific context means extra
3476 data that doesn't fit in the normal fragile-ABI class structure, and
3477 has nothing to do with the language concept of a class extension.
3478
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003479 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003480 uint32_t size;
3481 const char *weak_ivar_layout;
3482 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003483 };
3484*/
3485llvm::Constant *
John McCall3fd13f062015-10-21 18:06:47 +00003486CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
Manman Renad0e7912016-01-29 19:22:54 +00003487 CharUnits InstanceSize, bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00003488 bool isMetaclass) {
3489 // Weak ivar layout.
3490 llvm::Constant *layout;
3491 if (isMetaclass) {
3492 layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
3493 } else {
3494 layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
3495 hasMRCWeakIvars);
3496 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003497
John McCall176f8922016-11-30 02:39:18 +00003498 // Properties.
3499 llvm::Constant *propertyList =
3500 EmitPropertyList((isMetaclass ? Twine("\01l_OBJC_$_CLASS_PROP_LIST_")
3501 : Twine("\01l_OBJC_$_PROP_LIST_"))
3502 + ID->getName(),
3503 ID, ID->getClassInterface(), ObjCTypes, isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003504
3505 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00003506 if (layout->isNullValue() && propertyList->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003507 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003508 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003509
John McCall176f8922016-11-30 02:39:18 +00003510 uint64_t size =
3511 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3512
3513 ConstantInitBuilder builder(CGM);
3514 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3515 values.addInt(ObjCTypes.IntTy, size);
3516 values.add(layout);
3517 values.add(propertyList);
3518
3519 return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00003520 "__OBJC,__class_ext,regular,no_dead_strip",
3521 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003522}
3523
3524/*
3525 struct objc_ivar {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003526 char *ivar_name;
3527 char *ivar_type;
3528 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003529 };
3530
3531 struct objc_ivar_list {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003532 int ivar_count;
3533 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003534 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003535*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003536llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003537 bool ForClass) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003538 // When emitting the root class GCC emits ivar entries for the
3539 // actual class structure. It is not clear if we need to follow this
3540 // behavior; for now lets try and get away with not doing it. If so,
3541 // the cleanest solution would be to make up an ObjCInterfaceDecl
3542 // for the class.
3543 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00003544 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003545
Jordy Rosea91768e2011-07-22 02:08:32 +00003546 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003547
John McCall176f8922016-11-30 02:39:18 +00003548 ConstantInitBuilder builder(CGM);
3549 auto ivarList = builder.beginStruct();
3550 auto countSlot = ivarList.addPlaceholder();
3551 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3552
Jordy Rosea91768e2011-07-22 02:08:32 +00003553 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00003554 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00003555 // Ignore unnamed bit-fields.
3556 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003557 continue;
John McCall176f8922016-11-30 02:39:18 +00003558
3559 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3560 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3561 ivar.add(GetMethodVarType(IVD));
3562 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3563 ivar.finishAndAddTo(ivars);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003564 }
3565
3566 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00003567 auto count = ivars.size();
3568 if (count == 0) {
3569 ivars.abandon();
3570 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00003571 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003572 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003573
John McCall176f8922016-11-30 02:39:18 +00003574 ivars.finishAndAddTo(ivarList);
3575 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003576
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003577 llvm::GlobalVariable *GV;
3578 if (ForClass)
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003579 GV =
John McCall176f8922016-11-30 02:39:18 +00003580 CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003581 "__OBJC,__class_vars,regular,no_dead_strip",
3582 CGM.getPointerAlign(), true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003583 else
John McCall176f8922016-11-30 02:39:18 +00003584 GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003585 "__OBJC,__instance_vars,regular,no_dead_strip",
3586 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003587 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003588}
3589
John McCall176f8922016-11-30 02:39:18 +00003590/// Build a struct objc_method_description constant for the given method.
3591///
3592/// struct objc_method_description {
3593/// SEL method_name;
3594/// char *method_types;
3595/// };
3596void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
3597 const ObjCMethodDecl *MD) {
3598 auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy);
3599 description.addBitCast(GetMethodVarName(MD->getSelector()),
3600 ObjCTypes.SelectorPtrTy);
3601 description.add(GetMethodVarType(MD));
3602 description.finishAndAddTo(builder);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003603}
3604
John McCall176f8922016-11-30 02:39:18 +00003605/// Build a struct objc_method constant for the given method.
3606///
3607/// struct objc_method {
3608/// SEL method_name;
3609/// char *method_types;
3610/// void *method;
3611/// };
3612void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
3613 const ObjCMethodDecl *MD) {
3614 llvm::Function *fn = GetMethodDefinition(MD);
3615 assert(fn && "no definition registered for method");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003616
John McCall176f8922016-11-30 02:39:18 +00003617 auto method = builder.beginStruct(ObjCTypes.MethodTy);
3618 method.addBitCast(GetMethodVarName(MD->getSelector()),
3619 ObjCTypes.SelectorPtrTy);
3620 method.add(GetMethodVarType(MD));
3621 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
3622 method.finishAndAddTo(builder);
3623}
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003624
John McCall176f8922016-11-30 02:39:18 +00003625/// Build a struct objc_method_list or struct objc_method_description_list,
3626/// as appropriate.
3627///
3628/// struct objc_method_list {
3629/// struct objc_method_list *obsolete;
3630/// int count;
3631/// struct objc_method methods_list[count];
3632/// };
3633///
3634/// struct objc_method_description_list {
3635/// int count;
3636/// struct objc_method_description list[count];
3637/// };
3638llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3639 ArrayRef<const ObjCMethodDecl *> methods) {
3640 StringRef prefix;
3641 StringRef section;
3642 bool forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003643 switch (MLT) {
3644 case MethodListType::CategoryInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003645 prefix = "OBJC_CATEGORY_INSTANCE_METHODS_";
3646 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3647 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003648 break;
3649 case MethodListType::CategoryClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003650 prefix = "OBJC_CATEGORY_CLASS_METHODS_";
3651 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3652 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003653 break;
3654 case MethodListType::InstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003655 prefix = "OBJC_INSTANCE_METHODS_";
3656 section = "__OBJC,__inst_meth,regular,no_dead_strip";
3657 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003658 break;
3659 case MethodListType::ClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003660 prefix = "OBJC_CLASS_METHODS_";
3661 section = "__OBJC,__cls_meth,regular,no_dead_strip";
3662 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003663 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003664 case MethodListType::ProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003665 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_";
3666 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3667 forProtocol = true;
3668 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003669 case MethodListType::ProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003670 prefix = "OBJC_PROTOCOL_CLASS_METHODS_";
3671 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3672 forProtocol = true;
3673 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003674 case MethodListType::OptionalProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003675 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3676 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3677 forProtocol = true;
3678 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003679 case MethodListType::OptionalProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003680 prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3681 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3682 forProtocol = true;
3683 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003684 }
3685
John McCall176f8922016-11-30 02:39:18 +00003686 // Return null for empty list.
3687 if (methods.empty())
3688 return llvm::Constant::getNullValue(forProtocol
3689 ? ObjCTypes.MethodDescriptionListPtrTy
3690 : ObjCTypes.MethodListPtrTy);
3691
3692 // For protocols, this is an objc_method_description_list, which has
3693 // a slightly different structure.
3694 if (forProtocol) {
3695 ConstantInitBuilder builder(CGM);
3696 auto values = builder.beginStruct();
3697 values.addInt(ObjCTypes.IntTy, methods.size());
3698 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3699 for (auto MD : methods) {
3700 emitMethodDescriptionConstant(methodArray, MD);
3701 }
3702 methodArray.finishAndAddTo(values);
3703
3704 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3705 CGM.getPointerAlign(), true);
3706 return llvm::ConstantExpr::getBitCast(GV,
3707 ObjCTypes.MethodDescriptionListPtrTy);
3708 }
3709
3710 // Otherwise, it's an objc_method_list.
3711 ConstantInitBuilder builder(CGM);
3712 auto values = builder.beginStruct();
3713 values.addNullPointer(ObjCTypes.Int8PtrTy);
3714 values.addInt(ObjCTypes.IntTy, methods.size());
3715 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3716 for (auto MD : methods) {
3717 emitMethodConstant(methodArray, MD);
3718 }
3719 methodArray.finishAndAddTo(values);
3720
3721 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003722 CGM.getPointerAlign(), true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003723 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003724}
3725
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00003726llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003727 const ObjCContainerDecl *CD) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003728 SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00003729 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003730
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00003731 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00003732 llvm::FunctionType *MethodTy =
John McCalla729c622012-02-17 03:33:10 +00003733 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003734 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00003735 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003736 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00003737 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003738 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003739 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003740
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003741 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003742}
3743
Alp Toker541d5072014-06-07 23:30:53 +00003744llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
John McCall176f8922016-11-30 02:39:18 +00003745 ConstantStructBuilder &Init,
3746 StringRef Section,
3747 CharUnits Align,
3748 bool AddToUsed) {
3749 llvm::GlobalVariable *GV =
3750 Init.finishAndCreateGlobal(Name, Align, /*constant*/ false,
3751 llvm::GlobalValue::PrivateLinkage);
3752 if (!Section.empty())
3753 GV->setSection(Section);
3754 if (AddToUsed)
3755 CGM.addCompilerUsedGlobal(GV);
3756 return GV;
3757}
3758
3759llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
Alp Toker541d5072014-06-07 23:30:53 +00003760 llvm::Constant *Init,
3761 StringRef Section,
John McCall7f416cc2015-09-08 08:05:57 +00003762 CharUnits Align,
Alp Toker541d5072014-06-07 23:30:53 +00003763 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003764 llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003765 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00003766 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00003767 llvm::GlobalValue::PrivateLinkage, Init, Name);
Alp Toker541d5072014-06-07 23:30:53 +00003768 if (!Section.empty())
Daniel Dunbar30c65362009-03-09 20:09:19 +00003769 GV->setSection(Section);
John McCall7f416cc2015-09-08 08:05:57 +00003770 GV->setAlignment(Align.getQuantity());
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003771 if (AddToUsed)
Rafael Espindola060062a2014-03-06 22:15:10 +00003772 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003773 return GV;
3774}
3775
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003776llvm::GlobalVariable *
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003777CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type,
3778 bool ForceNonFragileABI,
3779 bool NullTerminate) {
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003780 StringRef Label;
3781 switch (Type) {
3782 case ObjCLabelType::ClassName: Label = "OBJC_CLASS_NAME_"; break;
3783 case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break;
3784 case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break;
3785 case ObjCLabelType::PropertyName: Label = "OBJC_PROP_NAME_ATTR_"; break;
3786 }
3787
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003788 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
3789
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003790 StringRef Section;
3791 switch (Type) {
3792 case ObjCLabelType::ClassName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003793 Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals"
3794 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003795 break;
3796 case ObjCLabelType::MethodVarName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003797 Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
3798 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003799 break;
3800 case ObjCLabelType::MethodVarType:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003801 Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals"
3802 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003803 break;
3804 case ObjCLabelType::PropertyName:
3805 Section = "__TEXT,__cstring,cstring_literals";
3806 break;
3807 }
3808
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003809 llvm::Constant *Value =
3810 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003811 llvm::GlobalVariable *GV =
Saleem Abdulrasool0c54dc82016-09-18 16:12:04 +00003812 new llvm::GlobalVariable(CGM.getModule(), Value->getType(),
3813 /*isConstant=*/true,
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003814 llvm::GlobalValue::PrivateLinkage, Value, Label);
Saleem Abdulrasool3f307512016-09-18 16:12:14 +00003815 if (CGM.getTriple().isOSBinFormatMachO())
3816 GV->setSection(Section);
3817 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003818 GV->setAlignment(CharUnits::One().getQuantity());
3819 CGM.addCompilerUsedGlobal(GV);
3820
3821 return GV;
3822}
3823
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003824llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003825 // Abuse this interface function as a place to finalize.
3826 FinishModule();
Craig Topper8a13c412014-05-21 05:09:00 +00003827 return nullptr;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003828}
3829
Chris Lattnerd4808922009-03-22 21:03:39 +00003830llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003831 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003832}
3833
Chris Lattnerd4808922009-03-22 21:03:39 +00003834llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003835 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003836}
3837
Ted Kremeneke65b0862012-03-06 20:05:56 +00003838llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
3839 bool copy) {
3840 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
3841}
3842
David Chisnall168b80f2010-12-26 22:13:16 +00003843llvm::Constant *CGObjCMac::GetGetStructFunction() {
3844 return ObjCTypes.getCopyStructFn();
3845}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00003846
David Chisnall168b80f2010-12-26 22:13:16 +00003847llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00003848 return ObjCTypes.getCopyStructFn();
3849}
3850
David Chisnall0d75e062012-12-17 18:54:24 +00003851llvm::Constant *CGObjCMac::GetCppAtomicObjectGetFunction() {
3852 return ObjCTypes.getCppAtomicObjectFunction();
3853}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00003854
David Chisnall0d75e062012-12-17 18:54:24 +00003855llvm::Constant *CGObjCMac::GetCppAtomicObjectSetFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00003856 return ObjCTypes.getCppAtomicObjectFunction();
3857}
3858
Chris Lattnerd4808922009-03-22 21:03:39 +00003859llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003860 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00003861}
3862
John McCallbd309292010-07-06 01:34:17 +00003863void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
3864 return EmitTryOrSynchronizedStmt(CGF, S);
3865}
3866
3867void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
3868 const ObjCAtSynchronizedStmt &S) {
3869 return EmitTryOrSynchronizedStmt(CGF, S);
3870}
3871
John McCall65bea082010-07-21 06:59:36 +00003872namespace {
David Blaikie7e70d682015-08-18 22:40:54 +00003873 struct PerformFragileFinally final : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00003874 const Stmt &S;
John McCall7f416cc2015-09-08 08:05:57 +00003875 Address SyncArgSlot;
3876 Address CallTryExitVar;
3877 Address ExceptionData;
John McCall65bea082010-07-21 06:59:36 +00003878 ObjCTypesHelper &ObjCTypes;
3879 PerformFragileFinally(const Stmt *S,
John McCall7f416cc2015-09-08 08:05:57 +00003880 Address SyncArgSlot,
3881 Address CallTryExitVar,
3882 Address ExceptionData,
John McCall65bea082010-07-21 06:59:36 +00003883 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00003884 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00003885 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
3886
Craig Topper4f12f102014-03-12 06:41:41 +00003887 void Emit(CodeGenFunction &CGF, Flags flags) override {
John McCall65bea082010-07-21 06:59:36 +00003888 // Check whether we need to call objc_exception_try_exit.
3889 // In optimized code, this branch will always be folded.
3890 llvm::BasicBlock *FinallyCallExit =
3891 CGF.createBasicBlock("finally.call_exit");
3892 llvm::BasicBlock *FinallyNoCallExit =
3893 CGF.createBasicBlock("finally.no_call_exit");
3894 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
3895 FinallyCallExit, FinallyNoCallExit);
3896
3897 CGF.EmitBlock(FinallyCallExit);
John McCall882987f2013-02-28 19:01:20 +00003898 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
John McCall7f416cc2015-09-08 08:05:57 +00003899 ExceptionData.getPointer());
John McCall65bea082010-07-21 06:59:36 +00003900
3901 CGF.EmitBlock(FinallyNoCallExit);
3902
3903 if (isa<ObjCAtTryStmt>(S)) {
3904 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00003905 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
John McCall638d4f52013-04-03 00:56:07 +00003906 // Don't try to do the @finally if this is an EH cleanup.
3907 if (flags.isForEHCleanup()) return;
3908
John McCallcebe0ca2010-08-11 00:16:14 +00003909 // Save the current cleanup destination in case there's
3910 // control flow inside the finally statement.
3911 llvm::Value *CurCleanupDest =
3912 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
3913
John McCall65bea082010-07-21 06:59:36 +00003914 CGF.EmitStmt(FinallyStmt->getFinallyBody());
3915
John McCallcebe0ca2010-08-11 00:16:14 +00003916 if (CGF.HaveInsertPoint()) {
3917 CGF.Builder.CreateStore(CurCleanupDest,
3918 CGF.getNormalCleanupDestSlot());
3919 } else {
3920 // Currently, the end of the cleanup must always exist.
3921 CGF.EnsureInsertPoint();
3922 }
3923 }
John McCall65bea082010-07-21 06:59:36 +00003924 } else {
3925 // Emit objc_sync_exit(expr); as finally's sole statement for
3926 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00003927 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall882987f2013-02-28 19:01:20 +00003928 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg);
John McCall65bea082010-07-21 06:59:36 +00003929 }
3930 }
3931 };
John McCall42227ed2010-07-31 23:20:56 +00003932
3933 class FragileHazards {
3934 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003935 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00003936 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
3937
3938 llvm::InlineAsm *ReadHazard;
3939 llvm::InlineAsm *WriteHazard;
3940
3941 llvm::FunctionType *GetAsmFnType();
3942
3943 void collectLocals();
3944 void emitReadHazard(CGBuilderTy &Builder);
3945
3946 public:
3947 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00003948
John McCall42227ed2010-07-31 23:20:56 +00003949 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00003950 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003951 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00003952} // end anonymous namespace
John McCall42227ed2010-07-31 23:20:56 +00003953
3954/// Create the fragile-ABI read and write hazards based on the current
3955/// state of the function, which is presumed to be immediately prior
3956/// to a @try block. These hazards are used to maintain correct
3957/// semantics in the face of optimization and the fragile ABI's
3958/// cavalier use of setjmp/longjmp.
3959FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
3960 collectLocals();
3961
3962 if (Locals.empty()) return;
3963
3964 // Collect all the blocks in the function.
3965 for (llvm::Function::iterator
3966 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
3967 BlocksBeforeTry.insert(&*I);
3968
3969 llvm::FunctionType *AsmFnTy = GetAsmFnType();
3970
3971 // Create a read hazard for the allocas. This inhibits dead-store
3972 // optimizations and forces the values to memory. This hazard is
3973 // inserted before any 'throwing' calls in the protected scope to
3974 // reflect the possibility that the variables might be read from the
3975 // catch block if the call throws.
3976 {
3977 std::string Constraint;
3978 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3979 if (I) Constraint += ',';
3980 Constraint += "*m";
3981 }
3982
3983 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3984 }
3985
3986 // Create a write hazard for the allocas. This inhibits folding
3987 // loads across the hazard. This hazard is inserted at the
3988 // beginning of the catch path to reflect the possibility that the
3989 // variables might have been written within the protected scope.
3990 {
3991 std::string Constraint;
3992 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3993 if (I) Constraint += ',';
3994 Constraint += "=*m";
3995 }
3996
3997 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3998 }
3999}
4000
4001/// Emit a write hazard at the current location.
4002void FragileHazards::emitWriteHazard() {
4003 if (Locals.empty()) return;
4004
John McCall882987f2013-02-28 19:01:20 +00004005 CGF.EmitNounwindRuntimeCall(WriteHazard, Locals);
John McCall42227ed2010-07-31 23:20:56 +00004006}
4007
John McCall42227ed2010-07-31 23:20:56 +00004008void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
4009 assert(!Locals.empty());
John McCall882987f2013-02-28 19:01:20 +00004010 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4011 call->setDoesNotThrow();
4012 call->setCallingConv(CGF.getRuntimeCC());
John McCall42227ed2010-07-31 23:20:56 +00004013}
4014
4015/// Emit read hazards in all the protected blocks, i.e. all the blocks
4016/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00004017void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00004018 if (Locals.empty()) return;
4019
John McCall7f416cc2015-09-08 08:05:57 +00004020 CGBuilderTy Builder(CGF, CGF.getLLVMContext());
John McCall42227ed2010-07-31 23:20:56 +00004021
4022 // Iterate through all blocks, skipping those prior to the try.
4023 for (llvm::Function::iterator
4024 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
4025 llvm::BasicBlock &BB = *FI;
4026 if (BlocksBeforeTry.count(&BB)) continue;
4027
4028 // Walk through all the calls in the block.
4029 for (llvm::BasicBlock::iterator
4030 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
4031 llvm::Instruction &I = *BI;
4032
4033 // Ignore instructions that aren't non-intrinsic calls.
4034 // These are the only calls that can possibly call longjmp.
4035 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
4036 if (isa<llvm::IntrinsicInst>(I))
4037 continue;
4038
4039 // Ignore call sites marked nounwind. This may be questionable,
4040 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
4041 llvm::CallSite CS(&I);
4042 if (CS.doesNotThrow()) continue;
4043
John McCall2dd7d442010-08-04 05:59:32 +00004044 // Insert a read hazard before the call. This will ensure that
4045 // any writes to the locals are performed before making the
4046 // call. If the call throws, then this is sufficient to
4047 // guarantee correctness as long as it doesn't also write to any
4048 // locals.
John McCall42227ed2010-07-31 23:20:56 +00004049 Builder.SetInsertPoint(&BB, BI);
4050 emitReadHazard(Builder);
4051 }
4052 }
4053}
4054
4055static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
4056 if (V) S.insert(V);
4057}
4058
John McCall7f416cc2015-09-08 08:05:57 +00004059static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) {
4060 if (V.isValid()) S.insert(V.getPointer());
4061}
4062
John McCall42227ed2010-07-31 23:20:56 +00004063void FragileHazards::collectLocals() {
4064 // Compute a set of allocas to ignore.
4065 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
4066 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
4067 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00004068
4069 // Collect all the allocas currently in the function. This is
4070 // probably way too aggressive.
4071 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
4072 for (llvm::BasicBlock::iterator
4073 I = Entry.begin(), E = Entry.end(); I != E; ++I)
4074 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
4075 Locals.push_back(&*I);
4076}
4077
4078llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004079 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00004080 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
4081 tys[i] = Locals[i]->getType();
4082 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00004083}
4084
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004085/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004086
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004087 Objective-C setjmp-longjmp (sjlj) Exception Handling
4088 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004089
John McCallbd309292010-07-06 01:34:17 +00004090 A catch buffer is a setjmp buffer plus:
4091 - a pointer to the exception that was caught
4092 - a pointer to the previous exception data buffer
4093 - two pointers of reserved storage
4094 Therefore catch buffers form a stack, with a pointer to the top
4095 of the stack kept in thread-local storage.
4096
4097 objc_exception_try_enter pushes a catch buffer onto the EH stack.
4098 objc_exception_try_exit pops the given catch buffer, which is
4099 required to be the top of the EH stack.
4100 objc_exception_throw pops the top of the EH stack, writes the
4101 thrown exception into the appropriate field, and longjmps
4102 to the setjmp buffer. It crashes the process (with a printf
4103 and an abort()) if there are no catch buffers on the stack.
4104 objc_exception_extract just reads the exception pointer out of the
4105 catch buffer.
4106
4107 There's no reason an implementation couldn't use a light-weight
4108 setjmp here --- something like __builtin_setjmp, but API-compatible
4109 with the heavyweight setjmp. This will be more important if we ever
4110 want to implement correct ObjC/C++ exception interactions for the
4111 fragile ABI.
4112
4113 Note that for this use of setjmp/longjmp to be correct, we may need
4114 to mark some local variables volatile: if a non-volatile local
4115 variable is modified between the setjmp and the longjmp, it has
4116 indeterminate value. For the purposes of LLVM IR, it may be
4117 sufficient to make loads and stores within the @try (to variables
4118 declared outside the @try) volatile. This is necessary for
4119 optimized correctness, but is not currently being done; this is
4120 being tracked as rdar://problem/8160285
4121
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004122 The basic framework for a @try-catch-finally is as follows:
4123 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004124 objc_exception_data d;
4125 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00004126 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004127
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004128 objc_exception_try_enter(&d);
4129 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004130 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004131 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004132 // exception path
4133 id _caught = objc_exception_extract(&d);
4134
4135 // enter new try scope for handlers
4136 if (!setjmp(d.jmp_buf)) {
4137 ... match exception and execute catch blocks ...
4138
4139 // fell off end, rethrow.
4140 _rethrow = _caught;
4141 ... jump-through-finally to finally_rethrow ...
4142 } else {
4143 // exception in catch block
4144 _rethrow = objc_exception_extract(&d);
4145 _call_try_exit = false;
4146 ... jump-through-finally to finally_rethrow ...
4147 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004148 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004149 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004150
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004151 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00004152 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004153 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00004154
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004155 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004156 ... dispatch to finally destination ...
4157
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004158 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004159 objc_exception_throw(_rethrow);
4160
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004161 finally_end:
4162 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004163
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004164 This framework differs slightly from the one gcc uses, in that gcc
4165 uses _rethrow to determine if objc_exception_try_exit should be called
4166 and if the object should be rethrown. This breaks in the face of
4167 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004168
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004169 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004170
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004171 - If there are no catch blocks, then we avoid emitting the second
4172 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004173
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004174 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
4175 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004176
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004177 - FIXME: If there is no @finally block we can do a few more
4178 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004179
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004180 Rethrows and Jumps-Through-Finally
4181 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004182
John McCallbd309292010-07-06 01:34:17 +00004183 '@throw;' is supported by pushing the currently-caught exception
4184 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004185
John McCallbd309292010-07-06 01:34:17 +00004186 Branches through the @finally block are handled with an ordinary
4187 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
4188 exceptions are not compatible with C++ exceptions, and this is
4189 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004190
John McCallbd309292010-07-06 01:34:17 +00004191 @synchronized(expr) { stmt; } is emitted as if it were:
4192 id synch_value = expr;
4193 objc_sync_enter(synch_value);
4194 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004195*/
4196
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00004197void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
4198 const Stmt &S) {
4199 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00004200
4201 // A destination for the fall-through edges of the catch handlers to
4202 // jump to.
4203 CodeGenFunction::JumpDest FinallyEnd =
4204 CGF.getJumpDestInCurrentScope("finally.end");
4205
4206 // A destination for the rethrow edge of the catch handlers to jump
4207 // to.
4208 CodeGenFunction::JumpDest FinallyRethrow =
4209 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004210
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004211 // For @synchronized, call objc_sync_enter(sync.expr). The
4212 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00004213 // @synchronized. We can't avoid a temp here because we need the
4214 // value to be preserved. If the backend ever does liveness
4215 // correctly after setjmp, this will be unnecessary.
John McCall7f416cc2015-09-08 08:05:57 +00004216 Address SyncArgSlot = Address::invalid();
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004217 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00004218 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004219 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4220 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004221 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);
John McCall2dd7d442010-08-04 05:59:32 +00004222
John McCall7f416cc2015-09-08 08:05:57 +00004223 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(),
4224 CGF.getPointerAlign(), "sync.arg");
John McCall2dd7d442010-08-04 05:59:32 +00004225 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004226 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004227
John McCall2dd7d442010-08-04 05:59:32 +00004228 // Allocate memory for the setjmp buffer. This needs to be kept
4229 // live throughout the try and catch blocks.
John McCall7f416cc2015-09-08 08:05:57 +00004230 Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
4231 CGF.getPointerAlign(),
4232 "exceptiondata.ptr");
John McCall2dd7d442010-08-04 05:59:32 +00004233
John McCall42227ed2010-07-31 23:20:56 +00004234 // Create the fragile hazards. Note that this will not capture any
4235 // of the allocas required for exception processing, but will
4236 // capture the current basic block (which extends all the way to the
4237 // setjmp call) as "before the @try".
4238 FragileHazards Hazards(CGF);
4239
John McCallbd309292010-07-06 01:34:17 +00004240 // Create a flag indicating whether the cleanup needs to call
4241 // objc_exception_try_exit. This is true except when
4242 // - no catches match and we're branching through the cleanup
4243 // just to rethrow the exception, or
4244 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00004245 // The setjmp-safety rule here is that we should always store to this
4246 // variable in a place that dominates the branch through the cleanup
4247 // without passing through any setjmps.
John McCall7f416cc2015-09-08 08:05:57 +00004248 Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
4249 CharUnits::One(),
4250 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004251
John McCall9916e3f2010-10-04 23:42:51 +00004252 // A slot containing the exception to rethrow. Only needed when we
4253 // have both a @catch and a @finally.
John McCall7f416cc2015-09-08 08:05:57 +00004254 Address PropagatingExnVar = Address::invalid();
John McCall9916e3f2010-10-04 23:42:51 +00004255
John McCallbd309292010-07-06 01:34:17 +00004256 // Push a normal cleanup to leave the try scope.
John McCall638d4f52013-04-03 00:56:07 +00004257 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00004258 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00004259 CallTryExitVar,
4260 ExceptionData,
4261 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00004262
4263 // Enter a try block:
4264 // - Call objc_exception_try_enter to push ExceptionData on top of
4265 // the EH stack.
Nico Weber6307cf02015-02-26 20:43:00 +00004266 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004267 ExceptionData.getPointer());
John McCallbd309292010-07-06 01:34:17 +00004268
4269 // - Call setjmp on the exception data buffer.
4270 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
4271 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
David Blaikie6b2a8302015-04-03 17:47:16 +00004272 llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
John McCall7f416cc2015-09-08 08:05:57 +00004273 ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes,
4274 "setjmp_buffer");
Nico Weber6307cf02015-02-26 20:43:00 +00004275 llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
4276 ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004277 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00004278
4279 // If setjmp returned 0, enter the protected block; otherwise,
4280 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00004281 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
4282 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00004283 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00004284 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4285 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004286
John McCallbd309292010-07-06 01:34:17 +00004287 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004288 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00004289 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004290 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00004291 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00004292
4293 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004294
John McCallbd309292010-07-06 01:34:17 +00004295 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00004296 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004297
John McCall42227ed2010-07-31 23:20:56 +00004298 // Don't optimize loads of the in-scope locals across this point.
4299 Hazards.emitWriteHazard();
4300
John McCallbd309292010-07-06 01:34:17 +00004301 // For a @synchronized (or a @try with no catches), just branch
4302 // through the cleanup to the rethrow block.
4303 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4304 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00004305 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004306 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00004307
4308 // Otherwise, we have to match against the caught exceptions.
4309 } else {
John McCall2dd7d442010-08-04 05:59:32 +00004310 // Retrieve the exception object. We may emit multiple blocks but
4311 // nothing can cross this so the value is already in SSA form.
4312 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004313 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004314 ExceptionData.getPointer(), "caught");
John McCall2dd7d442010-08-04 05:59:32 +00004315
John McCallbd309292010-07-06 01:34:17 +00004316 // Push the exception to rethrow onto the EH value stack for the
4317 // benefit of any @throws in the handlers.
4318 CGF.ObjCEHValueStack.push_back(Caught);
4319
Douglas Gregor96c79492010-04-23 22:50:49 +00004320 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004321
Craig Topper8a13c412014-05-21 05:09:00 +00004322 bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr);
John McCallbd309292010-07-06 01:34:17 +00004323
Craig Topper8a13c412014-05-21 05:09:00 +00004324 llvm::BasicBlock *CatchBlock = nullptr;
4325 llvm::BasicBlock *CatchHandler = nullptr;
John McCall2dd7d442010-08-04 05:59:32 +00004326 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00004327 // Save the currently-propagating exception before
4328 // objc_exception_try_enter clears the exception slot.
4329 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
John McCall7f416cc2015-09-08 08:05:57 +00004330 CGF.getPointerAlign(),
John McCall9916e3f2010-10-04 23:42:51 +00004331 "propagating_exception");
4332 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
4333
John McCall2dd7d442010-08-04 05:59:32 +00004334 // Enter a new exception try block (in case a @catch block
4335 // throws an exception).
John McCall882987f2013-02-28 19:01:20 +00004336 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004337 ExceptionData.getPointer());
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004338
John McCall2dd7d442010-08-04 05:59:32 +00004339 llvm::CallInst *SetJmpResult =
John McCall882987f2013-02-28 19:01:20 +00004340 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(),
4341 SetJmpBuffer, "setjmp.result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004342 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004343
John McCall2dd7d442010-08-04 05:59:32 +00004344 llvm::Value *Threw =
4345 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4346
4347 CatchBlock = CGF.createBasicBlock("catch");
4348 CatchHandler = CGF.createBasicBlock("catch_for_catch");
4349 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4350
4351 CGF.EmitBlock(CatchBlock);
4352 }
4353
4354 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004355
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004356 // Handle catch list. As a special case we check if everything is
4357 // matched and avoid generating code for falling off the end if
4358 // so.
4359 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00004360 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
4361 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004362
Douglas Gregor46a572b2010-04-26 16:46:50 +00004363 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Craig Topper8a13c412014-05-21 05:09:00 +00004364 const ObjCObjectPointerType *OPT = nullptr;
Daniel Dunbar523208f2008-09-27 07:36:24 +00004365
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004366 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004367 if (!CatchParam) {
4368 AllMatched = true;
4369 } else {
John McCall9dd450b2009-09-21 23:43:11 +00004370 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004371
John McCallbd309292010-07-06 01:34:17 +00004372 // catch(id e) always matches under this ABI, since only
4373 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00004374 // FIXME: For the time being we also match id<X>; this should
4375 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00004376 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004377 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004378 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004379
John McCallbd309292010-07-06 01:34:17 +00004380 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004381 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00004382 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4383
Anders Carlsson9396a892008-09-11 09:15:33 +00004384 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00004385 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004386 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00004387
4388 // These types work out because ConvertType(id) == i8*.
John McCall17f02752015-10-30 00:56:02 +00004389 EmitInitOfCatchParam(CGF, Caught, CatchParam);
Anders Carlsson9396a892008-09-11 09:15:33 +00004390 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004391
Anders Carlsson9396a892008-09-11 09:15:33 +00004392 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004393
4394 // The scope of the catch variable ends right here.
4395 CatchVarCleanups.ForceCleanup();
4396
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004397 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004398 break;
4399 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004400
Steve Naroff7cae42b2009-07-10 23:34:53 +00004401 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00004402 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00004403
4404 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00004405 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
4406 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004407
4408 // Check if the @catch block matches the exception object.
John McCall882987f2013-02-28 19:01:20 +00004409 llvm::Value *Class = EmitClassRef(CGF, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004410
John McCall882987f2013-02-28 19:01:20 +00004411 llvm::Value *matchArgs[] = { Class, Caught };
John McCallbd309292010-07-06 01:34:17 +00004412 llvm::CallInst *Match =
John McCall882987f2013-02-28 19:01:20 +00004413 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(),
4414 matchArgs, "match");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004415
John McCallbd309292010-07-06 01:34:17 +00004416 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
4417 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004418
4419 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00004420 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004421
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004422 // Emit the @catch block.
4423 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00004424
4425 // Collect any cleanups for the catch variable. The scope lasts until
4426 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00004427 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00004428
John McCall1c9c3fd2010-10-15 04:57:14 +00004429 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004430 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004431
John McCallbd309292010-07-06 01:34:17 +00004432 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004433 llvm::Value *Tmp =
4434 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004435 CGF.ConvertType(CatchParam->getType()));
John McCall17f02752015-10-30 00:56:02 +00004436 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004437
Anders Carlsson9396a892008-09-11 09:15:33 +00004438 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004439
4440 // We're done with the catch variable.
4441 CatchVarCleanups.ForceCleanup();
4442
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004443 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004444
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004445 CGF.EmitBlock(NextCatchBlock);
4446 }
4447
John McCallbd309292010-07-06 01:34:17 +00004448 CGF.ObjCEHValueStack.pop_back();
4449
John McCall2dd7d442010-08-04 05:59:32 +00004450 // If nothing wanted anything to do with the caught exception,
4451 // kill the extract call.
4452 if (Caught->use_empty())
4453 Caught->eraseFromParent();
4454
4455 if (!AllMatched)
4456 CGF.EmitBranchThroughCleanup(FinallyRethrow);
4457
4458 if (HasFinally) {
4459 // Emit the exception handler for the @catch blocks.
4460 CGF.EmitBlock(CatchHandler);
4461
4462 // In theory we might now need a write hazard, but actually it's
4463 // unnecessary because there's no local-accessing code between
4464 // the try's write hazard and here.
4465 //Hazards.emitWriteHazard();
4466
John McCall9916e3f2010-10-04 23:42:51 +00004467 // Extract the new exception and save it to the
4468 // propagating-exception slot.
John McCall7f416cc2015-09-08 08:05:57 +00004469 assert(PropagatingExnVar.isValid());
John McCall9916e3f2010-10-04 23:42:51 +00004470 llvm::CallInst *NewCaught =
John McCall882987f2013-02-28 19:01:20 +00004471 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004472 ExceptionData.getPointer(), "caught");
John McCall9916e3f2010-10-04 23:42:51 +00004473 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4474
John McCall2dd7d442010-08-04 05:59:32 +00004475 // Don't pop the catch handler; the throw already did.
4476 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004477 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004478 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004479 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004480
John McCall42227ed2010-07-31 23:20:56 +00004481 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00004482 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004483
John McCallbd309292010-07-06 01:34:17 +00004484 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00004485 CGF.Builder.restoreIP(TryFallthroughIP);
4486 if (CGF.HaveInsertPoint())
4487 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00004488 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00004489 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004490
John McCallbd309292010-07-06 01:34:17 +00004491 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00004492 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00004493 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00004494 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00004495 // If we have a propagating-exception variable, check it.
4496 llvm::Value *PropagatingExn;
John McCall7f416cc2015-09-08 08:05:57 +00004497 if (PropagatingExnVar.isValid()) {
John McCall9916e3f2010-10-04 23:42:51 +00004498 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00004499
John McCall9916e3f2010-10-04 23:42:51 +00004500 // Otherwise, just look in the buffer for the exception to throw.
4501 } else {
4502 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004503 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004504 ExceptionData.getPointer());
John McCall9916e3f2010-10-04 23:42:51 +00004505 PropagatingExn = Caught;
4506 }
4507
John McCall882987f2013-02-28 19:01:20 +00004508 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(),
4509 PropagatingExn);
John McCallbd309292010-07-06 01:34:17 +00004510 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00004511 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004512
John McCall42227ed2010-07-31 23:20:56 +00004513 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004514}
4515
4516void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004517 const ObjCAtThrowStmt &S,
4518 bool ClearInsertionPoint) {
Anders Carlssone005aa12008-09-09 16:16:55 +00004519 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004520
Anders Carlssone005aa12008-09-09 16:16:55 +00004521 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00004522 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004523 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004524 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00004525 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004526 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004527 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00004528 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00004529 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004530
John McCall882987f2013-02-28 19:01:20 +00004531 CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
John McCallbd309292010-07-06 01:34:17 +00004532 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004533 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004534
4535 // Clear the insertion point to indicate we are in unreachable code.
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004536 if (ClearInsertionPoint)
4537 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004538}
4539
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004540/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004541/// object: objc_read_weak (id *src)
4542///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004543llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004544 Address AddrWeakObj) {
4545 llvm::Type* DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004546 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4547 ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004548 llvm::Value *read_weak =
4549 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004550 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00004551 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004552 return read_weak;
4553}
4554
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004555/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4556/// objc_assign_weak (id src, id *dst)
4557///
4558void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004559 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004560 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004561 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004562 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004563 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004564 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4565 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004566 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4567 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004568 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4569 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004570 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00004571 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4572 args, "weakassign");
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004573}
4574
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004575/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4576/// objc_assign_global (id src, id *dst)
4577///
4578void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004579 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00004580 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004581 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004582 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004583 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004584 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004585 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4586 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004587 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4588 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004589 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4590 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004591 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00004592 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00004593 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4594 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00004595 else
John McCall882987f2013-02-28 19:01:20 +00004596 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4597 args, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004598}
4599
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004600/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004601/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004602///
4603void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004604 llvm::Value *src, Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004605 llvm::Value *ivarOffset) {
4606 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00004607 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004608 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004609 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004610 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004611 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4612 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004613 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4614 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004615 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4616 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004617 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00004618 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004619}
4620
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004621/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
4622/// objc_assign_strongCast (id src, id *dst)
4623///
4624void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004625 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004626 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004627 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004628 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004629 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004630 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4631 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004632 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4633 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004634 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4635 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004636 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00004637 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004638 args, "strongassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004639}
4640
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004641void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004642 Address DestPtr,
4643 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00004644 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004645 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
4646 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004647 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size };
John McCall882987f2013-02-28 19:01:20 +00004648 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004649}
4650
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004651/// EmitObjCValueForIvar - Code Gen for ivar reference.
4652///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004653LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4654 QualType ObjectTy,
4655 llvm::Value *BaseValue,
4656 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004657 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00004658 const ObjCInterfaceDecl *ID =
4659 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00004660 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4661 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004662}
4663
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004664llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00004665 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004666 const ObjCIvarDecl *Ivar) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004667 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4668 return llvm::ConstantInt::get(
4669 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
4670 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004671}
4672
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004673/* *** Private Interface *** */
4674
4675/// EmitImageInfo - Emit the image info marker used to encode some module
4676/// level information.
4677///
4678/// See: <rdr://4810609&4810587&4810587>
4679/// struct IMAGE_INFO {
4680/// unsigned version;
4681/// unsigned flags;
4682/// };
4683enum ImageInfoFlags {
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004684 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004685 eImageInfo_GarbageCollected = (1 << 1),
4686 eImageInfo_GCOnly = (1 << 2),
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004687 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
Daniel Dunbar75e909f2009-04-20 07:11:47 +00004688
Daniel Dunbar5e639272010-04-25 20:39:01 +00004689 // A flag indicating that the module has no instances of a @synthesize of a
4690 // superclass variable. <rdar://problem/6803242>
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004691 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
Manman Ren96df0b32016-01-29 23:45:01 +00004692 eImageInfo_ImageIsSimulated = (1 << 5),
4693 eImageInfo_ClassProperties = (1 << 6)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004694};
4695
Daniel Dunbar5e639272010-04-25 20:39:01 +00004696void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004697 unsigned version = 0; // Version is unused?
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004698 const char *Section = (ObjCABI == 1) ?
4699 "__OBJC, __image_info,regular" :
4700 "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004701
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004702 // Generate module-level named metadata to convey this information to the
4703 // linker and code-gen.
4704 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004705
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004706 // Add the ObjC ABI version to the module flags.
4707 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
4708 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
4709 version);
4710 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
4711 llvm::MDString::get(VMContext,Section));
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004712
David Blaikiebbafb8a2012-03-11 07:00:24 +00004713 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004714 // Non-GC overrides those files which specify GC.
4715 Mod.addModuleFlag(llvm::Module::Override,
4716 "Objective-C Garbage Collection", (uint32_t)0);
4717 } else {
4718 // Add the ObjC garbage collection value.
4719 Mod.addModuleFlag(llvm::Module::Error,
4720 "Objective-C Garbage Collection",
4721 eImageInfo_GarbageCollected);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004722
David Blaikiebbafb8a2012-03-11 07:00:24 +00004723 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004724 // Add the ObjC GC Only value.
4725 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
4726 eImageInfo_GCOnly);
4727
4728 // Require that GC be specified and set to eImageInfo_GarbageCollected.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +00004729 llvm::Metadata *Ops[2] = {
4730 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
4731 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
4732 llvm::Type::getInt32Ty(VMContext), eImageInfo_GarbageCollected))};
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004733 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
4734 llvm::MDNode::get(VMContext, Ops));
4735 }
4736 }
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004737
4738 // Indicate whether we're compiling this to run on a simulator.
4739 const llvm::Triple &Triple = CGM.getTarget().getTriple();
Tim Northover756447a2015-10-30 16:30:36 +00004740 if ((Triple.isiOS() || Triple.isWatchOS()) &&
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004741 (Triple.getArch() == llvm::Triple::x86 ||
4742 Triple.getArch() == llvm::Triple::x86_64))
4743 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
4744 eImageInfo_ImageIsSimulated);
Manman Ren96df0b32016-01-29 23:45:01 +00004745
4746 // Indicate whether we are generating class properties.
4747 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Class Properties",
4748 eImageInfo_ClassProperties);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004749}
4750
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004751// struct objc_module {
4752// unsigned long version;
4753// unsigned long size;
4754// const char *name;
4755// Symtab symtab;
4756// };
4757
4758// FIXME: Get from somewhere
4759static const int ModuleVersion = 7;
4760
4761void CGObjCMac::EmitModuleInfo() {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004762 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004763
John McCall176f8922016-11-30 02:39:18 +00004764 ConstantInitBuilder builder(CGM);
4765 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
4766 values.addInt(ObjCTypes.LongTy, ModuleVersion);
4767 values.addInt(ObjCTypes.LongTy, Size);
4768 // This used to be the filename, now it is unused. <rdr://4327263>
4769 values.add(GetClassName(StringRef("")));
4770 values.add(EmitModuleSymbols());
4771 CreateMetadataVar("OBJC_MODULES", values,
John McCall7f416cc2015-09-08 08:05:57 +00004772 "__OBJC,__module_info,regular,no_dead_strip",
4773 CGM.getPointerAlign(), true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004774}
4775
4776llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004777 unsigned NumClasses = DefinedClasses.size();
4778 unsigned NumCategories = DefinedCategories.size();
4779
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004780 // Return null if no symbols were defined.
4781 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00004782 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004783
John McCall176f8922016-11-30 02:39:18 +00004784 ConstantInitBuilder builder(CGM);
4785 auto values = builder.beginStruct();
4786 values.addInt(ObjCTypes.LongTy, 0);
4787 values.addNullPointer(ObjCTypes.SelectorPtrTy);
4788 values.addInt(ObjCTypes.ShortTy, NumClasses);
4789 values.addInt(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004790
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004791 // The runtime expects exactly the list of defined classes followed
4792 // by the list of defined categories, in a single array.
John McCall176f8922016-11-30 02:39:18 +00004793 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00004794 for (unsigned i=0; i<NumClasses; i++) {
4795 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
4796 assert(ID);
4797 if (ObjCImplementationDecl *IMP = ID->getImplementation())
4798 // We are implementing a weak imported interface. Give it external linkage
4799 if (ID->isWeakImported() && !IMP->isWeakImported())
4800 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
John McCall176f8922016-11-30 02:39:18 +00004801
4802 array.addBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00004803 }
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004804 for (unsigned i=0; i<NumCategories; i++)
John McCall176f8922016-11-30 02:39:18 +00004805 array.addBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004806
John McCall176f8922016-11-30 02:39:18 +00004807 array.finishAndAddTo(values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004808
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00004809 llvm::GlobalVariable *GV = CreateMetadataVar(
John McCall176f8922016-11-30 02:39:18 +00004810 "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip",
John McCall7f416cc2015-09-08 08:05:57 +00004811 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00004812 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004813}
4814
John McCall882987f2013-02-28 19:01:20 +00004815llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
4816 IdentifierInfo *II) {
John McCall31168b02011-06-15 23:02:42 +00004817 LazySymbols.insert(II);
4818
4819 llvm::GlobalVariable *&Entry = ClassReferences[II];
4820
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004821 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004822 llvm::Constant *Casted =
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00004823 llvm::ConstantExpr::getBitCast(GetClassName(II->getName()),
John McCall31168b02011-06-15 23:02:42 +00004824 ObjCTypes.ClassPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00004825 Entry = CreateMetadataVar(
4826 "OBJC_CLASS_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00004827 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
4828 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004829 }
John McCall31168b02011-06-15 23:02:42 +00004830
John McCall7f416cc2015-09-08 08:05:57 +00004831 return CGF.Builder.CreateAlignedLoad(Entry, CGF.getPointerAlign());
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004832}
4833
John McCall882987f2013-02-28 19:01:20 +00004834llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00004835 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00004836 // If the class has the objc_runtime_visible attribute, we need to
4837 // use the Objective-C runtime to get the class.
4838 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
4839 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
4840
John McCall882987f2013-02-28 19:01:20 +00004841 return EmitClassRefFromId(CGF, ID->getIdentifier());
John McCall31168b02011-06-15 23:02:42 +00004842}
4843
John McCall882987f2013-02-28 19:01:20 +00004844llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00004845 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
John McCall882987f2013-02-28 19:01:20 +00004846 return EmitClassRefFromId(CGF, II);
John McCall31168b02011-06-15 23:02:42 +00004847}
4848
John McCall7f416cc2015-09-08 08:05:57 +00004849llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
4850 return CGF.Builder.CreateLoad(EmitSelectorAddr(CGF, Sel));
4851}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004852
John McCall7f416cc2015-09-08 08:05:57 +00004853Address CGObjCMac::EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel) {
4854 CharUnits Align = CGF.getPointerAlign();
4855
4856 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004857 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004858 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00004859 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004860 ObjCTypes.SelectorPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00004861 Entry = CreateMetadataVar(
4862 "OBJC_SELECTOR_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00004863 "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true);
Michael Gottesman5c205962013-02-05 23:08:45 +00004864 Entry->setExternallyInitialized(true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004865 }
4866
John McCall7f416cc2015-09-08 08:05:57 +00004867 return Address(Entry, Align);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004868}
4869
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00004870llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
4871 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
4872 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004873 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00004874 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004875}
4876
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004877llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
4878 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
4879 I = MethodDefinitions.find(MD);
4880 if (I != MethodDefinitions.end())
4881 return I->second;
4882
Craig Topper8a13c412014-05-21 05:09:00 +00004883 return nullptr;
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004884}
4885
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004886/// GetIvarLayoutName - Returns a unique constant for the given
4887/// ivar layout bitmap.
4888llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004889 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00004890 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004891}
4892
John McCall3fd13f062015-10-21 18:06:47 +00004893void IvarLayoutBuilder::visitRecord(const RecordType *RT,
4894 CharUnits offset) {
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004895 const RecordDecl *RD = RT->getDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004896
John McCall3fd13f062015-10-21 18:06:47 +00004897 // If this is a union, remember that we had one, because it might mess
4898 // up the ordering of layout entries.
4899 if (RD->isUnion())
4900 IsDisordered = true;
4901
4902 const ASTRecordLayout *recLayout = nullptr;
4903 visitAggregate(RD->field_begin(), RD->field_end(), offset,
4904 [&](const FieldDecl *field) -> CharUnits {
4905 if (!recLayout)
4906 recLayout = &CGM.getContext().getASTRecordLayout(RD);
4907 auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
4908 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
4909 });
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004910}
4911
John McCall3fd13f062015-10-21 18:06:47 +00004912template <class Iterator, class GetOffsetFn>
4913void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
4914 CharUnits aggregateOffset,
4915 const GetOffsetFn &getOffset) {
4916 for (; begin != end; ++begin) {
4917 auto field = *begin;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004918
John McCall3fd13f062015-10-21 18:06:47 +00004919 // Skip over bitfields.
4920 if (field->isBitField()) {
4921 continue;
4922 }
4923
4924 // Compute the offset of the field within the aggregate.
4925 CharUnits fieldOffset = aggregateOffset + getOffset(field);
4926
4927 visitField(field, fieldOffset);
4928 }
4929}
4930
4931/// Collect layout information for the given fields into IvarsInfo.
4932void IvarLayoutBuilder::visitField(const FieldDecl *field,
4933 CharUnits fieldOffset) {
4934 QualType fieldType = field->getType();
4935
4936 // Drill down into arrays.
4937 uint64_t numElts = 1;
4938 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
4939 numElts *= arrayType->getSize().getZExtValue();
4940 fieldType = arrayType->getElementType();
4941 }
4942
4943 assert(!fieldType->isArrayType() && "ivar of non-constant array type?");
4944
4945 // If we ended up with a zero-sized array, we've done what we can do within
4946 // the limits of this layout encoding.
4947 if (numElts == 0) return;
4948
4949 // Recurse if the base element type is a record type.
4950 if (auto recType = fieldType->getAs<RecordType>()) {
4951 size_t oldEnd = IvarsInfo.size();
4952
4953 visitRecord(recType, fieldOffset);
4954
4955 // If we have an array, replicate the first entry's layout information.
4956 auto numEltEntries = IvarsInfo.size() - oldEnd;
4957 if (numElts != 1 && numEltEntries != 0) {
4958 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
4959 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
4960 // Copy the last numEltEntries onto the end of the array, adjusting
4961 // each for the element size.
4962 for (size_t i = 0; i != numEltEntries; ++i) {
4963 auto firstEntry = IvarsInfo[oldEnd + i];
4964 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
4965 firstEntry.SizeInWords));
4966 }
4967 }
4968 }
4969
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004970 return;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004971 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004972
John McCall3fd13f062015-10-21 18:06:47 +00004973 // Classify the element type.
4974 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004975
John McCall3fd13f062015-10-21 18:06:47 +00004976 // If it matches what we're looking for, add an entry.
4977 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
4978 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
4979 assert(CGM.getContext().getTypeSizeInChars(fieldType)
4980 == CGM.getPointerSize());
4981 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
4982 }
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004983}
4984
John McCall3fd13f062015-10-21 18:06:47 +00004985/// buildBitmap - This routine does the horsework of taking the offsets of
4986/// strong/weak references and creating a bitmap. The bitmap is also
4987/// returned in the given buffer, suitable for being passed to \c dump().
4988llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
4989 llvm::SmallVectorImpl<unsigned char> &buffer) {
4990 // The bitmap is a series of skip/scan instructions, aligned to word
4991 // boundaries. The skip is performed first.
4992 const unsigned char MaxNibble = 0xF;
4993 const unsigned char SkipMask = 0xF0, SkipShift = 4;
4994 const unsigned char ScanMask = 0x0F, ScanShift = 0;
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00004995
John McCall3fd13f062015-10-21 18:06:47 +00004996 assert(!IvarsInfo.empty() && "generating bitmap for no data");
4997
4998 // Sort the ivar info on byte position in case we encounterred a
4999 // union nested in the ivar list.
5000 if (IsDisordered) {
5001 // This isn't a stable sort, but our algorithm should handle it fine.
5002 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5003 } else {
Craig Toppera3467052016-01-03 19:43:20 +00005004 assert(std::is_sorted(IvarsInfo.begin(), IvarsInfo.end()));
John McCall3fd13f062015-10-21 18:06:47 +00005005 }
5006 assert(IvarsInfo.back().Offset < InstanceEnd);
5007
5008 assert(buffer.empty());
5009
5010 // Skip the next N words.
5011 auto skip = [&](unsigned numWords) {
5012 assert(numWords > 0);
5013
5014 // Try to merge into the previous byte. Since scans happen second, we
5015 // can't do this if it includes a scan.
5016 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5017 unsigned lastSkip = buffer.back() >> SkipShift;
5018 if (lastSkip < MaxNibble) {
5019 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5020 numWords -= claimed;
5021 lastSkip += claimed;
5022 buffer.back() = (lastSkip << SkipShift);
5023 }
5024 }
5025
5026 while (numWords >= MaxNibble) {
5027 buffer.push_back(MaxNibble << SkipShift);
5028 numWords -= MaxNibble;
5029 }
5030 if (numWords) {
5031 buffer.push_back(numWords << SkipShift);
5032 }
5033 };
5034
5035 // Scan the next N words.
5036 auto scan = [&](unsigned numWords) {
5037 assert(numWords > 0);
5038
5039 // Try to merge into the previous byte. Since scans happen second, we can
5040 // do this even if it includes a skip.
5041 if (!buffer.empty()) {
5042 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5043 if (lastScan < MaxNibble) {
5044 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5045 numWords -= claimed;
5046 lastScan += claimed;
5047 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5048 }
5049 }
5050
5051 while (numWords >= MaxNibble) {
5052 buffer.push_back(MaxNibble << ScanShift);
5053 numWords -= MaxNibble;
5054 }
5055 if (numWords) {
5056 buffer.push_back(numWords << ScanShift);
5057 }
5058 };
5059
5060 // One past the end of the last scan.
5061 unsigned endOfLastScanInWords = 0;
5062 const CharUnits WordSize = CGM.getPointerSize();
5063
5064 // Consider all the scan requests.
5065 for (auto &request : IvarsInfo) {
5066 CharUnits beginOfScan = request.Offset - InstanceBegin;
5067
5068 // Ignore scan requests that don't start at an even multiple of the
5069 // word size. We can't encode them.
5070 if ((beginOfScan % WordSize) != 0) continue;
5071
5072 // Ignore scan requests that start before the instance start.
5073 // This assumes that scans never span that boundary. The boundary
5074 // isn't the true start of the ivars, because in the fragile-ARC case
5075 // it's rounded up to word alignment, but the test above should leave
5076 // us ignoring that possibility.
5077 if (beginOfScan.isNegative()) {
5078 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5079 continue;
5080 }
5081
5082 unsigned beginOfScanInWords = beginOfScan / WordSize;
5083 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5084
5085 // If the scan starts some number of words after the last one ended,
5086 // skip forward.
5087 if (beginOfScanInWords > endOfLastScanInWords) {
5088 skip(beginOfScanInWords - endOfLastScanInWords);
5089
5090 // Otherwise, start scanning where the last left off.
5091 } else {
5092 beginOfScanInWords = endOfLastScanInWords;
5093
5094 // If that leaves us with nothing to scan, ignore this request.
5095 if (beginOfScanInWords >= endOfScanInWords) continue;
5096 }
5097
5098 // Scan to the end of the request.
5099 assert(beginOfScanInWords < endOfScanInWords);
5100 scan(endOfScanInWords - beginOfScanInWords);
5101 endOfLastScanInWords = endOfScanInWords;
5102 }
5103
John McCallf5ea0722015-10-29 23:36:14 +00005104 if (buffer.empty())
5105 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5106
John McCall3fd13f062015-10-21 18:06:47 +00005107 // For GC layouts, emit a skip to the end of the allocation so that we
5108 // have precise information about the entire thing. This isn't useful
5109 // or necessary for the ARC-style layout strings.
5110 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5111 unsigned lastOffsetInWords =
5112 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5113 if (lastOffsetInWords > endOfLastScanInWords) {
5114 skip(lastOffsetInWords - endOfLastScanInWords);
5115 }
5116 }
5117
5118 // Null terminate the string.
5119 buffer.push_back(0);
5120
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005121 auto *Entry = CGObjC.CreateCStringLiteral(
5122 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
John McCall3fd13f062015-10-21 18:06:47 +00005123 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005124}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005125
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005126/// BuildIvarLayout - Builds ivar layout bitmap for the class
5127/// implementation for the __strong or __weak case.
5128/// The layout map displays which words in ivar list must be skipped
5129/// and which must be scanned by GC (see below). String is built of bytes.
5130/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
5131/// of words to skip and right nibble is count of words to scan. So, each
5132/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
5133/// represented by a 0x00 byte which also ends the string.
5134/// 1. when ForStrongLayout is true, following ivars are scanned:
5135/// - id, Class
5136/// - object *
5137/// - __strong anything
5138///
5139/// 2. When ForStrongLayout is false, following ivars are scanned:
5140/// - __weak anything
5141///
John McCall3fd13f062015-10-21 18:06:47 +00005142llvm::Constant *
5143CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5144 CharUnits beginOffset, CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +00005145 bool ForStrongLayout, bool HasMRCWeakIvars) {
5146 // If this is MRC, and we're either building a strong layout or there
5147 // are no weak ivars, bail out early.
Chris Lattnerece04092012-02-07 00:39:47 +00005148 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikiebbafb8a2012-03-11 07:00:24 +00005149 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
John McCall460ce582015-10-22 18:38:17 +00005150 !CGM.getLangOpts().ObjCAutoRefCount &&
5151 (ForStrongLayout || !HasMRCWeakIvars))
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005152 return llvm::Constant::getNullValue(PtrTy);
5153
Jordy Rosea91768e2011-07-22 02:08:32 +00005154 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
John McCall3fd13f062015-10-21 18:06:47 +00005155 SmallVector<const ObjCIvarDecl*, 32> ivars;
5156
5157 // GC layout strings include the complete object layout, possibly
5158 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5159 // up.
5160 //
5161 // ARC layout strings only include the class's ivars. In non-fragile
John McCallf5ea0722015-10-29 23:36:14 +00005162 // runtimes, that means starting at InstanceStart, rounded up to word
5163 // alignment. In fragile runtimes, there's no InstanceStart, so it means
John McCalld80218f2015-11-19 02:27:55 +00005164 // starting at the offset of the first ivar, rounded up to word alignment.
John McCall460ce582015-10-22 18:38:17 +00005165 //
5166 // MRC weak layout strings follow the ARC style.
John McCall3fd13f062015-10-21 18:06:47 +00005167 CharUnits baseOffset;
John McCall460ce582015-10-22 18:38:17 +00005168 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Jordy Rosea91768e2011-07-22 02:08:32 +00005169 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005170 IVD; IVD = IVD->getNextIvar())
John McCall3fd13f062015-10-21 18:06:47 +00005171 ivars.push_back(IVD);
5172
5173 if (isNonFragileABI()) {
5174 baseOffset = beginOffset; // InstanceStart
John McCalld80218f2015-11-19 02:27:55 +00005175 } else if (!ivars.empty()) {
5176 baseOffset =
5177 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
John McCall3fd13f062015-10-21 18:06:47 +00005178 } else {
5179 baseOffset = CharUnits::Zero();
5180 }
John McCallf5ea0722015-10-29 23:36:14 +00005181
Rui Ueyama83aa9792016-01-14 21:00:27 +00005182 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005183 }
5184 else {
John McCall3fd13f062015-10-21 18:06:47 +00005185 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005186
John McCall3fd13f062015-10-21 18:06:47 +00005187 baseOffset = CharUnits::Zero();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005188 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005189
John McCall3fd13f062015-10-21 18:06:47 +00005190 if (ivars.empty())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005191 return llvm::Constant::getNullValue(PtrTy);
5192
John McCall3fd13f062015-10-21 18:06:47 +00005193 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005194
John McCall3fd13f062015-10-21 18:06:47 +00005195 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5196 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5197 return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
5198 });
5199
5200 if (!builder.hasBitmapData())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005201 return llvm::Constant::getNullValue(PtrTy);
John McCall3fd13f062015-10-21 18:06:47 +00005202
5203 llvm::SmallVector<unsigned char, 4> buffer;
5204 llvm::Constant *C = builder.buildBitmap(*this, buffer);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005205
John McCallf5ea0722015-10-29 23:36:14 +00005206 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005207 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005208 ForStrongLayout ? "strong" : "weak",
Ben Langmuire013bdc2014-07-11 00:43:47 +00005209 OMD->getClassInterface()->getName().str().c_str());
John McCall3fd13f062015-10-21 18:06:47 +00005210 builder.dump(buffer);
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005211 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005212 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00005213}
5214
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005215llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005216 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
Chris Lattner3def9ae2012-02-06 22:16:34 +00005217 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005218 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005219 Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
Owen Anderson170229f2009-07-14 23:10:40 +00005220 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005221}
5222
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005223// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005224llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005225 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5226}
5227
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005228llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005229 std::string TypeStr;
5230 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5231
5232 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005233 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005234 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005235 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005236}
5237
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005238llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5239 bool Extended) {
John McCall843dfcc2016-11-29 21:57:00 +00005240 std::string TypeStr =
5241 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005242
5243 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbar3241fae2009-04-14 23:14:47 +00005244 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005245 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005246 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005247}
5248
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005249// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005250llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005251 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005252 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005253 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
Owen Anderson170229f2009-07-14 23:10:40 +00005254 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005255}
5256
5257// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00005258// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005259llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005260CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5261 const Decl *Container) {
John McCall843dfcc2016-11-29 21:57:00 +00005262 std::string TypeStr =
5263 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005264 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5265}
5266
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005267void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005268 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005269 SmallVectorImpl<char> &Name) {
Daniel Dunbard2386812009-10-19 01:21:19 +00005270 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00005271 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00005272 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
5273 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005274 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00005275 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer2f569922012-02-07 11:57:45 +00005276 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00005277 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00005278}
5279
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005280void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005281 EmitModuleInfo();
5282
Daniel Dunbarc475d422008-10-29 22:36:39 +00005283 // Emit the dummy bodies for any protocols which were referenced but
5284 // never defined.
John McCall176f8922016-11-30 02:39:18 +00005285 for (auto &entry : Protocols) {
5286 llvm::GlobalVariable *global = entry.second;
5287 if (global->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00005288 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005289
John McCall176f8922016-11-30 02:39:18 +00005290 ConstantInitBuilder builder(CGM);
5291 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5292 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5293 values.add(GetClassName(entry.first->getName()));
5294 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5295 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5296 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5297 values.finishAndSetAsInitializer(global);
5298 CGM.addCompilerUsedGlobal(global);
Daniel Dunbarc475d422008-10-29 22:36:39 +00005299 }
5300
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005301 // Add assembler directives to add lazy undefined symbol references
5302 // for classes which are referenced but not defined. This is
5303 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00005304 //
5305 // FIXME: It would be nice if we had an LLVM construct for this.
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005306 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5307 CGM.getTriple().isOSBinFormatMachO()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005308 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00005309 Asm += CGM.getModule().getModuleInlineAsm();
5310 if (!Asm.empty() && Asm.back() != '\n')
5311 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005312
Daniel Dunbard027a922009-09-07 00:20:42 +00005313 llvm::raw_svector_ostream OS(Asm);
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005314 for (const auto *Sym : DefinedSymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005315 OS << "\t.objc_class_name_" << Sym->getName() << "=0\n"
5316 << "\t.globl .objc_class_name_" << Sym->getName() << "\n";
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005317 for (const auto *Sym : LazySymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005318 OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n";
5319 for (const auto &Category : DefinedCategoryNames)
5320 OS << "\t.objc_category_name_" << Category << "=0\n"
5321 << "\t.globl .objc_category_name_" << Category << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00005322
Daniel Dunbard027a922009-09-07 00:20:42 +00005323 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005324 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005325}
5326
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005327CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00005328 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5329 ObjCEmptyVtableVar(nullptr) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005330 ObjCABI = 2;
5331}
5332
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005333/* *** */
5334
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005335ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Craig Topper8a13c412014-05-21 05:09:00 +00005336 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00005337{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005338 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5339 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005340
John McCall176f8922016-11-30 02:39:18 +00005341 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5342 IntTy = CGM.IntTy;
5343 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
Chris Lattnerece04092012-02-07 00:39:47 +00005344 Int8PtrTy = CGM.Int8PtrTy;
5345 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005346
Tim Northover238b5082014-03-29 13:42:40 +00005347 // arm64 targets use "int" ivar offset variables. All others,
5348 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
Tim Northover40956e62014-07-23 12:32:58 +00005349 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
Tim Northover238b5082014-03-29 13:42:40 +00005350 IvarOffsetVarTy = IntTy;
5351 else
5352 IvarOffsetVarTy = LongTy;
5353
John McCall176f8922016-11-30 02:39:18 +00005354 ObjectPtrTy =
5355 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5356 PtrObjectPtrTy =
5357 llvm::PointerType::getUnqual(ObjectPtrTy);
5358 SelectorPtrTy =
5359 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005360
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005361 // I'm not sure I like this. The implicit coordination is a bit
5362 // gross. We should solve this in a reasonable fashion because this
5363 // is a pretty common task (match some runtime data structure with
5364 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005365
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005366 // FIXME: This is leaked.
5367 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005368
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005369 // struct _objc_super {
5370 // id self;
5371 // Class cls;
5372 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00005373 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005374 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005375 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005376 &Ctx.Idents.get("_objc_super"));
Craig Topper8a13c412014-05-21 05:09:00 +00005377 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5378 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5379 false, ICIS_NoInit));
5380 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5381 nullptr, Ctx.getObjCClassType(), nullptr,
5382 nullptr, false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005383 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005384
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005385 SuperCTy = Ctx.getTagDeclType(RD);
5386 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005387
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005388 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005389 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5390
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005391 // struct _prop_t {
5392 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005393 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005394 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005395 PropertyTy = llvm::StructType::create("struct._prop_t",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005396 Int8PtrTy, Int8PtrTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005397
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005398 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005399 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005400 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005401 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005402 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005403 PropertyListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005404 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005405 llvm::ArrayType::get(PropertyTy, 0), nullptr);
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005406 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005407 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005408
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005409 // struct _objc_method {
5410 // SEL _cmd;
5411 // char *method_type;
5412 // char *_imp;
5413 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005414 MethodTy = llvm::StructType::create("struct._objc_method",
5415 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005416 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005417
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005418 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00005419 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005420 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005421}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005422
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005423ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005424 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005425 // struct _objc_method_description {
5426 // SEL name;
5427 // char *types;
5428 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005429 MethodDescriptionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005430 llvm::StructType::create("struct._objc_method_description",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005431 SelectorPtrTy, Int8PtrTy, nullptr);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005432
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005433 // struct _objc_method_description_list {
5434 // int count;
5435 // struct _objc_method_description[1];
5436 // }
Reid Kleckneree7cf842014-12-01 22:02:27 +00005437 MethodDescriptionListTy = llvm::StructType::create(
5438 "struct._objc_method_description_list", IntTy,
5439 llvm::ArrayType::get(MethodDescriptionTy, 0), nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005440
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005441 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005442 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005443 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005444
Daniel Dunbarb036db82008-08-13 03:21:16 +00005445 // Protocol description structures
5446
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005447 // struct _objc_protocol_extension {
5448 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5449 // struct _objc_method_description_list *optional_instance_methods;
5450 // struct _objc_method_description_list *optional_class_methods;
5451 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005452 // const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00005453 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005454 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005455 ProtocolExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005456 llvm::StructType::create("struct._objc_protocol_extension",
5457 IntTy, MethodDescriptionListPtrTy,
5458 MethodDescriptionListPtrTy, PropertyListPtrTy,
Manman Rence7bff52016-01-29 23:46:55 +00005459 Int8PtrPtrTy, PropertyListPtrTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005460
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005461 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005462 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005463
Daniel Dunbarc475d422008-10-29 22:36:39 +00005464 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00005465
Chris Lattnera5f58b02011-07-09 17:41:47 +00005466 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005467 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00005468
Chris Lattnera5f58b02011-07-09 17:41:47 +00005469 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005470 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005471 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005472 LongTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00005473 llvm::ArrayType::get(ProtocolTy, 0),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005474 nullptr);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005475
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005476 // struct _objc_protocol {
5477 // struct _objc_protocol_extension *isa;
5478 // char *protocol_name;
5479 // struct _objc_protocol **_objc_protocol_list;
5480 // struct _objc_method_description_list *instance_methods;
5481 // struct _objc_method_description_list *class_methods;
5482 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005483 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5484 llvm::PointerType::getUnqual(ProtocolListTy),
5485 MethodDescriptionListPtrTy,
5486 MethodDescriptionListPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005487 nullptr);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005488
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005489 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005490 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005491
Owen Anderson9793f0e2009-07-29 22:16:19 +00005492 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005493
5494 // Class description structures
5495
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005496 // struct _objc_ivar {
5497 // char *ivar_name;
5498 // char *ivar_type;
5499 // int ivar_offset;
5500 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005501 IvarTy = llvm::StructType::create("struct._objc_ivar",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005502 Int8PtrTy, Int8PtrTy, IntTy, nullptr);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005503
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005504 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005505 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005506 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005507 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005508
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005509 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005510 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005511 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005512 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005513
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005514 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005515 ClassExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005516 llvm::StructType::create("struct._objc_class_extension",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005517 IntTy, Int8PtrTy, PropertyListPtrTy, nullptr);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005518 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005519
Chris Lattner5ec04a52011-08-12 17:43:31 +00005520 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005521
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005522 // struct _objc_class {
5523 // Class isa;
5524 // Class super_class;
5525 // char *name;
5526 // long version;
5527 // long info;
5528 // long instance_size;
5529 // struct _objc_ivar_list *ivars;
5530 // struct _objc_method_list *methods;
5531 // struct _objc_cache *cache;
5532 // struct _objc_protocol_list *protocols;
5533 // char *ivar_layout;
5534 // struct _objc_class_ext *ext;
5535 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005536 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
5537 llvm::PointerType::getUnqual(ClassTy),
5538 Int8PtrTy,
5539 LongTy,
5540 LongTy,
5541 LongTy,
5542 IvarListPtrTy,
5543 MethodListPtrTy,
5544 CachePtrTy,
5545 ProtocolListPtrTy,
5546 Int8PtrTy,
5547 ClassExtensionPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005548 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005549
Owen Anderson9793f0e2009-07-29 22:16:19 +00005550 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005551
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005552 // struct _objc_category {
5553 // char *category_name;
5554 // char *class_name;
5555 // struct _objc_method_list *instance_method;
5556 // struct _objc_method_list *class_method;
Manman Renb3736772016-01-25 22:37:47 +00005557 // struct _objc_protocol_list *protocols;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005558 // uint32_t size; // sizeof(struct _objc_category)
5559 // struct _objc_property_list *instance_properties;// category's @property
Manman Ren96df0b32016-01-29 23:45:01 +00005560 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005561 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005562 CategoryTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005563 llvm::StructType::create("struct._objc_category",
5564 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5565 MethodListPtrTy, ProtocolListPtrTy,
Manman Ren96df0b32016-01-29 23:45:01 +00005566 IntTy, PropertyListPtrTy, PropertyListPtrTy,
5567 nullptr);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005568
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005569 // Global metadata structures
5570
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005571 // struct _objc_symtab {
5572 // long sel_ref_cnt;
5573 // SEL *refs;
5574 // short cls_def_cnt;
5575 // short cat_def_cnt;
5576 // char *defs[cls_def_cnt + cat_def_cnt];
5577 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005578 SymtabTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005579 llvm::StructType::create("struct._objc_symtab",
5580 LongTy, SelectorPtrTy, ShortTy, ShortTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005581 llvm::ArrayType::get(Int8PtrTy, 0), nullptr);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005582 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005583
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00005584 // struct _objc_module {
5585 // long version;
5586 // long size; // sizeof(struct _objc_module)
5587 // char *name;
5588 // struct _objc_symtab* symtab;
5589 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005590 ModuleTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005591 llvm::StructType::create("struct._objc_module",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005592 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, nullptr);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00005593
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005594
Mike Stump18bb9282009-05-16 07:57:57 +00005595 // FIXME: This is the size of the setjmp buffer and should be target
5596 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00005597 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005598
Anders Carlsson9ff22482008-09-09 10:10:21 +00005599 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00005600 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005601
5602 ExceptionDataTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005603 llvm::StructType::create("struct._objc_exception_data",
Chris Lattnerece04092012-02-07 00:39:47 +00005604 llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005605 StackPtrTy, nullptr);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005606}
5607
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005608ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005609 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005610 // struct _method_list_t {
5611 // uint32_t entsize; // sizeof(struct _objc_method)
5612 // uint32_t method_count;
5613 // struct _objc_method method_list[method_count];
5614 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005615 MethodListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005616 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005617 llvm::ArrayType::get(MethodTy, 0), nullptr);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005618 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005619 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005620
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005621 // struct _protocol_t {
5622 // id isa; // NULL
5623 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005624 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005625 // const struct method_list_t * const instance_methods;
5626 // const struct method_list_t * const class_methods;
5627 // const struct method_list_t *optionalInstanceMethods;
5628 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005629 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005630 // const uint32_t size; // sizeof(struct _protocol_t)
5631 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005632 // const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00005633 // const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00005634 // const struct _prop_list_t * class_properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005635 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005636
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005637 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005638 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005639 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005640
Chris Lattnera5f58b02011-07-09 17:41:47 +00005641 ProtocolnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005642 llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
5643 llvm::PointerType::getUnqual(ProtocolListnfABITy),
5644 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5645 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005646 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
Manman Rence7bff52016-01-29 23:46:55 +00005647 Int8PtrTy, PropertyListPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005648 nullptr);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005649
5650 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005651 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005652
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005653 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005654 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005655 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005656 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005657 ProtocolListnfABITy->setBody(LongTy,
5658 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005659 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005660
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005661 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005662 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005663
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005664 // struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00005665 // unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005666 // char *name;
5667 // char *type;
5668 // uint32_t alignment;
5669 // uint32_t size;
5670 // }
Tim Northover238b5082014-03-29 13:42:40 +00005671 IvarnfABITy = llvm::StructType::create(
5672 "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005673 Int8PtrTy, Int8PtrTy, IntTy, IntTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005674
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005675 // struct _ivar_list_t {
5676 // uint32 entsize; // sizeof(struct _ivar_t)
5677 // uint32 count;
5678 // struct _iver_t list[count];
5679 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005680 IvarListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005681 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005682 llvm::ArrayType::get(IvarnfABITy, 0), nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005683
Owen Anderson9793f0e2009-07-29 22:16:19 +00005684 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005685
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005686 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005687 // uint32_t const flags;
5688 // uint32_t const instanceStart;
5689 // uint32_t const instanceSize;
5690 // uint32_t const reserved; // only when building for 64bit targets
5691 // const uint8_t * const ivarLayout;
5692 // const char *const name;
5693 // const struct _method_list_t * const baseMethods;
5694 // const struct _objc_protocol_list *const baseProtocols;
5695 // const struct _ivar_list_t *const ivars;
5696 // const uint8_t * const weakIvarLayout;
5697 // const struct _prop_list_t * const properties;
5698 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005699
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005700 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattner5ec04a52011-08-12 17:43:31 +00005701 ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
5702 IntTy, IntTy, IntTy, Int8PtrTy,
5703 Int8PtrTy, MethodListnfABIPtrTy,
5704 ProtocolListnfABIPtrTy,
5705 IvarListnfABIPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005706 Int8PtrTy, PropertyListPtrTy,
5707 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005708
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005709 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00005710 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00005711 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
5712 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005713
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005714 // struct _class_t {
5715 // struct _class_t *isa;
5716 // struct _class_t * const superclass;
5717 // void *cache;
5718 // IMP *vtable;
5719 // struct class_ro_t *ro;
5720 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005721
Chris Lattner5ec04a52011-08-12 17:43:31 +00005722 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005723 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
5724 llvm::PointerType::getUnqual(ClassnfABITy),
5725 CachePtrTy,
5726 llvm::PointerType::getUnqual(ImpnfABITy),
5727 llvm::PointerType::getUnqual(ClassRonfABITy),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005728 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005729
Fariborz Jahanian71394042009-01-23 23:53:38 +00005730 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005731 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005732
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005733 // struct _category_t {
5734 // const char * const name;
5735 // struct _class_t *const cls;
5736 // const struct _method_list_t * const instance_methods;
5737 // const struct _method_list_t * const class_methods;
5738 // const struct _protocol_list_t * const protocols;
5739 // const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00005740 // const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00005741 // const uint32_t size;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00005742 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005743 CategorynfABITy = llvm::StructType::create("struct._category_t",
5744 Int8PtrTy, ClassnfABIPtrTy,
5745 MethodListnfABIPtrTy,
5746 MethodListnfABIPtrTy,
5747 ProtocolListnfABIPtrTy,
5748 PropertyListPtrTy,
Manman Ren96df0b32016-01-29 23:45:01 +00005749 PropertyListPtrTy,
Manman Ren42ff3902016-02-24 17:49:50 +00005750 IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005751 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005752
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005753 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005754 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5755 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005756
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005757 // MessageRefTy - LLVM for:
5758 // struct _message_ref_t {
5759 // IMP messenger;
5760 // SEL name;
5761 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005762
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005763 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00005764 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005765 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005766 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005767 &Ctx.Idents.get("_message_ref_t"));
Craig Topper8a13c412014-05-21 05:09:00 +00005768 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5769 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
Richard Smith2b013182012-06-10 03:12:00 +00005770 ICIS_NoInit));
Craig Topper8a13c412014-05-21 05:09:00 +00005771 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5772 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
5773 false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005774 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005775
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005776 MessageRefCTy = Ctx.getTagDeclType(RD);
5777 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
5778 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005779
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005780 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005781 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005782
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005783 // SuperMessageRefTy - LLVM for:
5784 // struct _super_message_ref_t {
5785 // SUPER_IMP messenger;
5786 // SEL name;
5787 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005788 SuperMessageRefTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005789 llvm::StructType::create("struct._super_message_ref_t",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005790 ImpnfABITy, SelectorPtrTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005791
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005792 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005793 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005794
Daniel Dunbarb1559a42009-03-01 04:46:24 +00005795
5796 // struct objc_typeinfo {
5797 // const void** vtable; // objc_ehtype_vtable + 2
5798 // const char* name; // c++ typeinfo string
5799 // Class cls;
5800 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005801 EHTypeTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005802 llvm::StructType::create("struct._objc_typeinfo",
5803 llvm::PointerType::getUnqual(Int8PtrTy),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005804 Int8PtrTy, ClassnfABIPtrTy, nullptr);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005805 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005806}
5807
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005808llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00005809 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005810
Craig Topper8a13c412014-05-21 05:09:00 +00005811 return nullptr;
Fariborz Jahanian71394042009-01-23 23:53:38 +00005812}
5813
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00005814void CGObjCNonFragileABIMac::AddModuleClassList(
5815 ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
5816 StringRef SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00005817 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005818
Daniel Dunbar19573e72009-05-15 21:48:48 +00005819 if (!NumClasses)
5820 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005821
Chris Lattner3def9ae2012-02-06 22:16:34 +00005822 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005823 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00005824 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00005825 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00005826 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005827 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00005828 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00005829 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005830
Daniel Dunbar19573e72009-05-15 21:48:48 +00005831 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005832 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00005833 llvm::GlobalValue::PrivateLinkage,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005834 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005835 SymbolName);
Micah Villmowdd31ca12012-10-08 16:25:52 +00005836 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00005837 GV->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00005838 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005839}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005840
Fariborz Jahanian71394042009-01-23 23:53:38 +00005841void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
5842 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005843
Daniel Dunbar19573e72009-05-15 21:48:48 +00005844 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005845 // L_OBJC_LABEL_CLASS_$.
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005846
5847 for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) {
5848 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5849 assert(ID);
5850 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5851 // We are implementing a weak imported interface. Give it external linkage
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00005852 if (ID->isWeakImported() && !IMP->isWeakImported()) {
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005853 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00005854 DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5855 }
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005856 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005857
5858 AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$",
Daniel Dunbar19573e72009-05-15 21:48:48 +00005859 "__DATA, __objc_classlist, regular, no_dead_strip");
Rafael Espindola554256c2014-02-26 22:25:45 +00005860
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005861 AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$",
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005862 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005863
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005864 // Build list of all implemented category addresses in array
5865 // L_OBJC_LABEL_CATEGORY_$.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005866 AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$",
Daniel Dunbar19573e72009-05-15 21:48:48 +00005867 "__DATA, __objc_catlist, regular, no_dead_strip");
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005868 AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$",
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005869 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005870
Daniel Dunbar5e639272010-04-25 20:39:01 +00005871 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005872}
5873
John McCall9e8bb002011-05-14 03:10:52 +00005874/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
5875/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005876/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005877/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00005878bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
5879 // At various points we've experimented with using vtable-based
5880 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005881 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005882 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00005883 return false;
John McCall9e8bb002011-05-14 03:10:52 +00005884 case CodeGenOptions::NonLegacy:
5885 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005886 case CodeGenOptions::Mixed:
5887 break;
5888 }
5889
5890 // If so, see whether this selector is in the white-list of things which must
5891 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00005892 if (VTableDispatchMethods.empty()) {
5893 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
5894 VTableDispatchMethods.insert(GetNullarySelector("class"));
5895 VTableDispatchMethods.insert(GetNullarySelector("self"));
5896 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
5897 VTableDispatchMethods.insert(GetNullarySelector("length"));
5898 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005899
John McCall9e8bb002011-05-14 03:10:52 +00005900 // These are vtable-based if GC is disabled.
5901 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005902 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00005903 VTableDispatchMethods.insert(GetNullarySelector("retain"));
5904 VTableDispatchMethods.insert(GetNullarySelector("release"));
5905 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
5906 }
5907
5908 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
5909 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
5910 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
5911 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
5912 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
5913 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
5914 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
5915
5916 // These are vtable-based if GC is enabled.
5917 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005918 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00005919 VTableDispatchMethods.insert(GetNullarySelector("hash"));
5920 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
5921
5922 // "countByEnumeratingWithState:objects:count"
5923 IdentifierInfo *KeyIdents[] = {
5924 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
5925 &CGM.getContext().Idents.get("objects"),
5926 &CGM.getContext().Idents.get("count")
5927 };
5928 VTableDispatchMethods.insert(
5929 CGM.getContext().Selectors.getSelector(3, KeyIdents));
5930 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005931 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005932
John McCall9e8bb002011-05-14 03:10:52 +00005933 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005934}
5935
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005936/// BuildClassRoTInitializer - generate meta-data for:
5937/// struct _class_ro_t {
5938/// uint32_t const flags;
5939/// uint32_t const instanceStart;
5940/// uint32_t const instanceSize;
5941/// uint32_t const reserved; // only when building for 64bit targets
5942/// const uint8_t * const ivarLayout;
5943/// const char *const name;
5944/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005945/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005946/// const struct _ivar_list_t *const ivars;
5947/// const uint8_t * const weakIvarLayout;
5948/// const struct _prop_list_t * const properties;
5949/// }
5950///
5951llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005952 unsigned flags,
5953 unsigned InstanceStart,
5954 unsigned InstanceSize,
5955 const ObjCImplementationDecl *ID) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00005956 std::string ClassName = ID->getObjCRuntimeNameAsString();
John McCall31168b02011-06-15 23:02:42 +00005957
John McCall3fd13f062015-10-21 18:06:47 +00005958 CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
5959 CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
5960
John McCall460ce582015-10-22 18:38:17 +00005961 bool hasMRCWeak = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00005962 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCallef19dbb2012-10-17 04:53:23 +00005963 flags |= NonFragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00005964 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
5965 flags |= NonFragileABI_Class_HasMRCWeakIvars;
John McCall31168b02011-06-15 23:02:42 +00005966
John McCall176f8922016-11-30 02:39:18 +00005967 ConstantInitBuilder builder(CGM);
5968 auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
5969
5970 values.addInt(ObjCTypes.IntTy, flags);
5971 values.addInt(ObjCTypes.IntTy, InstanceStart);
5972 values.addInt(ObjCTypes.IntTy, InstanceSize);
5973 values.add((flags & NonFragileABI_Class_Meta)
5974 ? GetIvarLayoutName(nullptr, ObjCTypes)
5975 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
5976 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
5977
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005978 // const struct _method_list_t * const baseMethods;
John McCall176f8922016-11-30 02:39:18 +00005979 SmallVector<const ObjCMethodDecl*, 16> methods;
John McCallef19dbb2012-10-17 04:53:23 +00005980 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00005981 for (const auto *MD : ID->class_methods())
5982 methods.push_back(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005983 } else {
John McCall176f8922016-11-30 02:39:18 +00005984 for (const auto *MD : ID->instance_methods())
5985 methods.push_back(MD);
Aaron Ballmanf26acce2014-03-13 19:50:17 +00005986
Aaron Ballmand85eff42014-03-14 15:02:45 +00005987 for (const auto *PID : ID->property_impls()) {
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005988 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
5989 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005990
John McCall176f8922016-11-30 02:39:18 +00005991 if (auto MD = PD->getGetterMethodDecl())
5992 if (GetMethodDefinition(MD))
5993 methods.push_back(MD);
5994 if (auto MD = PD->getSetterMethodDecl())
5995 if (GetMethodDefinition(MD))
5996 methods.push_back(MD);
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005997 }
5998 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005999 }
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006000
John McCall176f8922016-11-30 02:39:18 +00006001 values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
6002 (flags & NonFragileABI_Class_Meta)
6003 ? MethodListType::ClassMethods
6004 : MethodListType::InstanceMethods,
6005 methods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006006
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006007 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6008 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
John McCall176f8922016-11-30 02:39:18 +00006009 values.add(EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006010 + OID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006011 OID->all_referenced_protocol_begin(),
6012 OID->all_referenced_protocol_end()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006013
John McCallef19dbb2012-10-17 04:53:23 +00006014 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00006015 values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
6016 values.add(GetIvarLayoutName(nullptr, ObjCTypes));
6017 values.add(EmitPropertyList(
Manman Renad0e7912016-01-29 19:22:54 +00006018 "\01l_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006019 ID, ID->getClassInterface(), ObjCTypes, true));
John McCallef19dbb2012-10-17 04:53:23 +00006020 } else {
John McCall176f8922016-11-30 02:39:18 +00006021 values.add(EmitIvarList(ID));
6022 values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
6023 values.add(EmitPropertyList(
Manman Renad0e7912016-01-29 19:22:54 +00006024 "\01l_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006025 ID, ID->getClassInterface(), ObjCTypes, false));
John McCallef19dbb2012-10-17 04:53:23 +00006026 }
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006027
John McCall176f8922016-11-30 02:39:18 +00006028 llvm::SmallString<64> roLabel;
6029 llvm::raw_svector_ostream(roLabel)
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006030 << ((flags & NonFragileABI_Class_Meta) ? "\01l_OBJC_METACLASS_RO_$_"
6031 : "\01l_OBJC_CLASS_RO_$_")
6032 << ClassName;
6033
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006034 llvm::GlobalVariable *CLASS_RO_GV =
John McCall176f8922016-11-30 02:39:18 +00006035 values.finishAndCreateGlobal(roLabel, CGM.getPointerAlign(),
6036 /*constant*/ false,
6037 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006038 if (CGM.getTriple().isOSBinFormatMachO())
6039 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006040 return CLASS_RO_GV;
6041}
6042
6043/// BuildClassMetaData - This routine defines that to-level meta-data
6044/// for the given ClassName for:
6045/// struct _class_t {
6046/// struct _class_t *isa;
6047/// struct _class_t * const superclass;
6048/// void *cache;
6049/// IMP *vtable;
6050/// struct class_ro_t *ro;
6051/// }
6052///
Rafael Espindola554256c2014-02-26 22:25:45 +00006053llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassMetaData(
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006054 const std::string &ClassName, llvm::Constant *IsAGV, llvm::Constant *SuperClassGV,
Rafael Espindola554256c2014-02-26 22:25:45 +00006055 llvm::Constant *ClassRoGV, bool HiddenVisibility, bool Weak) {
John McCall176f8922016-11-30 02:39:18 +00006056 ConstantInitBuilder builder(CGM);
6057 auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
6058 values.add(IsAGV);
6059 if (SuperClassGV) {
6060 values.add(SuperClassGV);
6061 } else {
6062 values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
6063 }
6064 values.add(ObjCEmptyCacheVar);
6065 values.add(ObjCEmptyVtableVar);
6066 values.add(ClassRoGV);
6067
Rafael Espindola554256c2014-02-26 22:25:45 +00006068 llvm::GlobalVariable *GV = GetClassGlobal(ClassName, Weak);
John McCall176f8922016-11-30 02:39:18 +00006069 values.finishAndSetAsInitializer(GV);
6070
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006071 if (CGM.getTriple().isOSBinFormatMachO())
6072 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006073 GV->setAlignment(
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006074 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006075 if (!CGM.getTriple().isOSBinFormatCOFF())
6076 if (HiddenVisibility)
6077 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006078 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006079}
6080
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006081bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00006082CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Craig Topper8a13c412014-05-21 05:09:00 +00006083 return OD->getClassMethod(GetNullarySelector("load")) != nullptr;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006084}
6085
Daniel Dunbar961202372009-05-03 12:57:56 +00006086void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00006087 uint32_t &InstanceStart,
6088 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006089 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00006090 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006091
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006092 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00006093 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006094
6095 // If there are no fields, the start is the same as the end.
6096 if (!RL.getFieldCount())
6097 InstanceStart = InstanceSize;
6098 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00006099 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00006100}
6101
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006102static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
6103 StringRef Name) {
6104 IdentifierInfo &II = CGM.getContext().Idents.get(Name);
6105 TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
6106 DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
6107
6108 const VarDecl *VD = nullptr;
6109 for (const auto &Result : DC->lookup(&II))
6110 if ((VD = dyn_cast<VarDecl>(Result)))
6111 break;
6112
6113 if (!VD)
6114 return llvm::GlobalValue::DLLImportStorageClass;
6115 if (VD->hasAttr<DLLExportAttr>())
6116 return llvm::GlobalValue::DLLExportStorageClass;
6117 if (VD->hasAttr<DLLImportAttr>())
6118 return llvm::GlobalValue::DLLImportStorageClass;
6119 return llvm::GlobalValue::DefaultStorageClass;
6120}
6121
Fariborz Jahanian71394042009-01-23 23:53:38 +00006122void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00006123 if (!ObjCEmptyCacheVar) {
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006124 ObjCEmptyCacheVar =
6125 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false,
6126 llvm::GlobalValue::ExternalLinkage, nullptr,
6127 "_objc_empty_cache");
6128 if (CGM.getTriple().isOSBinFormatCOFF())
6129 ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache"));
Craig Topper8a13c412014-05-21 05:09:00 +00006130
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006131 // Only OS X with deployment version <10.9 use the empty vtable symbol
Fariborz Jahanian42d49552013-10-24 17:40:28 +00006132 const llvm::Triple &Triple = CGM.getTarget().getTriple();
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006133 if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006134 ObjCEmptyVtableVar =
6135 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false,
6136 llvm::GlobalValue::ExternalLinkage, nullptr,
6137 "_objc_empty_vtable");
John McCall176f8922016-11-30 02:39:18 +00006138 else
6139 ObjCEmptyVtableVar =
6140 llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
Fariborz Jahanian71394042009-01-23 23:53:38 +00006141 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006142
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00006143 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006144 uint32_t InstanceStart =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006145 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006146 uint32_t InstanceSize = InstanceStart;
John McCallef19dbb2012-10-17 04:53:23 +00006147 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006148
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006149 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006150
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006151 StringRef ClassName = ID->getObjCRuntimeNameAsString();
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006152 const auto *CI = ID->getClassInterface();
6153 assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0");
6154
John McCall0d54a172012-10-17 04:53:31 +00006155 // Build the flags for the metaclass.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006156 bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
6157 ? !CI->hasAttr<DLLExportAttr>()
6158 : CI->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006159 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006160 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006161
6162 // FIXME: why is this flag set on the metaclass?
6163 // ObjC metaclasses have no fields and don't really get constructed.
6164 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006165 flags |= NonFragileABI_Class_HasCXXStructors;
John McCall0d54a172012-10-17 04:53:31 +00006166 if (!ID->hasNonZeroConstructors())
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006167 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
John McCall0d54a172012-10-17 04:53:31 +00006168 }
6169
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006170 if (!CI->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006171 // class is root
John McCallef19dbb2012-10-17 04:53:23 +00006172 flags |= NonFragileABI_Class_Root;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006173
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006174 SuperClassGV = GetClassGlobal((getClassSymbolPrefix() + ClassName).str(),
6175 CI->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006176 if (CGM.getTriple().isOSBinFormatCOFF())
6177 if (CI->hasAttr<DLLImportAttr>())
6178 SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006179
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006180 IsAGV = GetClassGlobal((getMetaclassSymbolPrefix() + ClassName).str(),
6181 CI->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006182 if (CGM.getTriple().isOSBinFormatCOFF())
6183 if (CI->hasAttr<DLLImportAttr>())
6184 IsAGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006185 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006186 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00006187 const ObjCInterfaceDecl *Root = ID->getClassInterface();
6188 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
6189 Root = Super;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006190
6191 const auto *Super = CI->getSuperClass();
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006192 StringRef RootClassName = Root->getObjCRuntimeNameAsString();
6193 StringRef SuperClassName = Super->getObjCRuntimeNameAsString();
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006194
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006195 IsAGV = GetClassGlobal((getMetaclassSymbolPrefix() + RootClassName).str(),
6196 Root->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006197 if (CGM.getTriple().isOSBinFormatCOFF())
6198 if (Root->hasAttr<DLLImportAttr>())
6199 IsAGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006200
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00006201 // work on super class metadata symbol.
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006202 SuperClassGV =
6203 GetClassGlobal((getMetaclassSymbolPrefix() + SuperClassName).str(),
6204 Super->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006205 if (CGM.getTriple().isOSBinFormatCOFF())
6206 if (Super->hasAttr<DLLImportAttr>())
6207 SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006208 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006209
6210 llvm::GlobalVariable *CLASS_RO_GV =
6211 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6212
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006213 llvm::GlobalVariable *MetaTClass =
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006214 BuildClassMetaData((getMetaclassSymbolPrefix() + ClassName).str(), IsAGV,
6215 SuperClassGV, CLASS_RO_GV, classIsHidden,
6216 CI->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006217 if (CGM.getTriple().isOSBinFormatCOFF())
6218 if (CI->hasAttr<DLLExportAttr>())
6219 MetaTClass->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Fariborz Jahanian67260552009-11-17 21:37:35 +00006220 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00006221
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006222 // Metadata for the class
John McCallef19dbb2012-10-17 04:53:23 +00006223 flags = 0;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006224 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006225 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006226
6227 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006228 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006229
John McCall0d54a172012-10-17 04:53:31 +00006230 // Set a flag to enable a runtime optimization when a class has
6231 // fields that require destruction but which don't require
6232 // anything except zero-initialization during construction. This
6233 // is most notably true of __strong and __weak types, but you can
6234 // also imagine there being C++ types with non-trivial default
6235 // constructors that merely set all fields to null.
6236 if (!ID->hasNonZeroConstructors())
6237 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6238 }
6239
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006240 if (hasObjCExceptionAttribute(CGM.getContext(), CI))
John McCallef19dbb2012-10-17 04:53:23 +00006241 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006242
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006243 if (!CI->getSuperClass()) {
John McCallef19dbb2012-10-17 04:53:23 +00006244 flags |= NonFragileABI_Class_Root;
Craig Topper8a13c412014-05-21 05:09:00 +00006245 SuperClassGV = nullptr;
Chris Lattnerb433b272009-04-19 06:02:28 +00006246 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006247 // Has a root. Current class is not a root.
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006248 const auto *Super = CI->getSuperClass();
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006249 StringRef SuperClassName = Super->getObjCRuntimeNameAsString();
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006250
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006251 SuperClassGV =
6252 GetClassGlobal((getClassSymbolPrefix() + SuperClassName).str(),
6253 Super->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006254 if (CGM.getTriple().isOSBinFormatCOFF())
6255 if (Super->hasAttr<DLLImportAttr>())
6256 SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006257 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006258
Daniel Dunbar961202372009-05-03 12:57:56 +00006259 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006260 CLASS_RO_GV =
6261 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006262
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006263 llvm::GlobalVariable *ClassMD =
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006264 BuildClassMetaData((getClassSymbolPrefix() + ClassName).str(), MetaTClass,
6265 SuperClassGV, CLASS_RO_GV, classIsHidden,
6266 CI->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006267 if (CGM.getTriple().isOSBinFormatCOFF())
6268 if (CI->hasAttr<DLLExportAttr>())
6269 ClassMD->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006270 DefinedClasses.push_back(ClassMD);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006271 ImplementedClasses.push_back(CI);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006272
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006273 // Determine if this class is also "non-lazy".
6274 if (ImplementationIsNonLazy(ID))
6275 DefinedNonLazyClasses.push_back(ClassMD);
6276
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006277 // Force the definition of the EHType if necessary.
John McCallef19dbb2012-10-17 04:53:23 +00006278 if (flags & NonFragileABI_Class_Exception)
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006279 GetInterfaceEHType(CI, true);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006280 // Make sure method definition entries are all clear for next implementation.
6281 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00006282}
6283
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006284/// GenerateProtocolRef - This routine is called to generate code for
6285/// a protocol reference expression; as in:
6286/// @code
6287/// @protocol(Proto1);
6288/// @endcode
6289/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
6290/// which will hold address of the protocol meta-data.
6291///
John McCall882987f2013-02-28 19:01:20 +00006292llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006293 const ObjCProtocolDecl *PD) {
6294
Fariborz Jahanian464423d2009-04-10 18:47:34 +00006295 // This routine is called for @protocol only. So, we must build definition
6296 // of protocol's meta-data (not a reference to it!)
6297 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006298 llvm::Constant *Init =
6299 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00006300 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006301
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006302 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006303 ProtocolName += PD->getObjCRuntimeNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006304
John McCall7f416cc2015-09-08 08:05:57 +00006305 CharUnits Align = CGF.getPointerAlign();
6306
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006307 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
6308 if (PTGV)
John McCall7f416cc2015-09-08 08:05:57 +00006309 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006310 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006311 CGM.getModule(),
6312 Init->getType(), false,
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006313 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006314 Init,
6315 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006316 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006317 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
John McCall7f416cc2015-09-08 08:05:57 +00006318 PTGV->setAlignment(Align.getQuantity());
Rafael Espindola060062a2014-03-06 22:15:10 +00006319 CGM.addCompilerUsedGlobal(PTGV);
John McCall7f416cc2015-09-08 08:05:57 +00006320 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006321}
6322
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006323/// GenerateCategory - Build metadata for a category implementation.
6324/// struct _category_t {
6325/// const char * const name;
6326/// struct _class_t *const cls;
6327/// const struct _method_list_t * const instance_methods;
6328/// const struct _method_list_t * const class_methods;
6329/// const struct _protocol_list_t * const protocols;
6330/// const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00006331/// const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00006332/// const uint32_t size;
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006333/// }
6334///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006335void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006336 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006337 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006338
6339 llvm::SmallString<64> ExtCatName(Prefix);
6340 ExtCatName += Interface->getObjCRuntimeNameAsString();
6341 ExtCatName += "_$_";
6342 ExtCatName += OCD->getNameAsString();
6343
6344 llvm::SmallString<64> ExtClassName(getClassSymbolPrefix());
6345 ExtClassName += Interface->getObjCRuntimeNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006346
John McCall176f8922016-11-30 02:39:18 +00006347 ConstantInitBuilder builder(CGM);
6348 auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
6349 values.add(GetClassName(OCD->getIdentifier()->getName()));
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006350 // meta-class entry symbol
Rafael Espindola554256c2014-02-26 22:25:45 +00006351 llvm::GlobalVariable *ClassGV =
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006352 GetClassGlobal(ExtClassName.str(), Interface->isWeakImported());
Rafael Espindola554256c2014-02-26 22:25:45 +00006353
John McCall176f8922016-11-30 02:39:18 +00006354 values.add(ClassGV);
6355 std::string listName =
Saleem Abdulrasool209150a2016-10-24 21:25:57 +00006356 (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006357
John McCall176f8922016-11-30 02:39:18 +00006358 SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
6359 SmallVector<const ObjCMethodDecl *, 8> classMethods;
6360 for (const auto *MD : OCD->methods()) {
6361 if (MD->isInstanceMethod()) {
6362 instanceMethods.push_back(MD);
6363 } else {
6364 classMethods.push_back(MD);
6365 }
6366 }
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006367
John McCall176f8922016-11-30 02:39:18 +00006368 values.add(emitMethodList(listName, MethodListType::CategoryInstanceMethods,
6369 instanceMethods));
6370 values.add(emitMethodList(listName, MethodListType::CategoryClassMethods,
6371 classMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006372
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006373 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00006374 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006375 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006376 SmallString<256> ExtName;
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006377 llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006378 << OCD->getName();
John McCall176f8922016-11-30 02:39:18 +00006379 values.add(EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006380 + Interface->getObjCRuntimeNameAsString() + "_$_"
6381 + Category->getName(),
John McCall176f8922016-11-30 02:39:18 +00006382 Category->protocol_begin(),
6383 Category->protocol_end()));
6384 values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
6385 OCD, Category, ObjCTypes, false));
6386 values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
6387 OCD, Category, ObjCTypes, true));
Mike Stump658fe022009-07-30 22:28:39 +00006388 } else {
John McCall176f8922016-11-30 02:39:18 +00006389 values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
6390 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6391 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006392 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006393
Manman Ren42ff3902016-02-24 17:49:50 +00006394 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
John McCall176f8922016-11-30 02:39:18 +00006395 values.addInt(ObjCTypes.IntTy, Size);
Manman Ren42ff3902016-02-24 17:49:50 +00006396
John McCall176f8922016-11-30 02:39:18 +00006397 llvm::GlobalVariable *GCATV =
6398 values.finishAndCreateGlobal(ExtCatName.str(), CGM.getPointerAlign(),
6399 /*constant*/ false,
6400 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006401 if (CGM.getTriple().isOSBinFormatMachO())
6402 GCATV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006403 CGM.addCompilerUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006404 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006405
6406 // Determine if this category is also "non-lazy".
6407 if (ImplementationIsNonLazy(OCD))
6408 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006409 // method definition entries must be clear for next implementation.
6410 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006411}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006412
John McCall176f8922016-11-30 02:39:18 +00006413/// emitMethodConstant - Return a struct objc_method constant. If
6414/// forProtocol is true, the implementation will be null; otherwise,
6415/// the method must have a definition registered with the runtime.
6416///
6417/// struct _objc_method {
6418/// SEL _cmd;
6419/// char *method_type;
6420/// char *_imp;
6421/// }
6422void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
6423 const ObjCMethodDecl *MD,
6424 bool forProtocol) {
6425 auto method = builder.beginStruct(ObjCTypes.MethodTy);
6426 method.addBitCast(GetMethodVarName(MD->getSelector()),
6427 ObjCTypes.SelectorPtrTy);
6428 method.add(GetMethodVarType(MD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006429
John McCall176f8922016-11-30 02:39:18 +00006430 if (forProtocol) {
6431 // Protocol methods have no implementation. So, this entry is always NULL.
6432 method.addNullPointer(ObjCTypes.Int8PtrTy);
6433 } else {
6434 llvm::Function *fn = GetMethodDefinition(MD);
6435 assert(fn && "no definition for method?");
6436 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
6437 }
6438
6439 method.finishAndAddTo(builder);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006440}
6441
John McCall176f8922016-11-30 02:39:18 +00006442/// Build meta-data for method declarations.
6443///
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006444/// struct _method_list_t {
6445/// uint32_t entsize; // sizeof(struct _objc_method)
6446/// uint32_t method_count;
6447/// struct _objc_method method_list[method_count];
6448/// }
6449///
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00006450llvm::Constant *
John McCall176f8922016-11-30 02:39:18 +00006451CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
6452 ArrayRef<const ObjCMethodDecl *> methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006453 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006454 if (methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006455 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006456
John McCall176f8922016-11-30 02:39:18 +00006457 StringRef prefix;
6458 bool forProtocol;
6459 switch (kind) {
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006460 case MethodListType::CategoryInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006461 prefix = "\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_";
6462 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006463 break;
6464 case MethodListType::CategoryClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006465 prefix = "\01l_OBJC_$_CATEGORY_CLASS_METHODS_";
6466 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006467 break;
6468 case MethodListType::InstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006469 prefix = "\01l_OBJC_$_INSTANCE_METHODS_";
6470 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006471 break;
6472 case MethodListType::ClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006473 prefix = "\01l_OBJC_$_CLASS_METHODS_";
6474 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006475 break;
6476
6477 case MethodListType::ProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006478 prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_";
6479 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006480 break;
6481 case MethodListType::ProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006482 prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_";
6483 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006484 break;
6485 case MethodListType::OptionalProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006486 prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_";
6487 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006488 break;
6489 case MethodListType::OptionalProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006490 prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_";
6491 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006492 break;
6493 }
6494
John McCall176f8922016-11-30 02:39:18 +00006495 ConstantInitBuilder builder(CGM);
6496 auto values = builder.beginStruct();
6497
6498 // sizeof(struct _objc_method)
6499 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
6500 values.addInt(ObjCTypes.IntTy, Size);
6501 // method_count
6502 values.addInt(ObjCTypes.IntTy, methods.size());
6503 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
6504 for (auto MD : methods) {
6505 emitMethodConstant(methodArray, MD, forProtocol);
6506 }
6507 methodArray.finishAndAddTo(values);
6508
6509 auto *GV = values.finishAndCreateGlobal(prefix + name, CGM.getPointerAlign(),
6510 /*constant*/ false,
6511 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006512 if (CGM.getTriple().isOSBinFormatMachO())
6513 GV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006514 CGM.addCompilerUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006515 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006516}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006517
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006518/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6519/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006520llvm::GlobalVariable *
6521CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6522 const ObjCIvarDecl *Ivar) {
6523 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006524 llvm::SmallString<64> Name("OBJC_IVAR_$_");
6525 Name += Container->getObjCRuntimeNameAsString();
6526 Name += ".";
6527 Name += Ivar->getName();
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006528 llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
6529 if (!IvarOffsetGV) {
6530 IvarOffsetGV =
6531 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy,
6532 false, llvm::GlobalValue::ExternalLinkage,
6533 nullptr, Name.str());
6534 if (CGM.getTriple().isOSBinFormatCOFF()) {
6535 bool IsPrivateOrPackage =
6536 Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6537 Ivar->getAccessControl() == ObjCIvarDecl::Package;
6538
6539 if (ID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
6540 IvarOffsetGV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
6541 else if (ID->hasAttr<DLLImportAttr>())
6542 IvarOffsetGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
6543 }
6544 }
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006545 return IvarOffsetGV;
6546}
6547
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006548llvm::Constant *
6549CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6550 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00006551 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006552 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Tim Northover238b5082014-03-29 13:42:40 +00006553 IvarOffsetGV->setInitializer(
6554 llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006555 IvarOffsetGV->setAlignment(
Tim Northover238b5082014-03-29 13:42:40 +00006556 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006557
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006558 if (!CGM.getTriple().isOSBinFormatCOFF()) {
6559 // FIXME: This matches gcc, but shouldn't the visibility be set on the use
6560 // as well (i.e., in ObjCIvarOffsetVariable).
6561 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6562 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6563 ID->getVisibility() == HiddenVisibility)
6564 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6565 else
6566 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
6567 }
6568
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006569 if (CGM.getTriple().isOSBinFormatMachO())
6570 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006571 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006572}
6573
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006574/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006575/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006576/// IvarListnfABIPtrTy.
6577/// struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00006578/// unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006579/// char *name;
6580/// char *type;
6581/// uint32_t alignment;
6582/// uint32_t size;
6583/// }
6584/// struct _ivar_list_t {
6585/// uint32 entsize; // sizeof(struct _ivar_t)
6586/// uint32 count;
6587/// struct _iver_t list[count];
6588/// }
6589///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00006590
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006591llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006592 const ObjCImplementationDecl *ID) {
6593
John McCall176f8922016-11-30 02:39:18 +00006594 ConstantInitBuilder builder(CGM);
6595 auto ivarList = builder.beginStruct();
6596 ivarList.addInt(ObjCTypes.IntTy,
6597 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
6598 auto ivarCountSlot = ivarList.addPlaceholder();
6599 auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006600
Jordy Rosea91768e2011-07-22 02:08:32 +00006601 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006602 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006603
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006604 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006605
Jordy Rosea91768e2011-07-22 02:08:32 +00006606 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00006607 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00006608 // Ignore unnamed bit-fields.
6609 if (!IVD->getDeclName())
6610 continue;
John McCall176f8922016-11-30 02:39:18 +00006611
6612 auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
6613 ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
6614 ComputeIvarBaseOffset(CGM, ID, IVD)));
6615 ivar.add(GetMethodVarName(IVD->getIdentifier()));
6616 ivar.add(GetMethodVarType(IVD));
Chris Lattner2192fe52011-07-18 04:24:23 +00006617 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006618 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmowdd31ca12012-10-08 16:25:52 +00006619 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006620 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006621 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006622 Align = llvm::Log2_32(Align);
John McCall176f8922016-11-30 02:39:18 +00006623 ivar.addInt(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00006624 // NOTE. Size of a bitfield does not match gcc's, because of the
6625 // way bitfields are treated special in each. But I am told that
6626 // 'size' for bitfield ivars is ignored by the runtime so it does
6627 // not matter. If it matters, there is enough info to get the
6628 // bitfield right!
John McCall176f8922016-11-30 02:39:18 +00006629 ivar.addInt(ObjCTypes.IntTy, Size);
6630 ivar.finishAndAddTo(ivars);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006631 }
6632 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006633 if (ivars.empty()) {
6634 ivars.abandon();
6635 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00006636 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCall176f8922016-11-30 02:39:18 +00006637 }
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006638
John McCall176f8922016-11-30 02:39:18 +00006639 auto ivarCount = ivars.size();
6640 ivars.finishAndAddTo(ivarList);
6641 ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
6642
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006643 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
6644 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00006645 ivarList.finishAndCreateGlobal(Prefix + OID->getObjCRuntimeNameAsString(),
6646 CGM.getPointerAlign(), /*constant*/ false,
6647 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006648 if (CGM.getTriple().isOSBinFormatMachO())
6649 GV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006650 CGM.addCompilerUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00006651 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006652}
6653
6654llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006655 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006656 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006657
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006658 if (!Entry) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006659 // We use the initializer as a marker of whether this is a forward
6660 // reference or not. At module finalization we add the empty
6661 // contents for protocols which were referenced but never defined.
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006662 llvm::SmallString<64> Protocol;
6663 llvm::raw_svector_ostream(Protocol) << "\01l_OBJC_PROTOCOL_$_"
6664 << PD->getObjCRuntimeNameAsString();
6665
6666 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6667 false, llvm::GlobalValue::ExternalLinkage,
6668 nullptr, Protocol);
6669 if (!CGM.getTriple().isOSBinFormatMachO())
6670 Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
6671 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006672
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006673 return Entry;
6674}
6675
6676/// GetOrEmitProtocol - Generate the protocol meta-data:
6677/// @code
6678/// struct _protocol_t {
6679/// id isa; // NULL
6680/// const char * const protocol_name;
6681/// const struct _protocol_list_t * protocol_list; // super protocols
6682/// const struct method_list_t * const instance_methods;
6683/// const struct method_list_t * const class_methods;
6684/// const struct method_list_t *optionalInstanceMethods;
6685/// const struct method_list_t *optionalClassMethods;
6686/// const struct _prop_list_t * properties;
6687/// const uint32_t size; // sizeof(struct _protocol_t)
6688/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006689/// const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006690/// const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00006691/// const struct _prop_list_t * class_properties;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006692/// }
6693/// @endcode
6694///
6695
6696llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006697 const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00006698 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006699
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006700 // Early exit if a defining object has already been generated.
6701 if (Entry && Entry->hasInitializer())
6702 return Entry;
6703
Douglas Gregora715bff2012-01-01 19:51:50 +00006704 // Use the protocol definition, if there is one.
6705 if (const ObjCProtocolDecl *Def = PD->getDefinition())
6706 PD = Def;
6707
John McCall176f8922016-11-30 02:39:18 +00006708 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006709
John McCall176f8922016-11-30 02:39:18 +00006710 ConstantInitBuilder builder(CGM);
6711 auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
Douglas Gregora9d84932011-05-27 01:19:52 +00006712
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006713 // isa is NULL
John McCall176f8922016-11-30 02:39:18 +00006714 values.addNullPointer(ObjCTypes.ObjectPtrTy);
6715 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
6716 values.add(EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_"
6717 + PD->getObjCRuntimeNameAsString(),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006718 PD->protocol_begin(),
John McCall176f8922016-11-30 02:39:18 +00006719 PD->protocol_end()));
6720 values.add(methodLists.emitMethodList(this, PD,
6721 ProtocolMethodLists::RequiredInstanceMethods));
6722 values.add(methodLists.emitMethodList(this, PD,
6723 ProtocolMethodLists::RequiredClassMethods));
6724 values.add(methodLists.emitMethodList(this, PD,
6725 ProtocolMethodLists::OptionalInstanceMethods));
6726 values.add(methodLists.emitMethodList(this, PD,
6727 ProtocolMethodLists::OptionalClassMethods));
6728 values.add(EmitPropertyList(
6729 "\01l_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
6730 nullptr, PD, ObjCTypes, false));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006731 uint32_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006732 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
John McCall176f8922016-11-30 02:39:18 +00006733 values.addInt(ObjCTypes.IntTy, Size);
6734 values.addInt(ObjCTypes.IntTy, 0);
6735 values.add(EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006736 + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006737 methodLists.emitExtendedTypesArray(this),
6738 ObjCTypes));
6739
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006740 // const char *demangledName;
John McCall176f8922016-11-30 02:39:18 +00006741 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Rence7bff52016-01-29 23:46:55 +00006742
John McCall176f8922016-11-30 02:39:18 +00006743 values.add(EmitPropertyList(
Manman Rence7bff52016-01-29 23:46:55 +00006744 "\01l_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006745 nullptr, PD, ObjCTypes, true));
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006746
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006747 if (Entry) {
Rafael Espindola24615092014-09-12 20:14:20 +00006748 // Already created, fix the linkage and update the initializer.
6749 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
John McCall176f8922016-11-30 02:39:18 +00006750 values.finishAndSetAsInitializer(Entry);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006751 } else {
John McCall176f8922016-11-30 02:39:18 +00006752 llvm::SmallString<64> symbolName;
6753 llvm::raw_svector_ostream(symbolName)
6754 << "\01l_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006755
John McCall176f8922016-11-30 02:39:18 +00006756 Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
6757 /*constant*/ false,
6758 llvm::GlobalValue::WeakAnyLinkage);
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006759 if (!CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00006760 Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
John McCallf9582a72012-03-30 21:29:05 +00006761
6762 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006763 }
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006764 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Rafael Espindola060062a2014-03-06 22:15:10 +00006765 CGM.addCompilerUsedGlobal(Entry);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006766
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006767 // Use this protocol meta-data to build protocol list table in section
6768 // __DATA, __objc_protolist
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006769 llvm::SmallString<64> ProtocolRef;
6770 llvm::raw_svector_ostream(ProtocolRef) << "\01l_OBJC_LABEL_PROTOCOL_$_"
6771 << PD->getObjCRuntimeNameAsString();
6772
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006773 llvm::GlobalVariable *PTGV =
6774 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006775 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006776 ProtocolRef);
6777 if (!CGM.getTriple().isOSBinFormatMachO())
6778 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006779 PTGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006780 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006781 if (CGM.getTriple().isOSBinFormatMachO())
6782 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006783 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Rafael Espindola060062a2014-03-06 22:15:10 +00006784 CGM.addCompilerUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006785 return Entry;
6786}
6787
6788/// EmitProtocolList - Generate protocol list meta-data:
6789/// @code
6790/// struct _protocol_list_t {
6791/// long protocol_count; // Note, this is 32/64 bit
6792/// struct _protocol_t[protocol_count];
6793/// }
6794/// @endcode
6795///
6796llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006797CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006798 ObjCProtocolDecl::protocol_iterator begin,
6799 ObjCProtocolDecl::protocol_iterator end) {
Dmitri Gribenkof8579502013-01-12 19:30:44 +00006800 SmallVector<llvm::Constant *, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006801
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006802 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006803 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00006804 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006805
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006806 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006807 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006808 Name.toVector(TmpName);
6809 llvm::GlobalVariable *GV =
6810 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006811 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006812 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006813
John McCall176f8922016-11-30 02:39:18 +00006814 ConstantInitBuilder builder(CGM);
6815 auto values = builder.beginStruct();
6816 auto countSlot = values.addPlaceholder();
6817
6818 // A null-terminated array of protocols.
6819 auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006820 for (; begin != end; ++begin)
John McCall176f8922016-11-30 02:39:18 +00006821 array.add(GetProtocolRef(*begin)); // Implemented???
6822 auto count = array.size();
6823 array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006824
John McCall176f8922016-11-30 02:39:18 +00006825 array.finishAndAddTo(values);
6826 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006827
John McCall176f8922016-11-30 02:39:18 +00006828 GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
6829 /*constant*/ false,
6830 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006831 if (CGM.getTriple().isOSBinFormatMachO())
6832 GV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006833 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006834 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006835 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006836}
6837
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006838/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
6839/// This code gen. amounts to generating code for:
6840/// @code
6841/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
6842/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006843///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00006844LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00006845 CodeGen::CodeGenFunction &CGF,
6846 QualType ObjectTy,
6847 llvm::Value *BaseValue,
6848 const ObjCIvarDecl *Ivar,
6849 unsigned CVRQualifiers) {
6850 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006851 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00006852 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006853 Offset);
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006854}
6855
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006856llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006857 CodeGen::CodeGenFunction &CGF,
6858 const ObjCInterfaceDecl *Interface,
6859 const ObjCIvarDecl *Ivar) {
Tim Northover238b5082014-03-29 13:42:40 +00006860 llvm::Value *IvarOffsetValue = ObjCIvarOffsetVariable(Interface, Ivar);
John McCall7f416cc2015-09-08 08:05:57 +00006861 IvarOffsetValue = CGF.Builder.CreateAlignedLoad(IvarOffsetValue,
6862 CGF.getSizeAlign(), "ivar");
Tim Northover238b5082014-03-29 13:42:40 +00006863 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
6864 cast<llvm::LoadInst>(IvarOffsetValue)
6865 ->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
Craig Topper5fc8fc22014-08-27 06:28:36 +00006866 llvm::MDNode::get(VMContext, None));
Tim Northover238b5082014-03-29 13:42:40 +00006867
6868 // This could be 32bit int or 64bit integer depending on the architecture.
6869 // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
6870 // as this is what caller always expectes.
6871 if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
6872 IvarOffsetValue = CGF.Builder.CreateIntCast(
6873 IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
6874 return IvarOffsetValue;
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006875}
6876
John McCall234eac82011-05-13 23:16:18 +00006877static void appendSelectorForMessageRefTable(std::string &buffer,
6878 Selector selector) {
6879 if (selector.isUnarySelector()) {
6880 buffer += selector.getNameForSlot(0);
6881 return;
6882 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006883
John McCall234eac82011-05-13 23:16:18 +00006884 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
6885 buffer += selector.getNameForSlot(i);
6886 buffer += '_';
6887 }
6888}
6889
Eric Christopherd160c502016-01-29 01:35:53 +00006890/// Emit a "vtable" message send. We emit a weak hidden-visibility
John McCall9e8bb002011-05-14 03:10:52 +00006891/// struct, initially containing the selector pointer and a pointer to
6892/// a "fixup" variant of the appropriate objc_msgSend. To call, we
6893/// load and call the function pointer, passing the address of the
6894/// struct as the second parameter. The runtime determines whether
6895/// the selector is currently emitted using vtable dispatch; if so, it
6896/// substitutes a stub function which simply tail-calls through the
6897/// appropriate vtable slot, and if not, it substitues a stub function
6898/// which tail-calls objc_msgSend. Both stubs adjust the selector
6899/// argument to correctly point to the selector.
6900RValue
6901CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
6902 ReturnValueSlot returnSlot,
6903 QualType resultType,
6904 Selector selector,
6905 llvm::Value *arg0,
6906 QualType arg0Type,
6907 bool isSuper,
6908 const CallArgList &formalArgs,
6909 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00006910 // Compute the actual arguments.
6911 CallArgList args;
6912
John McCall9e8bb002011-05-14 03:10:52 +00006913 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00006914 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00006915 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
6916 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00006917
John McCall9e8bb002011-05-14 03:10:52 +00006918 // Second argument: a pointer to the message ref structure. Leave
6919 // the actual argument value blank for now.
Craig Topper8a13c412014-05-21 05:09:00 +00006920 args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
John McCall234eac82011-05-13 23:16:18 +00006921
6922 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
6923
John McCalla729c622012-02-17 03:33:10 +00006924 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCall234eac82011-05-13 23:16:18 +00006925
John McCall5880fb82011-05-14 21:12:11 +00006926 NullReturnState nullReturn;
6927
John McCall9e8bb002011-05-14 03:10:52 +00006928 // Find the function to call and the mangled name for the message
6929 // ref structure. Using a different mangled name wouldn't actually
6930 // be a problem; it would just be a waste.
6931 //
6932 // The runtime currently never uses vtable dispatch for anything
6933 // except normal, non-super message-sends.
6934 // FIXME: don't use this for that.
Craig Topper8a13c412014-05-21 05:09:00 +00006935 llvm::Constant *fn = nullptr;
John McCall234eac82011-05-13 23:16:18 +00006936 std::string messageRefName("\01l_");
Tim Northovere77cc392014-03-29 13:28:05 +00006937 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
John McCall234eac82011-05-13 23:16:18 +00006938 if (isSuper) {
6939 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
6940 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006941 } else {
John McCall5880fb82011-05-14 21:12:11 +00006942 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00006943 fn = ObjCTypes.getMessageSendStretFixupFn();
6944 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006945 }
John McCall234eac82011-05-13 23:16:18 +00006946 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
6947 fn = ObjCTypes.getMessageSendFpretFixupFn();
6948 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00006949 } else {
John McCall234eac82011-05-13 23:16:18 +00006950 if (isSuper) {
6951 fn = ObjCTypes.getMessageSendSuper2FixupFn();
6952 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006953 } else {
John McCall234eac82011-05-13 23:16:18 +00006954 fn = ObjCTypes.getMessageSendFixupFn();
6955 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006956 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006957 }
John McCall234eac82011-05-13 23:16:18 +00006958 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
6959 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006960
John McCall234eac82011-05-13 23:16:18 +00006961 // Append the selector name, except use underscores anywhere we
6962 // would have used colons.
6963 appendSelectorForMessageRefTable(messageRefName, selector);
6964
6965 llvm::GlobalVariable *messageRef
6966 = CGM.getModule().getGlobalVariable(messageRefName);
6967 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00006968 // Build the message ref structure.
John McCall176f8922016-11-30 02:39:18 +00006969 ConstantInitBuilder builder(CGM);
6970 auto values = builder.beginStruct();
6971 values.add(fn);
6972 values.add(GetMethodVarName(selector));
6973 messageRef = values.finishAndCreateGlobal(messageRefName,
6974 CharUnits::fromQuantity(16),
6975 /*constant*/ false,
6976 llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006977 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
John McCall234eac82011-05-13 23:16:18 +00006978 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
6979 }
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006980
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006981 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00006982 if (CGM.getLangOpts().ObjCAutoRefCount && method)
David Majnemer59f77922016-06-24 04:05:48 +00006983 for (const auto *ParamDecl : method->parameters()) {
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006984 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
6985 if (!nullReturn.NullBB)
6986 nullReturn.init(CGF, arg0);
6987 requiresnullCheck = true;
6988 break;
6989 }
6990 }
6991
John McCall7f416cc2015-09-08 08:05:57 +00006992 Address mref =
6993 Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
6994 CGF.getPointerAlign());
John McCall234eac82011-05-13 23:16:18 +00006995
John McCall9e8bb002011-05-14 03:10:52 +00006996 // Update the message ref argument.
John McCall7f416cc2015-09-08 08:05:57 +00006997 args[1].RV = RValue::get(mref.getPointer());
John McCall234eac82011-05-13 23:16:18 +00006998
6999 // Load the function to call from the message ref table.
John McCall7f416cc2015-09-08 08:05:57 +00007000 Address calleeAddr =
7001 CGF.Builder.CreateStructGEP(mref, 0, CharUnits::Zero());
John McCallb92ab1a2016-10-26 23:46:34 +00007002 llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
John McCall234eac82011-05-13 23:16:18 +00007003
John McCallb92ab1a2016-10-26 23:46:34 +00007004 calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
7005 CGCallee callee(CGCalleeInfo(), calleePtr);
John McCall234eac82011-05-13 23:16:18 +00007006
John McCalla729c622012-02-17 03:33:10 +00007007 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Craig Topper8a13c412014-05-21 05:09:00 +00007008 return nullReturn.complete(CGF, result, resultType, formalArgs,
7009 requiresnullCheck ? method : nullptr);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007010}
7011
7012/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007013CodeGen::RValue
7014CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007015 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007016 QualType ResultType,
7017 Selector Sel,
7018 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007019 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00007020 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007021 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00007022 return isVTableDispatchedSelector(Sel)
7023 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007024 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00007025 false, CallArgs, Method)
7026 : EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00007027 EmitSelector(CGF, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007028 Receiver, CGF.getContext().getObjCIdType(),
John McCall1e3157b2015-09-10 22:27:50 +00007029 false, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007030}
7031
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007032llvm::GlobalVariable *
Benjamin Kramer0772c422016-02-13 13:42:54 +00007033CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name, bool Weak) {
Rafael Espindola554256c2014-02-26 22:25:45 +00007034 llvm::GlobalValue::LinkageTypes L =
7035 Weak ? llvm::GlobalValue::ExternalWeakLinkage
7036 : llvm::GlobalValue::ExternalLinkage;
7037
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007038 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
7039
Rafael Espindola554256c2014-02-26 22:25:45 +00007040 if (!GV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007041 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Craig Topper8a13c412014-05-21 05:09:00 +00007042 false, L, nullptr, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007043
Rafael Espindola554256c2014-02-26 22:25:45 +00007044 assert(GV->getLinkage() == L);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007045 return GV;
7046}
7047
John McCall882987f2013-02-28 19:01:20 +00007048llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
Rafael Espindola554256c2014-02-26 22:25:45 +00007049 IdentifierInfo *II,
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007050 bool Weak,
7051 const ObjCInterfaceDecl *ID) {
John McCall7f416cc2015-09-08 08:05:57 +00007052 CharUnits Align = CGF.getPointerAlign();
John McCall31168b02011-06-15 23:02:42 +00007053 llvm::GlobalVariable *&Entry = ClassReferences[II];
7054
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007055 if (!Entry) {
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00007056 StringRef Name = ID ? ID->getObjCRuntimeNameAsString() : II->getName();
7057 std::string ClassName = (getClassSymbolPrefix() + Name).str();
Rafael Espindola554256c2014-02-26 22:25:45 +00007058 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, Weak);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007059 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
7060 false, llvm::GlobalValue::PrivateLinkage,
7061 ClassGV, "OBJC_CLASSLIST_REFERENCES_$_");
John McCall7f416cc2015-09-08 08:05:57 +00007062 Entry->setAlignment(Align.getQuantity());
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007063 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00007064 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007065 }
John McCall7f416cc2015-09-08 08:05:57 +00007066 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007067}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007068
John McCall882987f2013-02-28 19:01:20 +00007069llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00007070 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00007071 // If the class has the objc_runtime_visible attribute, we need to
7072 // use the Objective-C runtime to get the class.
7073 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
7074 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
7075
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007076 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID->isWeakImported(), ID);
John McCall31168b02011-06-15 23:02:42 +00007077}
7078
7079llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
John McCall882987f2013-02-28 19:01:20 +00007080 CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00007081 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
Hans Wennborgdcfba332015-10-06 23:40:43 +00007082 return EmitClassRefFromId(CGF, II, false, nullptr);
John McCall31168b02011-06-15 23:02:42 +00007083}
7084
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007085llvm::Value *
John McCall882987f2013-02-28 19:01:20 +00007086CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007087 const ObjCInterfaceDecl *ID) {
John McCall7f416cc2015-09-08 08:05:57 +00007088 CharUnits Align = CGF.getPointerAlign();
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007089 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007090
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007091 if (!Entry) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007092 llvm::SmallString<64> ClassName(getClassSymbolPrefix());
7093 ClassName += ID->getObjCRuntimeNameAsString();
7094 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(),
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00007095 ID->isWeakImported());
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007096 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
7097 false, llvm::GlobalValue::PrivateLinkage,
7098 ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
John McCall7f416cc2015-09-08 08:05:57 +00007099 Entry->setAlignment(Align.getQuantity());
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007100 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00007101 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007102 }
John McCall7f416cc2015-09-08 08:05:57 +00007103 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007104}
7105
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007106/// EmitMetaClassRef - Return a Value * of the address of _class_t
7107/// meta-data
7108///
John McCall882987f2013-02-28 19:01:20 +00007109llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00007110 const ObjCInterfaceDecl *ID,
7111 bool Weak) {
John McCall7f416cc2015-09-08 08:05:57 +00007112 CharUnits Align = CGF.getPointerAlign();
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007113 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
Rafael Espindola21039aa2014-02-27 16:26:32 +00007114 if (!Entry) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007115 llvm::SmallString<64> MetaClassName(getMetaclassSymbolPrefix());
7116 MetaClassName += ID->getObjCRuntimeNameAsString();
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00007117 llvm::GlobalVariable *MetaClassGV =
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007118 GetClassGlobal(MetaClassName.str(), Weak);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007119
Rafael Espindola21039aa2014-02-27 16:26:32 +00007120 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00007121 false, llvm::GlobalValue::PrivateLinkage,
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007122 MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
John McCall7f416cc2015-09-08 08:05:57 +00007123 Entry->setAlignment(Align.getQuantity());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007124
Rafael Espindola21039aa2014-02-27 16:26:32 +00007125 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00007126 CGM.addCompilerUsedGlobal(Entry);
Rafael Espindola21039aa2014-02-27 16:26:32 +00007127 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007128
John McCall7f416cc2015-09-08 08:05:57 +00007129 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007130}
7131
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007132/// GetClass - Return a reference to the class for the given interface
7133/// decl.
John McCall882987f2013-02-28 19:01:20 +00007134llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007135 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00007136 if (ID->isWeakImported()) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007137 llvm::SmallString<64> ClassName(getClassSymbolPrefix());
7138 ClassName += ID->getObjCRuntimeNameAsString();
7139 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(), true);
Nick Lewycky9a441642014-02-27 00:36:00 +00007140 (void)ClassGV;
Rafael Espindolab3262952014-05-09 00:43:37 +00007141 assert(ClassGV->hasExternalWeakLinkage());
Fariborz Jahanian95ace552009-11-17 22:42:00 +00007142 }
7143
John McCall882987f2013-02-28 19:01:20 +00007144 return EmitClassRef(CGF, ID);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007145}
7146
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007147/// Generates a message send where the super is the receiver. This is
7148/// a message send to self with special delivery semantics indicating
7149/// which class's method should be called.
7150CodeGen::RValue
7151CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007152 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007153 QualType ResultType,
7154 Selector Sel,
7155 const ObjCInterfaceDecl *Class,
7156 bool isCategoryImpl,
7157 llvm::Value *Receiver,
7158 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007159 const CodeGen::CallArgList &CallArgs,
7160 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007161 // ...
7162 // Create and init a super structure; this is a (receiver, class)
7163 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00007164 Address ObjCSuper =
7165 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
7166 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007167
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007168 llvm::Value *ReceiverAsObject =
7169 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
David Blaikie1ed728c2015-04-05 22:45:47 +00007170 CGF.Builder.CreateStore(
7171 ReceiverAsObject,
John McCall7f416cc2015-09-08 08:05:57 +00007172 CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007173
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007174 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00007175 llvm::Value *Target;
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007176 if (IsClassMessage)
Fariborz Jahanian85b99da2014-08-28 17:05:17 +00007177 Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007178 else
John McCall882987f2013-02-28 19:01:20 +00007179 Target = EmitSuperClassRef(CGF, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007180
Mike Stump18bb9282009-05-16 07:57:57 +00007181 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
7182 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00007183 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007184 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
7185 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
David Blaikie1ed728c2015-04-05 22:45:47 +00007186 CGF.Builder.CreateStore(
John McCall7f416cc2015-09-08 08:05:57 +00007187 Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007188
John McCall9e8bb002011-05-14 03:10:52 +00007189 return (isVTableDispatchedSelector(Sel))
7190 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
John McCall7f416cc2015-09-08 08:05:57 +00007191 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00007192 true, CallArgs, Method)
7193 : EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00007194 EmitSelector(CGF, Sel),
John McCall7f416cc2015-09-08 08:05:57 +00007195 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall1e3157b2015-09-10 22:27:50 +00007196 true, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007197}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007198
John McCall882987f2013-02-28 19:01:20 +00007199llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007200 Selector Sel) {
7201 Address Addr = EmitSelectorAddr(CGF, Sel);
7202
7203 llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
7204 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
7205 llvm::MDNode::get(VMContext, None));
7206 return LI;
7207}
7208
7209Address CGObjCNonFragileABIMac::EmitSelectorAddr(CodeGenFunction &CGF,
7210 Selector Sel) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007211 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007212
John McCall7f416cc2015-09-08 08:05:57 +00007213 CharUnits Align = CGF.getPointerAlign();
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007214 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007215 llvm::Constant *Casted =
7216 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
7217 ObjCTypes.SelectorPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007218 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy,
7219 false, llvm::GlobalValue::PrivateLinkage,
7220 Casted, "OBJC_SELECTOR_REFERENCES_");
Michael Gottesman5c205962013-02-05 23:08:45 +00007221 Entry->setExternallyInitialized(true);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00007222 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
John McCall7f416cc2015-09-08 08:05:57 +00007223 Entry->setAlignment(Align.getQuantity());
Rafael Espindola060062a2014-03-06 22:15:10 +00007224 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007225 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007226
John McCall7f416cc2015-09-08 08:05:57 +00007227 return Address(Entry, Align);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007228}
John McCall7f416cc2015-09-08 08:05:57 +00007229
Fariborz Jahanian06292952009-02-16 22:52:32 +00007230/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007231/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00007232///
7233void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00007234 llvm::Value *src,
John McCall7f416cc2015-09-08 08:05:57 +00007235 Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007236 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007237 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007238 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007239 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007240 assert(Size <= 8 && "does not support size > 8");
7241 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7242 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007243 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7244 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007245 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7246 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007247 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00007248 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007249}
7250
7251/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
7252/// objc_assign_strongCast (id src, id *dst)
7253///
7254void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007255 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007256 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007257 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007258 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007259 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007260 assert(Size <= 8 && "does not support size > 8");
7261 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007262 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007263 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7264 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007265 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7266 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007267 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007268 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
7269 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007270}
7271
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007272void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007273 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007274 Address DestPtr,
7275 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00007276 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007277 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
7278 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007279 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size };
John McCall882987f2013-02-28 19:01:20 +00007280 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007281}
7282
Fariborz Jahanian06292952009-02-16 22:52:32 +00007283/// EmitObjCWeakRead - Code gen for loading value of a __weak
7284/// object: objc_read_weak (id *src)
7285///
7286llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007287 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007288 Address AddrWeakObj) {
7289 llvm::Type *DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007290 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00007291 llvm::Value *read_weak =
7292 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00007293 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00007294 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007295 return read_weak;
7296}
7297
7298/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
7299/// objc_assign_weak (id src, id *dst)
7300///
7301void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007302 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007303 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007304 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007305 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007306 assert(Size <= 8 && "does not support size > 8");
7307 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7308 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007309 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7310 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007311 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7312 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007313 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007314 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
7315 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007316}
7317
7318/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
7319/// objc_assign_global (id src, id *dst)
7320///
7321void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007322 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00007323 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007324 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007325 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007326 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007327 assert(Size <= 8 && "does not support size > 8");
7328 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7329 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007330 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7331 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007332 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7333 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007334 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00007335 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00007336 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
7337 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00007338 else
John McCall882987f2013-02-28 19:01:20 +00007339 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
7340 args, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007341}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007342
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007343void
John McCallbd309292010-07-06 01:34:17 +00007344CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
7345 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00007346 EmitAtSynchronizedStmt(CGF, S,
7347 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
7348 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00007349}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007350
John McCall2ca705e2010-07-24 00:37:23 +00007351llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00007352CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00007353 // There's a particular fixed type info for 'id'.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007354 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
7355 auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007356 if (!IDEHType) {
John McCall2ca705e2010-07-24 00:37:23 +00007357 IDEHType =
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007358 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
7359 llvm::GlobalValue::ExternalLinkage, nullptr,
7360 "OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007361 if (CGM.getTriple().isOSBinFormatCOFF())
7362 IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id"));
7363 }
John McCall2ca705e2010-07-24 00:37:23 +00007364 return IDEHType;
7365 }
7366
7367 // All other types should be Objective-C interface pointer types.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007368 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
John McCall2ca705e2010-07-24 00:37:23 +00007369 assert(PT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007370
John McCall2ca705e2010-07-24 00:37:23 +00007371 const ObjCInterfaceType *IT = PT->getInterfaceType();
7372 assert(IT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007373
John McCall2ca705e2010-07-24 00:37:23 +00007374 return GetInterfaceEHType(IT->getDecl(), false);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007375}
John McCall2ca705e2010-07-24 00:37:23 +00007376
John McCallbd309292010-07-06 01:34:17 +00007377void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
7378 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00007379 EmitTryCatchStmt(CGF, S,
7380 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
7381 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
7382 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00007383}
7384
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007385/// EmitThrowStmt - Generate code for a throw statement.
7386void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007387 const ObjCAtThrowStmt &S,
7388 bool ClearInsertionPoint) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007389 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00007390 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00007391 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00007392 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall17afe452010-10-16 08:21:07 +00007393 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007394 } else {
John McCall882987f2013-02-28 19:01:20 +00007395 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall17afe452010-10-16 08:21:07 +00007396 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007397 }
7398
John McCall17afe452010-10-16 08:21:07 +00007399 CGF.Builder.CreateUnreachable();
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007400 if (ClearInsertionPoint)
7401 CGF.Builder.ClearInsertionPoint();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007402}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007403
John McCall2ca705e2010-07-24 00:37:23 +00007404llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007405CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007406 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007407 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007408 StringRef ClassName = ID->getObjCRuntimeNameAsString();
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007409
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007410 // If we don't need a definition, return the entry if found or check
7411 // if we use an external reference.
7412 if (!ForDefinition) {
7413 if (Entry)
7414 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00007415
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007416 // If this type (or a super class) has the __objc_exception__
7417 // attribute, emit an external reference.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007418 if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
7419 std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str();
7420 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
7421 false, llvm::GlobalValue::ExternalLinkage,
7422 nullptr, EHTypeName);
7423 if (CGM.getTriple().isOSBinFormatCOFF()) {
7424 if (ID->hasAttr<DLLExportAttr>())
7425 Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
7426 else if (ID->hasAttr<DLLImportAttr>())
7427 Entry->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
7428 }
7429 return Entry;
7430 }
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007431 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007432
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007433 // Otherwise we need to either make a new entry or fill in the initializer.
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007434 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007435
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007436 std::string VTableName = "objc_ehtype_vtable";
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007437 auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007438 if (!VTableGV) {
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007439 VTableGV =
7440 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false,
7441 llvm::GlobalValue::ExternalLinkage, nullptr,
7442 VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007443 if (CGM.getTriple().isOSBinFormatCOFF())
7444 VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
7445 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007446
Chris Lattnerece04092012-02-07 00:39:47 +00007447 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
John McCall176f8922016-11-30 02:39:18 +00007448 ConstantInitBuilder builder(CGM);
7449 auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
7450 values.add(llvm::ConstantExpr::getGetElementPtr(VTableGV->getValueType(),
7451 VTableGV, VTableIdx));
7452 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
7453 values.add(GetClassGlobal((getClassSymbolPrefix() + ClassName).str()));
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007454
Rafael Espindola554256c2014-02-26 22:25:45 +00007455 llvm::GlobalValue::LinkageTypes L = ForDefinition
7456 ? llvm::GlobalValue::ExternalLinkage
7457 : llvm::GlobalValue::WeakAnyLinkage;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007458 if (Entry) {
John McCall176f8922016-11-30 02:39:18 +00007459 values.finishAndSetAsInitializer(Entry);
7460 Entry->setAlignment(CGM.getPointerAlign().getQuantity());
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007461 } else {
John McCall176f8922016-11-30 02:39:18 +00007462 Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName,
7463 CGM.getPointerAlign(),
7464 /*constant*/ false,
7465 L);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007466 if (CGM.getTriple().isOSBinFormatCOFF())
7467 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
7468 if (ID->hasAttr<DLLExportAttr>())
7469 Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007470 }
Rafael Espindola554256c2014-02-26 22:25:45 +00007471 assert(Entry->getLinkage() == L);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007472
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007473 if (!CGM.getTriple().isOSBinFormatCOFF())
7474 if (ID->getVisibility() == HiddenVisibility)
7475 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007476
Rafael Espindola554256c2014-02-26 22:25:45 +00007477 if (ForDefinition)
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00007478 if (CGM.getTriple().isOSBinFormatMachO())
7479 Entry->setSection("__DATA,__objc_const");
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007480
7481 return Entry;
7482}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007483
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00007484/* *** */
7485
Daniel Dunbarb036db82008-08-13 03:21:16 +00007486CodeGen::CGObjCRuntime *
7487CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall5fb5df92012-06-20 06:18:46 +00007488 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7489 case ObjCRuntime::FragileMacOSX:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007490 return new CGObjCMac(CGM);
John McCall5fb5df92012-06-20 06:18:46 +00007491
7492 case ObjCRuntime::MacOSX:
7493 case ObjCRuntime::iOS:
Tim Northover756447a2015-10-30 16:30:36 +00007494 case ObjCRuntime::WatchOS:
John McCall5fb5df92012-06-20 06:18:46 +00007495 return new CGObjCNonFragileABIMac(CGM);
7496
David Chisnallb601c962012-07-03 20:49:52 +00007497 case ObjCRuntime::GNUstep:
7498 case ObjCRuntime::GCC:
John McCall775086e2012-07-12 02:07:58 +00007499 case ObjCRuntime::ObjFW:
John McCall5fb5df92012-06-20 06:18:46 +00007500 llvm_unreachable("these runtimes are not Mac runtimes");
7501 }
7502 llvm_unreachable("bad runtime");
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007503}