blob: 593067c454aeef5f4d22f3ad16ce7ea15404d20c [file] [log] [blame]
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattner57540c52011-04-15 05:22:18 +000010// This provides Objective-C code generation targeting the Apple runtime.
Daniel Dunbar303e2c22008-08-11 02:45:11 +000011//
12//===----------------------------------------------------------------------===//
13
John McCallad7c5c12011-02-08 08:22:06 +000014#include "CGBlocks.h"
John McCalled1ae862011-01-28 11:13:47 +000015#include "CGCleanup.h"
Justin Lebar5e83dfe2016-10-21 21:45:01 +000016#include "CGObjCRuntime.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000017#include "CGRecordLayout.h"
18#include "CodeGenFunction.h"
19#include "CodeGenModule.h"
John McCall176f8922016-11-30 02:39:18 +000020#include "ConstantBuilder.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000021#include "clang/AST/ASTContext.h"
Daniel Dunbar221fa942008-08-11 04:54:23 +000022#include "clang/AST/Decl.h"
Daniel Dunbarb036db82008-08-13 03:21:16 +000023#include "clang/AST/DeclObjC.h"
Anders Carlsson15b73de2009-07-18 19:43:29 +000024#include "clang/AST/RecordLayout.h"
Chris Lattnerf0b64d72009-04-26 01:32:48 +000025#include "clang/AST/StmtObjC.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000026#include "clang/Basic/LangOptions.h"
Mark Laceya8e7df32013-10-30 21:53:58 +000027#include "clang/CodeGen/CGFunctionInfo.h"
Saleem Abdulrasool10a49722016-04-08 16:52:00 +000028#include "clang/Frontend/CodeGenOptions.h"
Justin Lebar5e83dfe2016-10-21 21:45:01 +000029#include "llvm/ADT/CachedHashString.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000030#include "llvm/ADT/DenseSet.h"
31#include "llvm/ADT/SetVector.h"
32#include "llvm/ADT/SmallPtrSet.h"
33#include "llvm/ADT/SmallString.h"
Chandler Carruthc80ceea2014-03-04 11:02:08 +000034#include "llvm/IR/CallSite.h"
Chandler Carruthffd55512013-01-02 11:45:17 +000035#include "llvm/IR/DataLayout.h"
36#include "llvm/IR/InlineAsm.h"
37#include "llvm/IR/IntrinsicInst.h"
38#include "llvm/IR/LLVMContext.h"
39#include "llvm/IR/Module.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000040#include "llvm/Support/raw_ostream.h"
Torok Edwindb714922009-08-24 13:25:12 +000041#include <cstdio>
Daniel Dunbar303e2c22008-08-11 02:45:11 +000042
43using namespace clang;
Daniel Dunbar41cf9de2008-09-09 01:06:48 +000044using namespace CodeGen;
Daniel Dunbar303e2c22008-08-11 02:45:11 +000045
46namespace {
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000047
Daniel Dunbar59e476b2009-08-03 17:06:42 +000048// FIXME: We should find a nicer way to make the labels for metadata, string
49// concatenation is lame.
Daniel Dunbarb036db82008-08-13 03:21:16 +000050
Fariborz Jahanian279eda62009-01-21 22:04:16 +000051class ObjCCommonTypesHelper {
Owen Anderson170229f2009-07-14 23:10:40 +000052protected:
53 llvm::LLVMContext &VMContext;
Daniel Dunbar59e476b2009-08-03 17:06:42 +000054
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000055private:
John McCall9dc0db22011-05-15 01:53:33 +000056 // The types of these functions don't really matter because we
57 // should always bitcast before calling them.
58
59 /// id objc_msgSend (id, SEL, ...)
60 ///
61 /// The default messenger, used for sends whose ABI is unchanged from
62 /// the all-integer/pointer case.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000063 llvm::Constant *getMessageSendFn() const {
John McCall31168b02011-06-15 23:02:42 +000064 // Add the non-lazy-bind attribute, since objc_msgSend is likely to
65 // be called a lot.
Chris Lattnera5f58b02011-07-09 17:41:47 +000066 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Bill Wendling8594fcb2013-01-31 00:30:05 +000067 return
68 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
69 params, true),
70 "objc_msgSend",
71 llvm::AttributeSet::get(CGM.getLLVMContext(),
72 llvm::AttributeSet::FunctionIndex,
73 llvm::Attribute::NonLazyBind));
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000074 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000075
John McCall9dc0db22011-05-15 01:53:33 +000076 /// void objc_msgSend_stret (id, SEL, ...)
77 ///
78 /// The messenger used when the return value is an aggregate returned
79 /// by indirect reference in the first argument, and therefore the
80 /// self and selector parameters are shifted over by one.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000081 llvm::Constant *getMessageSendStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000082 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +000083 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
84 params, true),
85 "objc_msgSend_stret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000086
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000087 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000088
John McCall9dc0db22011-05-15 01:53:33 +000089 /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
90 ///
91 /// The messenger used when the return value is returned on the x87
92 /// floating-point stack; without a special entrypoint, the nil case
93 /// would be unbalanced.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000094 llvm::Constant *getMessageSendFpretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000095 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Chris Lattnerece04092012-02-07 00:39:47 +000096 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
97 params, true),
John McCall9dc0db22011-05-15 01:53:33 +000098 "objc_msgSend_fpret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000099
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000100 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000101
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000102 /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
103 ///
104 /// The messenger used when the return value is returned in two values on the
105 /// x87 floating point stack; without a special entrypoint, the nil case
106 /// would be unbalanced. Only used on 64-bit X86.
107 llvm::Constant *getMessageSendFp2retFn() const {
108 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
109 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
110 llvm::Type *resultType =
Reid Kleckneree7cf842014-12-01 22:02:27 +0000111 llvm::StructType::get(longDoubleType, longDoubleType, nullptr);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000112
113 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
114 params, true),
115 "objc_msgSend_fp2ret");
116 }
117
John McCall9dc0db22011-05-15 01:53:33 +0000118 /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
119 ///
120 /// The messenger used for super calls, which have different dispatch
121 /// semantics. The class passed is the superclass of the current
122 /// class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000123 llvm::Constant *getMessageSendSuperFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000124 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000125 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000126 params, true),
127 "objc_msgSendSuper");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000128 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000129
John McCall9dc0db22011-05-15 01:53:33 +0000130 /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
131 ///
132 /// A slightly different messenger used for super calls. The class
133 /// passed is the current class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000134 llvm::Constant *getMessageSendSuperFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000135 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000136 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000137 params, true),
138 "objc_msgSendSuper2");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000139 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000140
John McCall9dc0db22011-05-15 01:53:33 +0000141 /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
142 /// SEL op, ...)
143 ///
144 /// The messenger used for super calls which return an aggregate indirectly.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000145 llvm::Constant *getMessageSendSuperStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000146 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000147 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000148 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000149 "objc_msgSendSuper_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000150 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000151
John McCall9dc0db22011-05-15 01:53:33 +0000152 /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
153 /// SEL op, ...)
154 ///
155 /// objc_msgSendSuper_stret with the super2 semantics.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000156 llvm::Constant *getMessageSendSuperStretFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000157 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000158 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000159 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000160 "objc_msgSendSuper2_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000161 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000162
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000163 llvm::Constant *getMessageSendSuperFpretFn() const {
164 // There is no objc_msgSendSuper_fpret? How can that work?
165 return getMessageSendSuperFn();
166 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000167
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000168 llvm::Constant *getMessageSendSuperFpretFn2() const {
169 // There is no objc_msgSendSuper_fpret? How can that work?
170 return getMessageSendSuperFn2();
171 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000172
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000173protected:
174 CodeGen::CodeGenModule &CGM;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000175
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000176public:
John McCall176f8922016-11-30 02:39:18 +0000177 llvm::IntegerType *ShortTy, *IntTy, *LongTy;
178 llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
Tim Northover238b5082014-03-29 13:42:40 +0000179 llvm::Type *IvarOffsetVarTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000180
Daniel Dunbar5d715592008-08-12 05:28:47 +0000181 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
John McCall176f8922016-11-30 02:39:18 +0000182 llvm::PointerType *ObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000183
Fariborz Jahanian406b1172008-11-18 20:18:11 +0000184 /// PtrObjectPtrTy - LLVM type for id *
John McCall176f8922016-11-30 02:39:18 +0000185 llvm::PointerType *PtrObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000186
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000187 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
John McCall176f8922016-11-30 02:39:18 +0000188 llvm::PointerType *SelectorPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000189
190private:
Daniel Dunbarb036db82008-08-13 03:21:16 +0000191 /// ProtocolPtrTy - LLVM type for external protocol handles
192 /// (typeof(Protocol))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000193 llvm::Type *ExternalProtocolPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000194
195public:
196 llvm::Type *getExternalProtocolPtrTy() {
197 if (!ExternalProtocolPtrTy) {
198 // FIXME: It would be nice to unify this with the opaque type, so that the
199 // IR comes out a bit cleaner.
200 CodeGen::CodeGenTypes &Types = CGM.getTypes();
201 ASTContext &Ctx = CGM.getContext();
202 llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
203 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
204 }
205
206 return ExternalProtocolPtrTy;
207 }
208
Daniel Dunbarc722b852008-08-30 03:02:31 +0000209 // SuperCTy - clang type for struct objc_super.
210 QualType SuperCTy;
211 // SuperPtrCTy - clang type for struct objc_super *.
212 QualType SuperPtrCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000213
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000214 /// SuperTy - LLVM type for struct objc_super.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000215 llvm::StructType *SuperTy;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +0000216 /// SuperPtrTy - LLVM type for struct objc_super *.
John McCall176f8922016-11-30 02:39:18 +0000217 llvm::PointerType *SuperPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000218
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000219 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
220 /// in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000221 llvm::StructType *PropertyTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000222
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000223 /// PropertyListTy - LLVM type for struct objc_property_list
224 /// (_prop_list_t in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000225 llvm::StructType *PropertyListTy;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000226 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
John McCall176f8922016-11-30 02:39:18 +0000227 llvm::PointerType *PropertyListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000228
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000229 // MethodTy - LLVM type for struct objc_method.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000230 llvm::StructType *MethodTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000231
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000232 /// CacheTy - LLVM type for struct objc_cache.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000233 llvm::Type *CacheTy;
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000234 /// CachePtrTy - LLVM type for struct objc_cache *.
John McCall176f8922016-11-30 02:39:18 +0000235 llvm::PointerType *CachePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000236
Chris Lattnerce8754e2009-04-22 02:44:54 +0000237 llvm::Constant *getGetPropertyFn() {
238 CodeGen::CodeGenTypes &Types = CGM.getTypes();
239 ASTContext &Ctx = CGM.getContext();
240 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
John McCall2da83a32010-02-26 00:48:12 +0000241 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
242 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Benjamin Kramer30934732016-07-02 11:41:41 +0000243 CanQualType Params[] = {
244 IdType, SelType,
245 Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), Ctx.BoolTy};
Chris Lattner2192fe52011-07-18 04:24:23 +0000246 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000247 Types.GetFunctionType(
248 Types.arrangeBuiltinFunctionDeclaration(IdType, Params));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000249 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
250 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000251
Chris Lattnerce8754e2009-04-22 02:44:54 +0000252 llvm::Constant *getSetPropertyFn() {
253 CodeGen::CodeGenTypes &Types = CGM.getTypes();
254 ASTContext &Ctx = CGM.getContext();
255 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
John McCall2da83a32010-02-26 00:48:12 +0000256 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
257 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Benjamin Kramer30934732016-07-02 11:41:41 +0000258 CanQualType Params[] = {
259 IdType,
260 SelType,
261 Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(),
262 IdType,
263 Ctx.BoolTy,
264 Ctx.BoolTy};
Chris Lattner2192fe52011-07-18 04:24:23 +0000265 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000266 Types.GetFunctionType(
267 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000268 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
269 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000270
Ted Kremeneke65b0862012-03-06 20:05:56 +0000271 llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) {
272 CodeGen::CodeGenTypes &Types = CGM.getTypes();
273 ASTContext &Ctx = CGM.getContext();
274 // void objc_setProperty_atomic(id self, SEL _cmd,
275 // id newValue, ptrdiff_t offset);
276 // void objc_setProperty_nonatomic(id self, SEL _cmd,
277 // id newValue, ptrdiff_t offset);
278 // void objc_setProperty_atomic_copy(id self, SEL _cmd,
279 // id newValue, ptrdiff_t offset);
280 // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
281 // id newValue, ptrdiff_t offset);
282
283 SmallVector<CanQualType,4> Params;
284 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
285 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
286 Params.push_back(IdType);
287 Params.push_back(SelType);
288 Params.push_back(IdType);
289 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
290 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000291 Types.GetFunctionType(
292 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Ted Kremeneke65b0862012-03-06 20:05:56 +0000293 const char *name;
294 if (atomic && copy)
295 name = "objc_setProperty_atomic_copy";
296 else if (atomic && !copy)
297 name = "objc_setProperty_atomic";
298 else if (!atomic && copy)
299 name = "objc_setProperty_nonatomic_copy";
300 else
301 name = "objc_setProperty_nonatomic";
302
303 return CGM.CreateRuntimeFunction(FTy, name);
304 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000305
306 llvm::Constant *getCopyStructFn() {
307 CodeGen::CodeGenTypes &Types = CGM.getTypes();
308 ASTContext &Ctx = CGM.getContext();
309 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000310 SmallVector<CanQualType,5> Params;
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000311 Params.push_back(Ctx.VoidPtrTy);
312 Params.push_back(Ctx.VoidPtrTy);
313 Params.push_back(Ctx.LongTy);
314 Params.push_back(Ctx.BoolTy);
315 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000316 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000317 Types.GetFunctionType(
318 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000319 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
320 }
321
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000322 /// This routine declares and returns address of:
323 /// void objc_copyCppObjectAtomic(
324 /// void *dest, const void *src,
325 /// void (*copyHelper) (void *dest, const void *source));
326 llvm::Constant *getCppAtomicObjectFunction() {
327 CodeGen::CodeGenTypes &Types = CGM.getTypes();
328 ASTContext &Ctx = CGM.getContext();
329 /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
330 SmallVector<CanQualType,3> Params;
331 Params.push_back(Ctx.VoidPtrTy);
332 Params.push_back(Ctx.VoidPtrTy);
333 Params.push_back(Ctx.VoidPtrTy);
334 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000335 Types.GetFunctionType(
336 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000337 return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
338 }
339
Chris Lattnerce8754e2009-04-22 02:44:54 +0000340 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000341 CodeGen::CodeGenTypes &Types = CGM.getTypes();
342 ASTContext &Ctx = CGM.getContext();
Chris Lattnerce8754e2009-04-22 02:44:54 +0000343 // void objc_enumerationMutation (id)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000344 SmallVector<CanQualType,1> Params;
John McCall2da83a32010-02-26 00:48:12 +0000345 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Chris Lattner2192fe52011-07-18 04:24:23 +0000346 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000347 Types.GetFunctionType(
348 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000349 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
350 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000351
Douglas Gregor24ae22c2016-04-01 23:23:52 +0000352 llvm::Constant *getLookUpClassFn() {
353 CodeGen::CodeGenTypes &Types = CGM.getTypes();
354 ASTContext &Ctx = CGM.getContext();
355 // Class objc_lookUpClass (const char *)
356 SmallVector<CanQualType,1> Params;
357 Params.push_back(
358 Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst())));
359 llvm::FunctionType *FTy =
360 Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration(
361 Ctx.getCanonicalType(Ctx.getObjCClassType()),
362 Params));
363 return CGM.CreateRuntimeFunction(FTy, "objc_lookUpClass");
364 }
365
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000366 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattnerce8754e2009-04-22 02:44:54 +0000367 llvm::Constant *getGcReadWeakFn() {
368 // id objc_read_weak (id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000369 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000370 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000371 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000372 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000373 }
374
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000375 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000376 llvm::Constant *getGcAssignWeakFn() {
377 // id objc_assign_weak (id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000378 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000379 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000380 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000381 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
382 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000383
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000384 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000385 llvm::Constant *getGcAssignGlobalFn() {
386 // id objc_assign_global(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000387 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000388 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000389 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000390 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
391 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000392
Fariborz Jahanian217af242010-07-20 20:30:03 +0000393 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
394 llvm::Constant *getGcAssignThreadLocalFn() {
395 // id objc_assign_threadlocal(id src, id * dest)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000396 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian217af242010-07-20 20:30:03 +0000397 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000398 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian217af242010-07-20 20:30:03 +0000399 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
400 }
401
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000402 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000403 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000404 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000405 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
406 CGM.PtrDiffTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000407 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000408 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000409 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
410 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000411
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000412 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
413 llvm::Constant *GcMemmoveCollectableFn() {
414 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000415 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
John McCall9dc0db22011-05-15 01:53:33 +0000416 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000417 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
418 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000419
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000420 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000421 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000422 // id objc_assign_strongCast(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000423 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000424 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000425 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000426 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
427 }
Anders Carlsson9ab53d12009-02-16 22:59:18 +0000428
429 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000430 llvm::Constant *getExceptionThrowFn() {
431 // void objc_exception_throw(id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000432 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000433 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000434 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000435 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
436 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000437
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000438 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
439 llvm::Constant *getExceptionRethrowFn() {
440 // void objc_exception_rethrow(void)
John McCall9dc0db22011-05-15 01:53:33 +0000441 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000442 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
443 }
444
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000445 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerdcceee72009-04-06 16:53:45 +0000446 llvm::Constant *getSyncEnterFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000447 // int objc_sync_enter (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000448 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerdcceee72009-04-06 16:53:45 +0000449 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000450 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000451 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
452 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000453
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000454 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000455 llvm::Constant *getSyncExitFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000456 // int objc_sync_exit (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000457 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000458 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000459 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000460 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
461 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000462
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000463 llvm::Constant *getSendFn(bool IsSuper) const {
464 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
465 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000466
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000467 llvm::Constant *getSendFn2(bool IsSuper) const {
468 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
469 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000470
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000471 llvm::Constant *getSendStretFn(bool IsSuper) const {
472 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
473 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000474
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000475 llvm::Constant *getSendStretFn2(bool IsSuper) const {
476 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
477 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000478
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000479 llvm::Constant *getSendFpretFn(bool IsSuper) const {
480 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
481 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000482
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000483 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
484 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
485 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000486
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000487 llvm::Constant *getSendFp2retFn(bool IsSuper) const {
488 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
489 }
490
491 llvm::Constant *getSendFp2RetFn2(bool IsSuper) const {
492 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
493 }
494
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000495 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000496};
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000497
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000498/// ObjCTypesHelper - Helper class that encapsulates lazy
499/// construction of varies types used during ObjC generation.
500class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000501public:
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000502 /// SymtabTy - LLVM type for struct objc_symtab.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000503 llvm::StructType *SymtabTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000504 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
John McCall176f8922016-11-30 02:39:18 +0000505 llvm::PointerType *SymtabPtrTy;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000506 /// ModuleTy - LLVM type for struct objc_module.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000507 llvm::StructType *ModuleTy;
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000508
Daniel Dunbarb036db82008-08-13 03:21:16 +0000509 /// ProtocolTy - LLVM type for struct objc_protocol.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000510 llvm::StructType *ProtocolTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000511 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
John McCall176f8922016-11-30 02:39:18 +0000512 llvm::PointerType *ProtocolPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000513 /// ProtocolExtensionTy - LLVM type for struct
514 /// objc_protocol_extension.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000515 llvm::StructType *ProtocolExtensionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000516 /// ProtocolExtensionTy - LLVM type for struct
517 /// objc_protocol_extension *.
John McCall176f8922016-11-30 02:39:18 +0000518 llvm::PointerType *ProtocolExtensionPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000519 /// MethodDescriptionTy - LLVM type for struct
520 /// objc_method_description.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000521 llvm::StructType *MethodDescriptionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000522 /// MethodDescriptionListTy - LLVM type for struct
523 /// objc_method_description_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000524 llvm::StructType *MethodDescriptionListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000525 /// MethodDescriptionListPtrTy - LLVM type for struct
526 /// objc_method_description_list *.
John McCall176f8922016-11-30 02:39:18 +0000527 llvm::PointerType *MethodDescriptionListPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000528 /// ProtocolListTy - LLVM type for struct objc_property_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000529 llvm::StructType *ProtocolListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000530 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
John McCall176f8922016-11-30 02:39:18 +0000531 llvm::PointerType *ProtocolListPtrTy;
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000532 /// CategoryTy - LLVM type for struct objc_category.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000533 llvm::StructType *CategoryTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000534 /// ClassTy - LLVM type for struct objc_class.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000535 llvm::StructType *ClassTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000536 /// ClassPtrTy - LLVM type for struct objc_class *.
John McCall176f8922016-11-30 02:39:18 +0000537 llvm::PointerType *ClassPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000538 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000539 llvm::StructType *ClassExtensionTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000540 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
John McCall176f8922016-11-30 02:39:18 +0000541 llvm::PointerType *ClassExtensionPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000542 // IvarTy - LLVM type for struct objc_ivar.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000543 llvm::StructType *IvarTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000544 /// IvarListTy - LLVM type for struct objc_ivar_list.
John McCall176f8922016-11-30 02:39:18 +0000545 llvm::StructType *IvarListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000546 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
John McCall176f8922016-11-30 02:39:18 +0000547 llvm::PointerType *IvarListPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000548 /// MethodListTy - LLVM type for struct objc_method_list.
John McCall176f8922016-11-30 02:39:18 +0000549 llvm::StructType *MethodListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000550 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
John McCall176f8922016-11-30 02:39:18 +0000551 llvm::PointerType *MethodListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000552
Anders Carlsson9ff22482008-09-09 10:10:21 +0000553 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
John McCall176f8922016-11-30 02:39:18 +0000554 llvm::StructType *ExceptionDataTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000555
Anders Carlsson9ff22482008-09-09 10:10:21 +0000556 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000557 llvm::Constant *getExceptionTryEnterFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000558 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000559 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000560 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000561 "objc_exception_try_enter");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000562 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000563
564 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000565 llvm::Constant *getExceptionTryExitFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000566 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000567 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000568 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000569 "objc_exception_try_exit");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000570 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000571
572 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000573 llvm::Constant *getExceptionExtractFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000574 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000575 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000576 params, false),
Chris Lattnerc6406db2009-04-22 02:26:14 +0000577 "objc_exception_extract");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000578 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000579
Anders Carlsson9ff22482008-09-09 10:10:21 +0000580 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000581 llvm::Constant *getExceptionMatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000582 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000583 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000584 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000585 "objc_exception_match");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000586 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000587
Anders Carlsson9ff22482008-09-09 10:10:21 +0000588 /// SetJmpFn - LLVM _setjmp function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000589 llvm::Constant *getSetJmpFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000590 // This is specifically the prototype for x86.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000591 llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
Bill Wendling8594fcb2013-01-31 00:30:05 +0000592 return
593 CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty,
594 params, false),
595 "_setjmp",
596 llvm::AttributeSet::get(CGM.getLLVMContext(),
597 llvm::AttributeSet::FunctionIndex,
598 llvm::Attribute::NonLazyBind));
Chris Lattnerc6406db2009-04-22 02:26:14 +0000599 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000600
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000601public:
602 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000603};
604
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000605/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000606/// modern abi
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000607class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000608public:
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000609 // MethodListnfABITy - LLVM for struct _method_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000610 llvm::StructType *MethodListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000611
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000612 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
John McCall176f8922016-11-30 02:39:18 +0000613 llvm::PointerType *MethodListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000614
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000615 // ProtocolnfABITy = LLVM for struct _protocol_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000616 llvm::StructType *ProtocolnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000617
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000618 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
John McCall176f8922016-11-30 02:39:18 +0000619 llvm::PointerType *ProtocolnfABIPtrTy;
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000620
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000621 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
Chris Lattnera5f58b02011-07-09 17:41:47 +0000622 llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000623
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000624 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
John McCall176f8922016-11-30 02:39:18 +0000625 llvm::PointerType *ProtocolListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000626
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000627 // ClassnfABITy - LLVM for struct _class_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000628 llvm::StructType *ClassnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000629
Fariborz Jahanian71394042009-01-23 23:53:38 +0000630 // ClassnfABIPtrTy - LLVM for struct _class_t*
John McCall176f8922016-11-30 02:39:18 +0000631 llvm::PointerType *ClassnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000632
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000633 // IvarnfABITy - LLVM for struct _ivar_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000634 llvm::StructType *IvarnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000635
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000636 // IvarListnfABITy - LLVM for struct _ivar_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000637 llvm::StructType *IvarListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000638
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000639 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
John McCall176f8922016-11-30 02:39:18 +0000640 llvm::PointerType *IvarListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000641
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000642 // ClassRonfABITy - LLVM for struct _class_ro_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000643 llvm::StructType *ClassRonfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000644
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000645 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
John McCall176f8922016-11-30 02:39:18 +0000646 llvm::PointerType *ImpnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000647
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000648 // CategorynfABITy - LLVM for struct _category_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000649 llvm::StructType *CategorynfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000650
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000651 // New types for nonfragile abi messaging.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000652
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000653 // MessageRefTy - LLVM for:
654 // struct _message_ref_t {
655 // IMP messenger;
656 // SEL name;
657 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000658 llvm::StructType *MessageRefTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000659 // MessageRefCTy - clang type for struct _message_ref_t
660 QualType MessageRefCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000661
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000662 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000663 llvm::Type *MessageRefPtrTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000664 // MessageRefCPtrTy - clang type for struct _message_ref_t*
665 QualType MessageRefCPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000666
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000667 // SuperMessageRefTy - LLVM for:
668 // struct _super_message_ref_t {
669 // SUPER_IMP messenger;
670 // SEL name;
671 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000672 llvm::StructType *SuperMessageRefTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000673
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000674 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
John McCall176f8922016-11-30 02:39:18 +0000675 llvm::PointerType *SuperMessageRefPtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000676
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000677 llvm::Constant *getMessageSendFixupFn() {
678 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000679 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000680 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000681 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000682 "objc_msgSend_fixup");
683 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000684
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000685 llvm::Constant *getMessageSendFpretFixupFn() {
686 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000687 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000688 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000689 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000690 "objc_msgSend_fpret_fixup");
691 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000692
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000693 llvm::Constant *getMessageSendStretFixupFn() {
694 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000695 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000696 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000697 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000698 "objc_msgSend_stret_fixup");
699 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000700
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000701 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000702 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000703 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000704 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000705 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000706 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000707 "objc_msgSendSuper2_fixup");
708 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000709
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000710 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000711 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000712 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000713 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000714 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000715 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000716 "objc_msgSendSuper2_stret_fixup");
717 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000718
Chris Lattnera7c00b42009-04-22 02:15:23 +0000719 llvm::Constant *getObjCEndCatchFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000720 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000721 "objc_end_catch");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000722
Chris Lattnera7c00b42009-04-22 02:15:23 +0000723 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000724
Chris Lattnera7c00b42009-04-22 02:15:23 +0000725 llvm::Constant *getObjCBeginCatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000726 llvm::Type *params[] = { Int8PtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000727 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000728 params, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000729 "objc_begin_catch");
730 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +0000731
Chris Lattnera5f58b02011-07-09 17:41:47 +0000732 llvm::StructType *EHTypeTy;
733 llvm::Type *EHTypePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000734
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000735 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000736};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000737
Saleem Abdulrasool271106c2016-09-16 23:41:13 +0000738enum class ObjCLabelType {
739 ClassName,
740 MethodVarName,
741 MethodVarType,
742 PropertyName,
743};
744
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000745class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000746public:
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000747 class SKIP_SCAN {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000748 public:
749 unsigned skip;
750 unsigned scan;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000751 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000752 : skip(_skip), scan(_scan) {}
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000753 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000754
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000755 /// opcode for captured block variables layout 'instructions'.
756 /// In the following descriptions, 'I' is the value of the immediate field.
757 /// (field following the opcode).
758 ///
759 enum BLOCK_LAYOUT_OPCODE {
760 /// An operator which affects how the following layout should be
761 /// interpreted.
762 /// I == 0: Halt interpretation and treat everything else as
763 /// a non-pointer. Note that this instruction is equal
764 /// to '\0'.
765 /// I != 0: Currently unused.
766 BLOCK_LAYOUT_OPERATOR = 0,
767
768 /// The next I+1 bytes do not contain a value of object pointer type.
769 /// Note that this can leave the stream unaligned, meaning that
770 /// subsequent word-size instructions do not begin at a multiple of
771 /// the pointer size.
772 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
773
774 /// The next I+1 words do not contain a value of object pointer type.
775 /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
776 /// when the required skip quantity is a multiple of the pointer size.
777 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
778
779 /// The next I+1 words are __strong pointers to Objective-C
780 /// objects or blocks.
781 BLOCK_LAYOUT_STRONG = 3,
782
783 /// The next I+1 words are pointers to __block variables.
784 BLOCK_LAYOUT_BYREF = 4,
785
786 /// The next I+1 words are __weak pointers to Objective-C
787 /// objects or blocks.
788 BLOCK_LAYOUT_WEAK = 5,
789
790 /// The next I+1 words are __unsafe_unretained pointers to
791 /// Objective-C objects or blocks.
792 BLOCK_LAYOUT_UNRETAINED = 6
793
794 /// The next I+1 words are block or object pointers with some
795 /// as-yet-unspecified ownership semantics. If we add more
796 /// flavors of ownership semantics, values will be taken from
797 /// this range.
798 ///
799 /// This is included so that older tools can at least continue
800 /// processing the layout past such things.
801 //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
802
803 /// All other opcodes are reserved. Halt interpretation and
804 /// treat everything else as opaque.
805 };
806
807 class RUN_SKIP {
808 public:
809 enum BLOCK_LAYOUT_OPCODE opcode;
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000810 CharUnits block_var_bytepos;
811 CharUnits block_var_size;
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000812 RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000813 CharUnits BytePos = CharUnits::Zero(),
814 CharUnits Size = CharUnits::Zero())
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +0000815 : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000816
817 // Allow sorting based on byte pos.
818 bool operator<(const RUN_SKIP &b) const {
819 return block_var_bytepos < b.block_var_bytepos;
820 }
821 };
822
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000823protected:
Owen Andersonae86c192009-07-13 04:10:07 +0000824 llvm::LLVMContext &VMContext;
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000825 // FIXME! May not be needing this after all.
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000826 unsigned ObjCABI;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000827
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000828 // arc/mrr layout of captured block literal variables.
829 SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000830
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000831 /// LazySymbols - Symbols to generate a lazy reference for. See
832 /// DefinedSymbols and FinishModule().
Daniel Dunbard027a922009-09-07 00:20:42 +0000833 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000834
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000835 /// DefinedSymbols - External symbols which are defined by this
836 /// module. The symbols in this list and LazySymbols are used to add
837 /// special linker symbols which ensure that Objective-C modules are
838 /// linked properly.
Daniel Dunbard027a922009-09-07 00:20:42 +0000839 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000840
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000841 /// ClassNames - uniqued class names.
Fariborz Jahanian451b92a2014-07-16 16:16:04 +0000842 llvm::StringMap<llvm::GlobalVariable*> ClassNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000843
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000844 /// MethodVarNames - uniqued method variable names.
845 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000846
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000847 /// DefinedCategoryNames - list of category names in form Class_Category.
Justin Lebar5e83dfe2016-10-21 21:45:01 +0000848 llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames;
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000849
Daniel Dunbarb036db82008-08-13 03:21:16 +0000850 /// MethodVarTypes - uniqued method type signatures. We have to use
851 /// a StringMap here because have no other unique reference.
852 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000853
Daniel Dunbar3c76cb52008-08-26 21:51:14 +0000854 /// MethodDefinitions - map of methods which have been defined in
855 /// this translation unit.
856 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000857
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000858 /// PropertyNames - uniqued method variable names.
859 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000860
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000861 /// ClassReferences - uniqued class references.
862 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000863
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000864 /// SelectorReferences - uniqued selector references.
865 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000866
Daniel Dunbarb036db82008-08-13 03:21:16 +0000867 /// Protocols - Protocols for which an objc_protocol structure has
868 /// been emitted. Forward declarations are handled by creating an
869 /// empty structure whose initializer is filled in when/if defined.
870 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000871
Daniel Dunbarc475d422008-10-29 22:36:39 +0000872 /// DefinedProtocols - Protocols which have actually been
873 /// defined. We should not need this, see FIXME in GenerateProtocol.
874 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000875
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000876 /// DefinedClasses - List of defined classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000877 SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +0000878
879 /// ImplementedClasses - List of @implemented classes.
880 SmallVector<const ObjCInterfaceDecl*, 16> ImplementedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000881
882 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000883 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000884
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000885 /// DefinedCategories - List of defined categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000886 SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000887
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000888 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000889 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000890
John McCallcd21d542016-11-30 23:15:55 +0000891 /// Cached reference to the class for constant strings. This value has type
892 /// int * but is actually an Obj-C class pointer.
893 llvm::WeakVH ConstantStringClassRef;
894
895 /// \brief The LLVM type corresponding to NSConstantString.
896 llvm::StructType *NSConstantStringType = nullptr;
897
898 llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
899
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000900 /// GetNameForMethod - Return a name for the given method.
901 /// \param[out] NameOut - The return value.
902 void GetNameForMethod(const ObjCMethodDecl *OMD,
903 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000904 SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000905
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000906 /// GetMethodVarName - Return a unique constant for the given
907 /// selector's name. The return value has type char *.
908 llvm::Constant *GetMethodVarName(Selector Sel);
909 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000910
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000911 /// GetMethodVarType - Return a unique constant for the given
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000912 /// method's type encoding string. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000913
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000914 // FIXME: This is a horrible name.
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000915 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
916 bool Extended = false);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000917 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000918
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000919 /// GetPropertyName - Return a unique constant for the given
920 /// name. The return value has type char *.
921 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000922
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000923 // FIXME: This can be dropped once string functions are unified.
924 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
925 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000926
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000927 /// GetClassName - Return a unique constant for the given selector's
Fariborz Jahanian451b92a2014-07-16 16:16:04 +0000928 /// runtime name (which may change via use of objc_runtime_name attribute on
929 /// class or protocol definition. The return value has type char *.
930 llvm::Constant *GetClassName(StringRef RuntimeName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000931
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000932 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
933
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000934 /// BuildIvarLayout - Builds ivar layout bitmap for the class
935 /// implementation for the __strong or __weak case.
936 ///
John McCall460ce582015-10-22 18:38:17 +0000937 /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there
938 /// are any weak ivars defined directly in the class. Meaningless unless
939 /// building a weak layout. Does not guarantee that the layout will
940 /// actually have any entries, because the ivar might be under-aligned.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000941 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
John McCall3fd13f062015-10-21 18:06:47 +0000942 CharUnits beginOffset,
943 CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +0000944 bool forStrongLayout,
945 bool hasMRCWeakIvars);
946
947 llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI,
948 CharUnits beginOffset,
949 CharUnits endOffset) {
950 return BuildIvarLayout(OI, beginOffset, endOffset, true, false);
951 }
952
953 llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI,
954 CharUnits beginOffset,
955 CharUnits endOffset,
956 bool hasMRCWeakIvars) {
957 return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
958 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +0000959
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000960 Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
Fariborz Jahanian2dd78192012-11-02 22:51:18 +0000961
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000962 void UpdateRunSkipBlockVars(bool IsByref,
963 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000964 CharUnits FieldOffset,
965 CharUnits FieldSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000966
967 void BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000968 CharUnits BytePos, bool &HasUnion,
969 bool ByrefLayout=false);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000970
971 void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
972 const RecordDecl *RD,
973 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000974 CharUnits BytePos, bool &HasUnion,
975 bool ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000976
Fariborz Jahanian23290b02012-11-01 18:32:55 +0000977 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
978
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000979 llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
980
Fariborz Jahanian01dff422009-03-05 19:17:31 +0000981 /// GetIvarLayoutName - Returns a unique constant for the given
982 /// ivar layout bitmap.
983 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
984 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000985
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000986 /// EmitPropertyList - Emit the given property list. The return
987 /// value has type PropertyListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000988 llvm::Constant *EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000989 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000990 const ObjCContainerDecl *OCD,
Manman Renad0e7912016-01-29 19:22:54 +0000991 const ObjCCommonTypesHelper &ObjCTypes,
992 bool IsClassProperty);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000993
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000994 /// EmitProtocolMethodTypes - Generate the array of extended method type
995 /// strings. The return value has type Int8PtrPtrTy.
996 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +0000997 ArrayRef<llvm::Constant*> MethodTypes,
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000998 const ObjCCommonTypesHelper &ObjCTypes);
999
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001000 /// GetProtocolRef - Return a reference to the internal protocol
1001 /// description, creating an empty one if it has not been
1002 /// defined. The return value has type ProtocolPtrTy.
1003 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +00001004
Douglas Gregor24ae22c2016-04-01 23:23:52 +00001005 /// Return a reference to the given Class using runtime calls rather than
1006 /// by a symbol reference.
1007 llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
1008 const ObjCInterfaceDecl *ID,
1009 ObjCCommonTypesHelper &ObjCTypes);
1010
John McCall3fd13f062015-10-21 18:06:47 +00001011public:
Daniel Dunbar30c65362009-03-09 20:09:19 +00001012 /// CreateMetadataVar - Create a global variable with internal
1013 /// linkage for use by the Objective-C runtime.
1014 ///
1015 /// This is a convenience wrapper which not only creates the
1016 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +00001017 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001018 ///
1019 /// \param Name - The variable name.
1020 /// \param Init - The variable initializer; this is also used to
John McCall176f8922016-11-30 02:39:18 +00001021 /// define the type of the variable.
Alp Toker541d5072014-06-07 23:30:53 +00001022 /// \param Section - The section the variable should go into, or empty.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001023 /// \param Align - The alignment for the variable, or 0.
1024 /// \param AddToUsed - Whether the variable should be added to
John McCall176f8922016-11-30 02:39:18 +00001025 /// "llvm.used".
1026 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1027 ConstantStructBuilder &Init,
1028 StringRef Section, CharUnits Align,
1029 bool AddToUsed);
1030 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1031 llvm::Constant *Init,
John McCall7f416cc2015-09-08 08:05:57 +00001032 StringRef Section, CharUnits Align,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001033 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +00001034
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001035 llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00001036 ObjCLabelType LabelType,
1037 bool ForceNonFragileABI = false,
1038 bool NullTerminate = true);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001039
John McCall3fd13f062015-10-21 18:06:47 +00001040protected:
John McCall9e8bb002011-05-14 03:10:52 +00001041 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1042 ReturnValueSlot Return,
1043 QualType ResultType,
1044 llvm::Value *Sel,
1045 llvm::Value *Arg0,
1046 QualType Arg0Ty,
1047 bool IsSuper,
1048 const CallArgList &CallArgs,
1049 const ObjCMethodDecl *OMD,
John McCall1e3157b2015-09-10 22:27:50 +00001050 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00001051 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +00001052
Daniel Dunbar5e639272010-04-25 20:39:01 +00001053 /// EmitImageInfo - Emit the image info marker used to encode some module
1054 /// level information.
1055 void EmitImageInfo();
1056
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001057public:
Owen Andersonae86c192009-07-13 04:10:07 +00001058 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
John McCalla729c622012-02-17 03:33:10 +00001059 CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001060
John McCall3fd13f062015-10-21 18:06:47 +00001061 bool isNonFragileABI() const {
1062 return ObjCABI == 2;
1063 }
1064
John McCall7f416cc2015-09-08 08:05:57 +00001065 ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
John McCallcd21d542016-11-30 23:15:55 +00001066 ConstantAddress GenerateConstantNSString(const StringLiteral *SL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001067
Craig Topper4f12f102014-03-12 06:41:41 +00001068 llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
Craig Topper8a13c412014-05-21 05:09:00 +00001069 const ObjCContainerDecl *CD=nullptr) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001070
1071 void GenerateProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001072
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001073 /// GetOrEmitProtocol - Get the protocol object for the given
1074 /// declaration, emitting it if necessary. The return value has type
1075 /// ProtocolPtrTy.
1076 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001077
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001078 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1079 /// object for the given declaration, emitting it if needed. These
1080 /// forward references will be filled in with empty bodies if no
1081 /// definition is seen. The return value has type ProtocolPtrTy.
1082 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCallcd21d542016-11-30 23:15:55 +00001083
1084 virtual llvm::Constant *getNSConstantStringClassRef() = 0;
1085
Craig Topper4f12f102014-03-12 06:41:41 +00001086 llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1087 const CGBlockInfo &blockInfo) override;
1088 llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1089 const CGBlockInfo &blockInfo) override;
1090
1091 llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1092 QualType T) override;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001093};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001094
John McCall176f8922016-11-30 02:39:18 +00001095namespace {
1096
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001097enum class MethodListType {
1098 CategoryInstanceMethods,
1099 CategoryClassMethods,
1100 InstanceMethods,
1101 ClassMethods,
1102 ProtocolInstanceMethods,
1103 ProtocolClassMethods,
1104 OptionalProtocolInstanceMethods,
1105 OptionalProtocolClassMethods,
1106};
1107
John McCall176f8922016-11-30 02:39:18 +00001108/// A convenience class for splitting the methods of a protocol into
1109/// the four interesting groups.
1110class ProtocolMethodLists {
1111public:
1112 enum Kind {
1113 RequiredInstanceMethods,
1114 RequiredClassMethods,
1115 OptionalInstanceMethods,
1116 OptionalClassMethods
1117 };
1118 enum {
1119 NumProtocolMethodLists = 4
1120 };
1121
1122 static MethodListType getMethodListKind(Kind kind) {
1123 switch (kind) {
1124 case RequiredInstanceMethods:
1125 return MethodListType::ProtocolInstanceMethods;
1126 case RequiredClassMethods:
1127 return MethodListType::ProtocolClassMethods;
1128 case OptionalInstanceMethods:
1129 return MethodListType::OptionalProtocolInstanceMethods;
1130 case OptionalClassMethods:
1131 return MethodListType::OptionalProtocolClassMethods;
1132 }
1133 llvm_unreachable("bad kind");
1134 }
1135
1136 SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];
1137
1138 static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
1139 ProtocolMethodLists result;
1140
1141 for (auto MD : PD->methods()) {
1142 size_t index = (2 * size_t(MD->isOptional()))
1143 + (size_t(MD->isClassMethod()));
1144 result.Methods[index].push_back(MD);
1145 }
1146
1147 return result;
1148 }
1149
1150 template <class Self>
1151 SmallVector<llvm::Constant*, 8> emitExtendedTypesArray(Self *self) const {
1152 // In both ABIs, the method types list is parallel with the
1153 // concatenation of the methods arrays in the following order:
1154 // instance methods
1155 // class methods
1156 // optional instance methods
1157 // optional class methods
1158 SmallVector<llvm::Constant*, 8> result;
1159
1160 // Methods is already in the correct order for both ABIs.
1161 for (auto &list : Methods) {
1162 for (auto MD : list) {
1163 result.push_back(self->GetMethodVarType(MD, true));
1164 }
1165 }
1166
1167 return result;
1168 }
1169
1170 template <class Self>
1171 llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD,
1172 Kind kind) const {
1173 return self->emitMethodList(PD->getObjCRuntimeNameAsString(),
1174 getMethodListKind(kind), Methods[kind]);
1175 }
1176};
1177
1178} // end anonymous namespace
1179
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001180class CGObjCMac : public CGObjCCommonMac {
1181private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001182 friend ProtocolMethodLists;
John McCall176f8922016-11-30 02:39:18 +00001183
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001184 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001185
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001186 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001187 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001188 void EmitModuleInfo();
1189
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001190 /// EmitModuleSymols - Emit module symbols, the list of defined
1191 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001192 llvm::Constant *EmitModuleSymbols();
1193
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001194 /// FinishModule - Write out global data structures at the end of
1195 /// processing a translation unit.
1196 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +00001197
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001198 /// EmitClassExtension - Generate the class extension structure used
1199 /// to store the weak ivar layout and properties. The return value
1200 /// has type ClassExtensionPtrTy.
John McCall3fd13f062015-10-21 18:06:47 +00001201 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
John McCall460ce582015-10-22 18:38:17 +00001202 CharUnits instanceSize,
Manman Renad0e7912016-01-29 19:22:54 +00001203 bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00001204 bool isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001205
1206 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1207 /// for the given class.
John McCall882987f2013-02-28 19:01:20 +00001208 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001209 const ObjCInterfaceDecl *ID);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001210
John McCall882987f2013-02-28 19:01:20 +00001211 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00001212 IdentifierInfo *II);
Craig Topper4f12f102014-03-12 06:41:41 +00001213
1214 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
1215
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001216 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1217 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001218
1219 /// EmitIvarList - Emit the ivar list for the given
1220 /// implementation. If ForClass is true the list of class ivars
1221 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1222 /// interface ivars will be emitted. The return value has type
1223 /// IvarListPtrTy.
1224 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00001225 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001226
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001227 /// EmitMetaClass - Emit a forward reference to the class structure
1228 /// for the metaclass of the given interface. The return value has
1229 /// type ClassPtrTy.
1230 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1231
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001232 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001233 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001234 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1235 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00001236 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001237
John McCall176f8922016-11-30 02:39:18 +00001238 void emitMethodConstant(ConstantArrayBuilder &builder,
1239 const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001240
John McCall176f8922016-11-30 02:39:18 +00001241 void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
1242 const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001243
1244 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +00001245 /// implementation. The return value has type MethodListPtrTy.
John McCall176f8922016-11-30 02:39:18 +00001246 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1247 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001248
Daniel Dunbarc475d422008-10-29 22:36:39 +00001249 /// GetOrEmitProtocol - Get the protocol object for the given
1250 /// declaration, emitting it if necessary. The return value has type
1251 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001252 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001253
1254 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1255 /// object for the given declaration, emitting it if needed. These
1256 /// forward references will be filled in with empty bodies if no
1257 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001258 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001259
Daniel Dunbarb036db82008-08-13 03:21:16 +00001260 /// EmitProtocolExtension - Generate the protocol extension
1261 /// structure used to store optional instance and class methods, and
1262 /// protocol properties. The return value has type
1263 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001264 llvm::Constant *
1265 EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00001266 const ProtocolMethodLists &methodLists);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001267
1268 /// EmitProtocolList - Generate the list of referenced
1269 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001270 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001271 ObjCProtocolDecl::protocol_iterator begin,
1272 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001273
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001274 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1275 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001276 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1277 Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001278
1279public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001280 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001281
John McCallcd21d542016-11-30 23:15:55 +00001282 llvm::Constant *getNSConstantStringClassRef() override;
1283
Craig Topper4f12f102014-03-12 06:41:41 +00001284 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001285
Craig Topper4f12f102014-03-12 06:41:41 +00001286 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1287 ReturnValueSlot Return,
1288 QualType ResultType,
1289 Selector Sel, llvm::Value *Receiver,
1290 const CallArgList &CallArgs,
1291 const ObjCInterfaceDecl *Class,
1292 const ObjCMethodDecl *Method) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001293
Craig Topper4f12f102014-03-12 06:41:41 +00001294 CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001295 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001296 ReturnValueSlot Return, QualType ResultType,
1297 Selector Sel, const ObjCInterfaceDecl *Class,
1298 bool isCategoryImpl, llvm::Value *Receiver,
1299 bool IsClassMessage, const CallArgList &CallArgs,
1300 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001301
Craig Topper4f12f102014-03-12 06:41:41 +00001302 llvm::Value *GetClass(CodeGenFunction &CGF,
1303 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001304
John McCall7f416cc2015-09-08 08:05:57 +00001305 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
1306 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001307
1308 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1309 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001310 llvm::Value *GetSelector(CodeGenFunction &CGF,
1311 const ObjCMethodDecl *Method) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001312
Craig Topper4f12f102014-03-12 06:41:41 +00001313 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001314
Craig Topper4f12f102014-03-12 06:41:41 +00001315 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001316
Craig Topper4f12f102014-03-12 06:41:41 +00001317 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001318
Craig Topper4f12f102014-03-12 06:41:41 +00001319 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001320
Craig Topper4f12f102014-03-12 06:41:41 +00001321 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1322 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001323
Craig Topper4f12f102014-03-12 06:41:41 +00001324 llvm::Constant *GetPropertyGetFunction() override;
1325 llvm::Constant *GetPropertySetFunction() override;
1326 llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1327 bool copy) override;
1328 llvm::Constant *GetGetStructFunction() override;
1329 llvm::Constant *GetSetStructFunction() override;
1330 llvm::Constant *GetCppAtomicObjectGetFunction() override;
1331 llvm::Constant *GetCppAtomicObjectSetFunction() override;
1332 llvm::Constant *EnumerationMutationFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001333
Craig Topper4f12f102014-03-12 06:41:41 +00001334 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1335 const ObjCAtTryStmt &S) override;
1336 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1337 const ObjCAtSynchronizedStmt &S) override;
John McCallbd309292010-07-06 01:34:17 +00001338 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Craig Topper4f12f102014-03-12 06:41:41 +00001339 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1340 bool ClearInsertionPoint=true) override;
1341 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001342 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001343 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001344 llvm::Value *src, Address dst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001345 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001346 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001347 bool threadlocal = false) override;
1348 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001349 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001350 llvm::Value *ivarOffset) override;
1351 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001352 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001353 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001354 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001355 llvm::Value *size) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001356
Craig Topper4f12f102014-03-12 06:41:41 +00001357 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1358 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1359 unsigned CVRQualifiers) override;
1360 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1361 const ObjCInterfaceDecl *Interface,
1362 const ObjCIvarDecl *Ivar) override;
1363
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001364 /// GetClassGlobal - Return the global variable for the Objective-C
1365 /// class of the given name.
Benjamin Kramer0772c422016-02-13 13:42:54 +00001366 llvm::GlobalVariable *GetClassGlobal(StringRef Name,
Craig Toppera798a9d2014-03-02 09:32:10 +00001367 bool Weak = false) override {
David Blaikie83d382b2011-09-23 05:06:16 +00001368 llvm_unreachable("CGObjCMac::GetClassGlobal");
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001369 }
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001370};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001371
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001372class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001373private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001374 friend ProtocolMethodLists;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001375 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001376 llvm::GlobalVariable* ObjCEmptyCacheVar;
John McCall176f8922016-11-30 02:39:18 +00001377 llvm::Constant* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001378
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001379 /// SuperClassReferences - uniqued super class references.
1380 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001381
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001382 /// MetaClassReferences - uniqued meta class references.
1383 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001384
1385 /// EHTypeReferences - uniqued class ehtype references.
1386 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001387
John McCall9e8bb002011-05-14 03:10:52 +00001388 /// VTableDispatchMethods - List of methods for which we generate
1389 /// vtable-based message dispatch.
1390 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001391
Fariborz Jahanian67260552009-11-17 21:37:35 +00001392 /// DefinedMetaClasses - List of defined meta-classes.
1393 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1394
John McCall9e8bb002011-05-14 03:10:52 +00001395 /// isVTableDispatchedSelector - Returns true if SEL is a
1396 /// vtable-based selector.
1397 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001398
Fariborz Jahanian71394042009-01-23 23:53:38 +00001399 /// FinishNonFragileABIModule - Write out global data structures at the end of
1400 /// processing a translation unit.
1401 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001402
Daniel Dunbar19573e72009-05-15 21:48:48 +00001403 /// AddModuleClassList - Add the given list of class pointers to the
1404 /// module with the provided symbol and section names.
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001405 void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container,
1406 StringRef SymbolName, StringRef SectionName);
Daniel Dunbar19573e72009-05-15 21:48:48 +00001407
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001408 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1409 unsigned InstanceStart,
1410 unsigned InstanceSize,
1411 const ObjCImplementationDecl *ID);
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00001412 llvm::GlobalVariable * BuildClassMetaData(const std::string &ClassName,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001413 llvm::Constant *IsAGV,
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001414 llvm::Constant *SuperClassGV,
Fariborz Jahanian82208252009-01-31 00:59:10 +00001415 llvm::Constant *ClassRoGV,
Rafael Espindola554256c2014-02-26 22:25:45 +00001416 bool HiddenVisibility,
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00001417 bool Weak);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001418
John McCall176f8922016-11-30 02:39:18 +00001419 void emitMethodConstant(ConstantArrayBuilder &builder,
1420 const ObjCMethodDecl *MD,
1421 bool forProtocol);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001422
John McCall176f8922016-11-30 02:39:18 +00001423 /// Emit the method list for the given implementation. The return value
1424 /// has type MethodListnfABITy.
1425 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1426 ArrayRef<const ObjCMethodDecl *> Methods);
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001427
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001428 /// EmitIvarList - Emit the ivar list for the given
1429 /// implementation. If ForClass is true the list of class ivars
1430 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1431 /// interface ivars will be emitted. The return value has type
1432 /// IvarListnfABIPtrTy.
1433 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001434
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001435 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001436 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00001437 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001438
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001439 /// GetOrEmitProtocol - Get the protocol object for the given
1440 /// declaration, emitting it if necessary. The return value has type
1441 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001442 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001443
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001444 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1445 /// object for the given declaration, emitting it if needed. These
1446 /// forward references will be filled in with empty bodies if no
1447 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001448 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001449
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001450 /// EmitProtocolList - Generate the list of referenced
1451 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001452 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001453 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001454 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001455
John McCall9e8bb002011-05-14 03:10:52 +00001456 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1457 ReturnValueSlot Return,
1458 QualType ResultType,
1459 Selector Sel,
1460 llvm::Value *Receiver,
1461 QualType Arg0Ty,
1462 bool IsSuper,
1463 const CallArgList &CallArgs,
1464 const ObjCMethodDecl *Method);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001465
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001466 /// GetClassGlobal - Return the global variable for the Objective-C
1467 /// class of the given name.
Benjamin Kramer0772c422016-02-13 13:42:54 +00001468 llvm::GlobalVariable *GetClassGlobal(StringRef Name,
Craig Toppera798a9d2014-03-02 09:32:10 +00001469 bool Weak = false) override;
Rafael Espindola554256c2014-02-26 22:25:45 +00001470
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001471 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001472 /// for the given class reference.
John McCall882987f2013-02-28 19:01:20 +00001473 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001474 const ObjCInterfaceDecl *ID);
John McCall31168b02011-06-15 23:02:42 +00001475
John McCall882987f2013-02-28 19:01:20 +00001476 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00001477 IdentifierInfo *II, bool Weak,
1478 const ObjCInterfaceDecl *ID);
Craig Topper4f12f102014-03-12 06:41:41 +00001479
1480 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001481
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001482 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1483 /// for the given super class reference.
John McCall882987f2013-02-28 19:01:20 +00001484 llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001485 const ObjCInterfaceDecl *ID);
1486
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001487 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1488 /// meta-data
John McCall882987f2013-02-28 19:01:20 +00001489 llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00001490 const ObjCInterfaceDecl *ID, bool Weak);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001491
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001492 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1493 /// the given ivar.
1494 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001495 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001496 const ObjCInterfaceDecl *ID,
1497 const ObjCIvarDecl *Ivar);
1498
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001499 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1500 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001501 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1502 Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001503
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001504 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001505 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001506 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001507 bool ForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001508
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001509 StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001510
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001511 StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; }
Daniel Dunbar15894b72009-04-07 05:48:37 +00001512
Daniel Dunbar961202372009-05-03 12:57:56 +00001513 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001514 uint32_t &InstanceStart,
1515 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001516
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001517 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001518 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001519 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1520 return CGM.getContext().Selectors.getSelector(0, &II);
1521 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001522
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001523 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001524 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1525 return CGM.getContext().Selectors.getSelector(1, &II);
1526 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001527
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001528 /// ImplementationIsNonLazy - Check whether the given category or
1529 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001530 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001531
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001532 bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001533 const ObjCIvarDecl *IV) {
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001534 // Annotate the load as an invariant load iff inside an instance method
1535 // and ivar belongs to instance method's class and one of its super class.
1536 // This check is needed because the ivar offset is a lazily
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001537 // initialised value that may depend on objc_msgSend to perform a fixup on
1538 // the first message dispatch.
1539 //
1540 // An additional opportunity to mark the load as invariant arises when the
1541 // base of the ivar access is a parameter to an Objective C method.
1542 // However, because the parameters are not available in the current
1543 // interface, we cannot perform this check.
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001544 if (const ObjCMethodDecl *MD =
1545 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
Fariborz Jahanian7a583022014-03-04 22:57:32 +00001546 if (MD->isInstanceMethod())
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001547 if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
1548 return IV->getContainingInterface()->isSuperClassOf(ID);
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001549 return false;
1550 }
1551
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001552public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001553 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
John McCallcd21d542016-11-30 23:15:55 +00001554
1555 llvm::Constant *getNSConstantStringClassRef() override;
1556
Craig Topper4f12f102014-03-12 06:41:41 +00001557 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001558
Craig Topper4f12f102014-03-12 06:41:41 +00001559 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1560 ReturnValueSlot Return,
1561 QualType ResultType, Selector Sel,
1562 llvm::Value *Receiver,
1563 const CallArgList &CallArgs,
1564 const ObjCInterfaceDecl *Class,
1565 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001566
Craig Topper4f12f102014-03-12 06:41:41 +00001567 CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001568 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001569 ReturnValueSlot Return, QualType ResultType,
1570 Selector Sel, const ObjCInterfaceDecl *Class,
1571 bool isCategoryImpl, llvm::Value *Receiver,
1572 bool IsClassMessage, const CallArgList &CallArgs,
1573 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001574
Craig Topper4f12f102014-03-12 06:41:41 +00001575 llvm::Value *GetClass(CodeGenFunction &CGF,
1576 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001577
John McCall7f416cc2015-09-08 08:05:57 +00001578 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override
1579 { return EmitSelector(CGF, Sel); }
1580 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override
1581 { return EmitSelectorAddr(CGF, Sel); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001582
1583 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1584 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001585 llvm::Value *GetSelector(CodeGenFunction &CGF,
1586 const ObjCMethodDecl *Method) override
John McCall882987f2013-02-28 19:01:20 +00001587 { return EmitSelector(CGF, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001588
Craig Topper4f12f102014-03-12 06:41:41 +00001589 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001590
Craig Topper4f12f102014-03-12 06:41:41 +00001591 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
David Chisnall92d436b2012-01-31 18:59:20 +00001592
Craig Topper4f12f102014-03-12 06:41:41 +00001593 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001594
Craig Topper4f12f102014-03-12 06:41:41 +00001595 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1596 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001597
Craig Topper4f12f102014-03-12 06:41:41 +00001598 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001599
Craig Topper4f12f102014-03-12 06:41:41 +00001600 llvm::Constant *GetPropertyGetFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001601 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001602 }
Craig Topper4f12f102014-03-12 06:41:41 +00001603 llvm::Constant *GetPropertySetFunction() override {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001604 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001605 }
Craig Topper4f12f102014-03-12 06:41:41 +00001606
1607 llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1608 bool copy) override {
Ted Kremeneke65b0862012-03-06 20:05:56 +00001609 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1610 }
Craig Topper4f12f102014-03-12 06:41:41 +00001611
1612 llvm::Constant *GetSetStructFunction() override {
David Chisnall168b80f2010-12-26 22:13:16 +00001613 return ObjCTypes.getCopyStructFn();
1614 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001615
Craig Topper4f12f102014-03-12 06:41:41 +00001616 llvm::Constant *GetGetStructFunction() override {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001617 return ObjCTypes.getCopyStructFn();
1618 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001619
Craig Topper4f12f102014-03-12 06:41:41 +00001620 llvm::Constant *GetCppAtomicObjectSetFunction() override {
David Chisnall0d75e062012-12-17 18:54:24 +00001621 return ObjCTypes.getCppAtomicObjectFunction();
1622 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001623
Craig Topper4f12f102014-03-12 06:41:41 +00001624 llvm::Constant *GetCppAtomicObjectGetFunction() override {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001625 return ObjCTypes.getCppAtomicObjectFunction();
1626 }
Craig Topper4f12f102014-03-12 06:41:41 +00001627
1628 llvm::Constant *EnumerationMutationFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001629 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001630 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001631
Craig Topper4f12f102014-03-12 06:41:41 +00001632 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1633 const ObjCAtTryStmt &S) override;
1634 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1635 const ObjCAtSynchronizedStmt &S) override;
1636 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1637 bool ClearInsertionPoint=true) override;
1638 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001639 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001640 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001641 llvm::Value *src, Address edst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001642 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001643 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001644 bool threadlocal = false) override;
1645 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001646 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001647 llvm::Value *ivarOffset) override;
1648 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001649 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001650 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001651 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001652 llvm::Value *size) override;
1653 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1654 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1655 unsigned CVRQualifiers) override;
1656 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1657 const ObjCInterfaceDecl *Interface,
1658 const ObjCIvarDecl *Ivar) override;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001659};
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001660
1661/// A helper class for performing the null-initialization of a return
1662/// value.
1663struct NullReturnState {
1664 llvm::BasicBlock *NullBB;
Craig Topper8a13c412014-05-21 05:09:00 +00001665 NullReturnState() : NullBB(nullptr) {}
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001666
John McCall3d1e2c92013-02-12 05:53:35 +00001667 /// Perform a null-check of the given receiver.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001668 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
John McCall3d1e2c92013-02-12 05:53:35 +00001669 // Make blocks for the null-receiver and call edges.
1670 NullBB = CGF.createBasicBlock("msgSend.null-receiver");
1671 llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001672
1673 // Check for a null receiver and, if there is one, jump to the
John McCall3d1e2c92013-02-12 05:53:35 +00001674 // null-receiver block. There's no point in trying to avoid it:
1675 // we're always going to put *something* there, because otherwise
1676 // we shouldn't have done this null-check in the first place.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001677 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1678 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1679
1680 // Otherwise, start performing the call.
1681 CGF.EmitBlock(callBB);
1682 }
1683
John McCall3d1e2c92013-02-12 05:53:35 +00001684 /// Complete the null-return operation. It is valid to call this
1685 /// regardless of whether 'init' has been called.
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001686 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
1687 const CallArgList &CallArgs,
1688 const ObjCMethodDecl *Method) {
John McCall3d1e2c92013-02-12 05:53:35 +00001689 // If we never had to do a null-check, just use the raw result.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001690 if (!NullBB) return result;
John McCall3d1e2c92013-02-12 05:53:35 +00001691
1692 // The continuation block. This will be left null if we don't have an
1693 // IP, which can happen if the method we're calling is marked noreturn.
Craig Topper8a13c412014-05-21 05:09:00 +00001694 llvm::BasicBlock *contBB = nullptr;
1695
John McCall3d1e2c92013-02-12 05:53:35 +00001696 // Finish the call path.
1697 llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
1698 if (callBB) {
1699 contBB = CGF.createBasicBlock("msgSend.cont");
1700 CGF.Builder.CreateBr(contBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001701 }
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001702
John McCall3d1e2c92013-02-12 05:53:35 +00001703 // Okay, start emitting the null-receiver block.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001704 CGF.EmitBlock(NullBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001705
John McCall3d1e2c92013-02-12 05:53:35 +00001706 // Release any consumed arguments we've got.
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001707 if (Method) {
1708 CallArgList::const_iterator I = CallArgs.begin();
1709 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1710 e = Method->param_end(); i != e; ++i, ++I) {
1711 const ParmVarDecl *ParamDecl = (*i);
1712 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1713 RValue RV = I->RV;
1714 assert(RV.isScalar() &&
1715 "NullReturnState::complete - arg not on object");
John McCallcdda29c2013-03-13 03:10:54 +00001716 CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001717 }
1718 }
1719 }
John McCall3d1e2c92013-02-12 05:53:35 +00001720
1721 // The phi code below assumes that we haven't needed any control flow yet.
1722 assert(CGF.Builder.GetInsertBlock() == NullBB);
1723
1724 // If we've got a void return, just jump to the continuation block.
1725 if (result.isScalar() && resultType->isVoidType()) {
1726 // No jumps required if the message-send was noreturn.
1727 if (contBB) CGF.EmitBlock(contBB);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001728 return result;
1729 }
1730
John McCall3d1e2c92013-02-12 05:53:35 +00001731 // If we've got a scalar return, build a phi.
1732 if (result.isScalar()) {
1733 // Derive the null-initialization value.
1734 llvm::Constant *null = CGF.CGM.EmitNullConstant(resultType);
1735
1736 // If no join is necessary, just flow out.
1737 if (!contBB) return RValue::get(null);
1738
1739 // Otherwise, build a phi.
1740 CGF.EmitBlock(contBB);
1741 llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2);
1742 phi->addIncoming(result.getScalarVal(), callBB);
1743 phi->addIncoming(null, NullBB);
1744 return RValue::get(phi);
1745 }
1746
1747 // If we've got an aggregate return, null the buffer out.
1748 // FIXME: maybe we should be doing things differently for all the
1749 // cases where the ABI has us returning (1) non-agg values in
1750 // memory or (2) agg values in registers.
1751 if (result.isAggregate()) {
1752 assert(result.isAggregate() && "null init of non-aggregate result?");
John McCall7f416cc2015-09-08 08:05:57 +00001753 CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
John McCall3d1e2c92013-02-12 05:53:35 +00001754 if (contBB) CGF.EmitBlock(contBB);
1755 return result;
1756 }
1757
1758 // Complex types.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001759 CGF.EmitBlock(contBB);
John McCall3d1e2c92013-02-12 05:53:35 +00001760 CodeGenFunction::ComplexPairTy callResult = result.getComplexVal();
1761
1762 // Find the scalar type and its zero value.
1763 llvm::Type *scalarTy = callResult.first->getType();
1764 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1765
1766 // Build phis for both coordinates.
1767 llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2);
1768 real->addIncoming(callResult.first, callBB);
1769 real->addIncoming(scalarZero, NullBB);
1770 llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2);
1771 imag->addIncoming(callResult.second, callBB);
1772 imag->addIncoming(scalarZero, NullBB);
1773 return RValue::getComplex(real, imag);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001774 }
1775};
1776
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001777} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001778
1779/* *** Helper Functions *** */
1780
1781/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001782static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
David Blaikiee3b172a2015-04-02 18:55:21 +00001783 llvm::GlobalVariable *C, unsigned idx0,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001784 unsigned idx1) {
1785 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001786 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1787 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001788 };
David Blaikiee3b172a2015-04-02 18:55:21 +00001789 return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001790}
1791
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001792/// hasObjCExceptionAttribute - Return true if this class or any super
1793/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001794static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001795 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001796 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001797 return true;
1798 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001799 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001800 return false;
1801}
1802
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001803/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001804
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001805CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001806 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001807 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001808 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001809}
1810
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001811/// GetClass - Return a reference to the class for the given interface
1812/// decl.
John McCall882987f2013-02-28 19:01:20 +00001813llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001814 const ObjCInterfaceDecl *ID) {
John McCall882987f2013-02-28 19:01:20 +00001815 return EmitClassRef(CGF, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001816}
1817
1818/// GetSelector - Return the pointer to the unique'd string for this selector.
John McCall7f416cc2015-09-08 08:05:57 +00001819llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
1820 return EmitSelector(CGF, Sel);
1821}
1822Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
1823 return EmitSelectorAddr(CGF, Sel);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001824}
John McCall882987f2013-02-28 19:01:20 +00001825llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001826 *Method) {
John McCall882987f2013-02-28 19:01:20 +00001827 return EmitSelector(CGF, Method->getSelector());
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001828}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001829
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001830llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001831 if (T->isObjCIdType() ||
1832 T->isObjCQualifiedIdType()) {
1833 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001834 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001835 }
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001836 if (T->isObjCClassType() ||
1837 T->isObjCQualifiedClassType()) {
1838 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001839 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001840 }
1841 if (T->isObjCObjectPointerType())
1842 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
1843
John McCall2ca705e2010-07-24 00:37:23 +00001844 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall2ca705e2010-07-24 00:37:23 +00001845}
1846
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001847/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001848/*
1849 struct __builtin_CFString {
1850 const int *isa; // point to __CFConstantStringClassReference
1851 int flags;
1852 const char *str;
1853 long length;
1854 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001855*/
1856
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001857/// or Generate a constant NSString object.
1858/*
1859 struct __builtin_NSString {
1860 const int *isa; // point to __NSConstantStringClassReference
1861 const char *str;
1862 unsigned int length;
1863 };
1864*/
1865
John McCallcd21d542016-11-30 23:15:55 +00001866ConstantAddress
1867CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) {
1868 return (!CGM.getLangOpts().NoConstantCFStrings
1869 ? CGM.GetAddrOfConstantCFString(SL)
1870 : GenerateConstantNSString(SL));
1871}
1872
1873static llvm::StringMapEntry<llvm::GlobalVariable *> &
1874GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
1875 const StringLiteral *Literal, unsigned &StringLength) {
1876 StringRef String = Literal->getString();
1877 StringLength = String.size();
1878 return *Map.insert(std::make_pair(String, nullptr)).first;
1879}
1880
1881llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1882 if (llvm::Value *V = ConstantStringClassRef)
1883 return cast<llvm::Constant>(V);
1884
1885 auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
1886 std::string str =
1887 StringClass.empty() ? "_NSConstantStringClassReference"
1888 : "_" + StringClass + "ClassReference";
1889
1890 llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0);
1891 auto GV = CGM.CreateRuntimeVariable(PTy, str);
1892 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1893 ConstantStringClassRef = V;
1894 return V;
1895}
1896
1897llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1898 if (llvm::Value *V = ConstantStringClassRef)
1899 return cast<llvm::Constant>(V);
1900
1901 auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
1902 std::string str =
1903 StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
1904 : "OBJC_CLASS_$_" + StringClass;
1905 auto GV = GetClassGlobal(str);
1906
1907 // Make sure the result is of the correct type.
1908 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1909
1910 ConstantStringClassRef = V;
1911 return V;
1912}
1913
1914ConstantAddress
1915CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) {
1916 unsigned StringLength = 0;
1917 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
1918 GetConstantStringEntry(NSConstantStringMap, Literal, StringLength);
1919
1920 if (auto *C = Entry.second)
1921 return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
1922
1923 // If we don't already have it, get _NSConstantStringClassReference.
1924 llvm::Constant *Class = getNSConstantStringClassRef();
1925
1926 // If we don't already have it, construct the type for a constant NSString.
1927 if (!NSConstantStringType) {
1928 NSConstantStringType =
1929 llvm::StructType::create({
1930 CGM.Int32Ty->getPointerTo(),
1931 CGM.Int8PtrTy,
1932 CGM.IntTy
1933 }, "struct.__builtin_NSString");
1934 }
1935
1936 ConstantInitBuilder Builder(CGM);
1937 auto Fields = Builder.beginStruct(NSConstantStringType);
1938
1939 // Class pointer.
1940 Fields.add(Class);
1941
1942 // String pointer.
1943 llvm::Constant *C =
1944 llvm::ConstantDataArray::getString(VMContext, Entry.first());
1945
1946 llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
1947 bool isConstant = !CGM.getLangOpts().WritableStrings;
1948
1949 auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant,
1950 Linkage, C, ".str");
1951 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1952 // Don't enforce the target's minimum global alignment, since the only use
1953 // of the string is via this class initializer.
1954 GV->setAlignment(1);
1955 Fields.addBitCast(GV, CGM.Int8PtrTy);
1956
1957 // String length.
1958 Fields.addInt(CGM.IntTy, StringLength);
1959
1960 // The struct.
1961 CharUnits Alignment = CGM.getPointerAlign();
1962 GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
1963 /*constant*/ true,
1964 llvm::GlobalVariable::PrivateLinkage);
1965 const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
1966 const char *NSStringNonFragileABISection =
1967 "__DATA,__objc_stringobj,regular,no_dead_strip";
1968 // FIXME. Fix section.
1969 GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile()
1970 ? NSStringNonFragileABISection
1971 : NSStringSection);
1972 Entry.second = GV;
1973
1974 return ConstantAddress(GV, Alignment);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001975}
1976
Ted Kremeneke65b0862012-03-06 20:05:56 +00001977enum {
1978 kCFTaggedObjectID_Integer = (1 << 1) + 1
1979};
1980
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001981/// Generates a message send where the super is the receiver. This is
1982/// a message send to self with special delivery semantics indicating
1983/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001984CodeGen::RValue
1985CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001986 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001987 QualType ResultType,
1988 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001989 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001990 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001991 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001992 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001993 const CodeGen::CallArgList &CallArgs,
1994 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001995 // Create and init a super structure; this is a (receiver, class)
1996 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00001997 Address ObjCSuper =
1998 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
1999 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002000 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002001 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
David Blaikie1ed728c2015-04-05 22:45:47 +00002002 CGF.Builder.CreateStore(
2003 ReceiverAsObject,
John McCall7f416cc2015-09-08 08:05:57 +00002004 CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero()));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002005
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002006 // If this is a class message the metaclass is passed as the target.
2007 llvm::Value *Target;
2008 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002009 if (isCategoryImpl) {
2010 // Message sent to 'super' in a class method defined in a category
2011 // implementation requires an odd treatment.
2012 // If we are in a class method, we must retrieve the
2013 // _metaclass_ for the current class, pointed at by
2014 // the class's "isa" pointer. The following assumes that
2015 // isa" is the first ivar in a class (which it must be).
John McCall882987f2013-02-28 19:01:20 +00002016 Target = EmitClassRef(CGF, Class->getSuperClass());
David Blaikie1ed728c2015-04-05 22:45:47 +00002017 Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
John McCall7f416cc2015-09-08 08:05:57 +00002018 Target = CGF.Builder.CreateAlignedLoad(Target, CGF.getPointerAlign());
Mike Stump658fe022009-07-30 22:28:39 +00002019 } else {
David Blaikie1ed728c2015-04-05 22:45:47 +00002020 llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
2021 llvm::Value *SuperPtr =
2022 CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00002023 llvm::Value *Super =
2024 CGF.Builder.CreateAlignedLoad(SuperPtr, CGF.getPointerAlign());
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002025 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002026 }
David Blaikie1ed728c2015-04-05 22:45:47 +00002027 } else if (isCategoryImpl)
John McCall882987f2013-02-28 19:01:20 +00002028 Target = EmitClassRef(CGF, Class->getSuperClass());
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00002029 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002030 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
David Blaikie1ed728c2015-04-05 22:45:47 +00002031 ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00002032 Target = CGF.Builder.CreateAlignedLoad(ClassPtr, CGF.getPointerAlign());
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002033 }
Mike Stump18bb9282009-05-16 07:57:57 +00002034 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
2035 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00002036 llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00002037 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00002038 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
John McCall7f416cc2015-09-08 08:05:57 +00002039 CGF.Builder.CreateStore(Target,
2040 CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize()));
John McCall9e8bb002011-05-14 03:10:52 +00002041 return EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00002042 EmitSelector(CGF, Sel),
John McCall7f416cc2015-09-08 08:05:57 +00002043 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall1e3157b2015-09-10 22:27:50 +00002044 true, CallArgs, Method, Class, ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002045}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002046
2047/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00002048CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00002049 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00002050 QualType ResultType,
2051 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002052 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00002053 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00002054 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00002055 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00002056 return EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00002057 EmitSelector(CGF, Sel),
John McCall9e8bb002011-05-14 03:10:52 +00002058 Receiver, CGF.getContext().getObjCIdType(),
John McCall1e3157b2015-09-10 22:27:50 +00002059 false, CallArgs, Method, Class, ObjCTypes);
2060}
2061
2062static bool isWeakLinkedClass(const ObjCInterfaceDecl *ID) {
2063 do {
2064 if (ID->isWeakImported())
2065 return true;
2066 } while ((ID = ID->getSuperClass()));
2067
2068 return false;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00002069}
2070
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00002071CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00002072CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
2073 ReturnValueSlot Return,
2074 QualType ResultType,
2075 llvm::Value *Sel,
2076 llvm::Value *Arg0,
2077 QualType Arg0Ty,
2078 bool IsSuper,
2079 const CallArgList &CallArgs,
2080 const ObjCMethodDecl *Method,
John McCall1e3157b2015-09-10 22:27:50 +00002081 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00002082 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc722b852008-08-30 03:02:31 +00002083 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00002084 if (!IsSuper)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00002085 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman43dca6a2011-05-02 17:57:46 +00002086 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
2087 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCall31168b02011-06-15 23:02:42 +00002088 ActualArgs.addFrom(CallArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002089
John McCalla729c622012-02-17 03:33:10 +00002090 // If we're calling a method, use the formal signature.
2091 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002092
Anders Carlsson280e61f12010-06-21 20:59:55 +00002093 if (Method)
Alp Toker314cc812014-01-25 16:55:45 +00002094 assert(CGM.getContext().getCanonicalType(Method->getReturnType()) ==
2095 CGM.getContext().getCanonicalType(ResultType) &&
Anders Carlsson280e61f12010-06-21 20:59:55 +00002096 "Result type mismatch!");
2097
John McCall1e3157b2015-09-10 22:27:50 +00002098 bool ReceiverCanBeNull = true;
2099
2100 // Super dispatch assumes that self is non-null; even the messenger
2101 // doesn't have a null check internally.
2102 if (IsSuper) {
2103 ReceiverCanBeNull = false;
2104
2105 // If this is a direct dispatch of a class method, check whether the class,
2106 // or anything in its hierarchy, was weak-linked.
2107 } else if (ClassReceiver && Method && Method->isClassMethod()) {
2108 ReceiverCanBeNull = isWeakLinkedClass(ClassReceiver);
2109
2110 // If we're emitting a method, and self is const (meaning just ARC, for now),
2111 // and the receiver is a load of self, then self is a valid object.
2112 } else if (auto CurMethod =
2113 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) {
2114 auto Self = CurMethod->getSelfDecl();
2115 if (Self->getType().isConstQualified()) {
2116 if (auto LI = dyn_cast<llvm::LoadInst>(Arg0->stripPointerCasts())) {
2117 llvm::Value *SelfAddr = CGF.GetAddrOfLocalVar(Self).getPointer();
2118 if (SelfAddr == LI->getPointerOperand()) {
2119 ReceiverCanBeNull = false;
2120 }
2121 }
2122 }
2123 }
2124
John McCall5880fb82011-05-14 21:12:11 +00002125 NullReturnState nullReturn;
2126
Craig Topper8a13c412014-05-21 05:09:00 +00002127 llvm::Constant *Fn = nullptr;
Tim Northovere77cc392014-03-29 13:28:05 +00002128 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
John McCall1e3157b2015-09-10 22:27:50 +00002129 if (ReceiverCanBeNull) nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002130 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002131 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00002132 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
2133 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2134 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +00002135 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
2136 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2137 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002138 } else {
Tim Northovere77cc392014-03-29 13:28:05 +00002139 // arm64 uses objc_msgSend for stret methods and yet null receiver check
2140 // must be made for it.
Ahmed Bougachaa3df87b2015-10-02 22:41:59 +00002141 if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
Tim Northovere77cc392014-03-29 13:28:05 +00002142 nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002143 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002144 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002145 }
John McCall1e3157b2015-09-10 22:27:50 +00002146
2147 // Emit a null-check if there's a consumed argument other than the receiver.
2148 bool RequiresNullCheck = false;
2149 if (ReceiverCanBeNull && CGM.getLangOpts().ObjCAutoRefCount && Method) {
David Majnemer59f77922016-06-24 04:05:48 +00002150 for (const auto *ParamDecl : Method->parameters()) {
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002151 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
2152 if (!nullReturn.NullBB)
2153 nullReturn.init(CGF, Arg0);
John McCall1e3157b2015-09-10 22:27:50 +00002154 RequiresNullCheck = true;
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002155 break;
2156 }
2157 }
John McCall1e3157b2015-09-10 22:27:50 +00002158 }
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002159
John McCall1e3157b2015-09-10 22:27:50 +00002160 llvm::Instruction *CallSite;
John McCalla729c622012-02-17 03:33:10 +00002161 Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
John McCallb92ab1a2016-10-26 23:46:34 +00002162 CGCallee Callee = CGCallee::forDirect(Fn);
2163 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2164 &CallSite);
John McCall1e3157b2015-09-10 22:27:50 +00002165
2166 // Mark the call as noreturn if the method is marked noreturn and the
2167 // receiver cannot be null.
2168 if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
2169 llvm::CallSite(CallSite).setDoesNotReturn();
2170 }
2171
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002172 return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
John McCall1e3157b2015-09-10 22:27:50 +00002173 RequiresNullCheck ? Method : nullptr);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002174}
2175
John McCall3fd13f062015-10-21 18:06:47 +00002176static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT,
2177 bool pointee = false) {
2178 // Note that GC qualification applies recursively to C pointer types
2179 // that aren't otherwise decorated. This is weird, but it's probably
2180 // an intentional workaround to the unreliable placement of GC qualifiers.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002181 if (FQT.isObjCGCStrong())
2182 return Qualifiers::Strong;
John McCall3fd13f062015-10-21 18:06:47 +00002183
2184 if (FQT.isObjCGCWeak())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002185 return Qualifiers::Weak;
John McCall3fd13f062015-10-21 18:06:47 +00002186
2187 if (auto ownership = FQT.getObjCLifetime()) {
2188 // Ownership does not apply recursively to C pointer types.
2189 if (pointee) return Qualifiers::GCNone;
2190 switch (ownership) {
2191 case Qualifiers::OCL_Weak: return Qualifiers::Weak;
2192 case Qualifiers::OCL_Strong: return Qualifiers::Strong;
2193 case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone;
2194 case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?");
2195 case Qualifiers::OCL_None: llvm_unreachable("known nonzero");
2196 }
2197 llvm_unreachable("bad objc ownership");
2198 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002199
John McCall3fd13f062015-10-21 18:06:47 +00002200 // Treat unqualified retainable pointers as strong.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002201 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
2202 return Qualifiers::Strong;
2203
John McCall3fd13f062015-10-21 18:06:47 +00002204 // Walk into C pointer types, but only in GC.
2205 if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) {
2206 if (const PointerType *PT = FQT->getAs<PointerType>())
2207 return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true);
2208 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002209
2210 return Qualifiers::GCNone;
2211}
2212
John McCall3fd13f062015-10-21 18:06:47 +00002213namespace {
2214 struct IvarInfo {
2215 CharUnits Offset;
2216 uint64_t SizeInWords;
2217 IvarInfo(CharUnits offset, uint64_t sizeInWords)
2218 : Offset(offset), SizeInWords(sizeInWords) {}
2219
2220 // Allow sorting based on byte pos.
2221 bool operator<(const IvarInfo &other) const {
2222 return Offset < other.Offset;
2223 }
2224 };
2225
2226 /// A helper class for building GC layout strings.
2227 class IvarLayoutBuilder {
2228 CodeGenModule &CGM;
2229
2230 /// The start of the layout. Offsets will be relative to this value,
2231 /// and entries less than this value will be silently discarded.
2232 CharUnits InstanceBegin;
2233
2234 /// The end of the layout. Offsets will never exceed this value.
2235 CharUnits InstanceEnd;
2236
2237 /// Whether we're generating the strong layout or the weak layout.
2238 bool ForStrongLayout;
2239
2240 /// Whether the offsets in IvarsInfo might be out-of-order.
2241 bool IsDisordered = false;
2242
2243 llvm::SmallVector<IvarInfo, 8> IvarsInfo;
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002244
John McCall3fd13f062015-10-21 18:06:47 +00002245 public:
2246 IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
2247 CharUnits instanceEnd, bool forStrongLayout)
2248 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2249 ForStrongLayout(forStrongLayout) {
2250 }
2251
2252 void visitRecord(const RecordType *RT, CharUnits offset);
2253
2254 template <class Iterator, class GetOffsetFn>
2255 void visitAggregate(Iterator begin, Iterator end,
2256 CharUnits aggrOffset,
2257 const GetOffsetFn &getOffset);
2258
2259 void visitField(const FieldDecl *field, CharUnits offset);
2260
2261 /// Add the layout of a block implementation.
2262 void visitBlock(const CGBlockInfo &blockInfo);
2263
2264 /// Is there any information for an interesting bitmap?
2265 bool hasBitmapData() const { return !IvarsInfo.empty(); }
2266
2267 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2268 llvm::SmallVectorImpl<unsigned char> &buffer);
2269
2270 static void dump(ArrayRef<unsigned char> buffer) {
2271 const unsigned char *s = buffer.data();
2272 for (unsigned i = 0, e = buffer.size(); i < e; i++)
2273 if (!(s[i] & 0xf0))
2274 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
2275 else
2276 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
2277 printf("\n");
2278 }
2279 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002280} // end anonymous namespace
John McCall3fd13f062015-10-21 18:06:47 +00002281
John McCall351762c2011-02-07 10:33:21 +00002282llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
2283 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002284
Chris Lattnerece04092012-02-07 00:39:47 +00002285 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
John McCall460ce582015-10-22 18:38:17 +00002286 if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
John McCall351762c2011-02-07 10:33:21 +00002287 return nullPtr;
2288
John McCall3fd13f062015-10-21 18:06:47 +00002289 IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize,
2290 /*for strong layout*/ true);
2291
2292 builder.visitBlock(blockInfo);
2293
2294 if (!builder.hasBitmapData())
2295 return nullPtr;
2296
2297 llvm::SmallVector<unsigned char, 32> buffer;
2298 llvm::Constant *C = builder.buildBitmap(*this, buffer);
John McCallf5ea0722015-10-29 23:36:14 +00002299 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
John McCall3fd13f062015-10-21 18:06:47 +00002300 printf("\n block variable layout for block: ");
2301 builder.dump(buffer);
2302 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002303
John McCall3fd13f062015-10-21 18:06:47 +00002304 return C;
2305}
2306
2307void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00002308 // __isa is the first field in block descriptor and must assume by runtime's
2309 // convention that it is GC'able.
John McCall3fd13f062015-10-21 18:06:47 +00002310 IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1));
John McCall351762c2011-02-07 10:33:21 +00002311
2312 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2313
John McCall351762c2011-02-07 10:33:21 +00002314 // Ignore the optional 'this' capture: C++ objects are not assumed
2315 // to be GC'ed.
2316
John McCall3fd13f062015-10-21 18:06:47 +00002317 CharUnits lastFieldOffset;
2318
John McCall351762c2011-02-07 10:33:21 +00002319 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002320 for (const auto &CI : blockDecl->captures()) {
2321 const VarDecl *variable = CI.getVariable();
John McCall351762c2011-02-07 10:33:21 +00002322 QualType type = variable->getType();
2323
2324 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2325
2326 // Ignore constant captures.
2327 if (capture.isConstant()) continue;
2328
John McCall3fd13f062015-10-21 18:06:47 +00002329 CharUnits fieldOffset = capture.getOffset();
2330
2331 // Block fields are not necessarily ordered; if we detect that we're
2332 // adding them out-of-order, make sure we sort later.
2333 if (fieldOffset < lastFieldOffset)
2334 IsDisordered = true;
2335 lastFieldOffset = fieldOffset;
John McCall351762c2011-02-07 10:33:21 +00002336
2337 // __block variables are passed by their descriptor address.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002338 if (CI.isByRef()) {
John McCall3fd13f062015-10-21 18:06:47 +00002339 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00002340 continue;
John McCall351762c2011-02-07 10:33:21 +00002341 }
2342
2343 assert(!type->isArrayType() && "array variable should not be caught");
2344 if (const RecordType *record = type->getAs<RecordType>()) {
John McCall3fd13f062015-10-21 18:06:47 +00002345 visitRecord(record, fieldOffset);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00002346 continue;
2347 }
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00002348
John McCall351762c2011-02-07 10:33:21 +00002349 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
John McCall351762c2011-02-07 10:33:21 +00002350
John McCall3fd13f062015-10-21 18:06:47 +00002351 if (GCAttr == Qualifiers::Strong) {
2352 assert(CGM.getContext().getTypeSize(type)
2353 == CGM.getTarget().getPointerWidth(0));
2354 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
2355 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002356 }
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00002357}
2358
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00002359/// getBlockCaptureLifetime - This routine returns life time of the captured
2360/// block variable for the purpose of block layout meta-data generation. FQT is
2361/// the type of the variable captured in the block.
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002362Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
2363 bool ByrefLayout) {
John McCall460ce582015-10-22 18:38:17 +00002364 // If it has an ownership qualifier, we're done.
2365 if (auto lifetime = FQT.getObjCLifetime())
2366 return lifetime;
2367
2368 // If it doesn't, and this is ARC, it has no ownership.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002369 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCall460ce582015-10-22 18:38:17 +00002370 return Qualifiers::OCL_None;
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002371
John McCall460ce582015-10-22 18:38:17 +00002372 // In MRC, retainable pointers are owned by non-__block variables.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002373 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002374 return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002375
2376 return Qualifiers::OCL_None;
2377}
2378
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002379void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
2380 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002381 CharUnits FieldOffset,
2382 CharUnits FieldSize) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002383 // __block variables are passed by their descriptor address.
2384 if (IsByref)
2385 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002386 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002387 else if (LifeTime == Qualifiers::OCL_Strong)
2388 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002389 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002390 else if (LifeTime == Qualifiers::OCL_Weak)
2391 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002392 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002393 else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2394 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002395 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002396 else
2397 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2398 FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002399 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002400}
2401
2402void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2403 const RecordDecl *RD,
2404 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002405 CharUnits BytePos, bool &HasUnion,
2406 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002407 bool IsUnion = (RD && RD->isUnion());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002408 CharUnits MaxUnionSize = CharUnits::Zero();
Craig Topper8a13c412014-05-21 05:09:00 +00002409 const FieldDecl *MaxField = nullptr;
2410 const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002411 CharUnits MaxFieldOffset = CharUnits::Zero();
2412 CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002413
2414 if (RecFields.empty())
2415 return;
John McCallc8e01702013-04-16 22:48:15 +00002416 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002417
2418 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2419 const FieldDecl *Field = RecFields[i];
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002420 // Note that 'i' here is actually the field index inside RD of Field,
2421 // although this dependency is hidden.
2422 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002423 CharUnits FieldOffset =
2424 CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002425
2426 // Skip over unnamed or bitfields
2427 if (!Field->getIdentifier() || Field->isBitField()) {
2428 LastFieldBitfieldOrUnnamed = Field;
2429 LastBitfieldOrUnnamedOffset = FieldOffset;
2430 continue;
2431 }
Craig Topper8a13c412014-05-21 05:09:00 +00002432
2433 LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002434 QualType FQT = Field->getType();
2435 if (FQT->isRecordType() || FQT->isUnionType()) {
2436 if (FQT->isUnionType())
2437 HasUnion = true;
2438
2439 BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
2440 BytePos + FieldOffset, HasUnion);
2441 continue;
2442 }
2443
2444 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2445 const ConstantArrayType *CArray =
2446 dyn_cast_or_null<ConstantArrayType>(Array);
2447 uint64_t ElCount = CArray->getSize().getZExtValue();
2448 assert(CArray && "only array with known element size is supported");
2449 FQT = CArray->getElementType();
2450 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2451 const ConstantArrayType *CArray =
2452 dyn_cast_or_null<ConstantArrayType>(Array);
2453 ElCount *= CArray->getSize().getZExtValue();
2454 FQT = CArray->getElementType();
2455 }
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002456 if (FQT->isRecordType() && ElCount) {
2457 int OldIndex = RunSkipBlockVars.size() - 1;
2458 const RecordType *RT = FQT->getAs<RecordType>();
2459 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
2460 HasUnion);
2461
2462 // Replicate layout information for each array element. Note that
2463 // one element is already done.
2464 uint64_t ElIx = 1;
2465 for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002466 CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002467 for (int i = OldIndex+1; i <= FirstIndex; ++i)
2468 RunSkipBlockVars.push_back(
2469 RUN_SKIP(RunSkipBlockVars[i].opcode,
2470 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2471 RunSkipBlockVars[i].block_var_size));
2472 }
2473 continue;
2474 }
2475 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002476 CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002477 if (IsUnion) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002478 CharUnits UnionIvarSize = FieldSize;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002479 if (UnionIvarSize > MaxUnionSize) {
2480 MaxUnionSize = UnionIvarSize;
2481 MaxField = Field;
2482 MaxFieldOffset = FieldOffset;
2483 }
2484 } else {
2485 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002486 getBlockCaptureLifetime(FQT, ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002487 BytePos + FieldOffset,
2488 FieldSize);
2489 }
2490 }
2491
2492 if (LastFieldBitfieldOrUnnamed) {
2493 if (LastFieldBitfieldOrUnnamed->isBitField()) {
2494 // Last field was a bitfield. Must update the info.
2495 uint64_t BitFieldSize
2496 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002497 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
Eli Friedman8cbca202012-11-06 22:15:52 +00002498 ((BitFieldSize % ByteSizeInBits) != 0);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002499 CharUnits Size = CharUnits::fromQuantity(UnsSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002500 Size += LastBitfieldOrUnnamedOffset;
2501 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002502 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2503 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002504 BytePos + LastBitfieldOrUnnamedOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002505 Size);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002506 } else {
2507 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2508 // Last field was unnamed. Must update skip info.
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002509 CharUnits FieldSize
2510 = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002511 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002512 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2513 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002514 BytePos + LastBitfieldOrUnnamedOffset,
2515 FieldSize);
2516 }
2517 }
2518
2519 if (MaxField)
2520 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002521 getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002522 BytePos + MaxFieldOffset,
2523 MaxUnionSize);
2524}
2525
2526void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002527 CharUnits BytePos,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002528 bool &HasUnion,
2529 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002530 const RecordDecl *RD = RT->getDecl();
Aaron Ballman62e47c42014-03-10 13:43:55 +00002531 SmallVector<const FieldDecl*, 16> Fields(RD->fields());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002532 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
2533 const llvm::StructLayout *RecLayout =
2534 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2535
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002536 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002537}
2538
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002539/// InlineLayoutInstruction - This routine produce an inline instruction for the
2540/// block variable layout if it can. If not, it returns 0. Rules are as follow:
2541/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
2542/// an inline layout of value 0x0000000000000xyz is interpreted as follows:
2543/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
2544/// y captured object of BLOCK_LAYOUT_BYREF. Followed by
2545/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
2546/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
2547/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
2548uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2549 SmallVectorImpl<unsigned char> &Layout) {
2550 uint64_t Result = 0;
2551 if (Layout.size() <= 3) {
2552 unsigned size = Layout.size();
2553 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2554 unsigned char inst;
2555 enum BLOCK_LAYOUT_OPCODE opcode ;
2556 switch (size) {
2557 case 3:
2558 inst = Layout[0];
2559 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2560 if (opcode == BLOCK_LAYOUT_STRONG)
2561 strong_word_count = (inst & 0xF)+1;
2562 else
2563 return 0;
2564 inst = Layout[1];
2565 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2566 if (opcode == BLOCK_LAYOUT_BYREF)
2567 byref_word_count = (inst & 0xF)+1;
2568 else
2569 return 0;
2570 inst = Layout[2];
2571 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2572 if (opcode == BLOCK_LAYOUT_WEAK)
2573 weak_word_count = (inst & 0xF)+1;
2574 else
2575 return 0;
2576 break;
2577
2578 case 2:
2579 inst = Layout[0];
2580 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2581 if (opcode == BLOCK_LAYOUT_STRONG) {
2582 strong_word_count = (inst & 0xF)+1;
2583 inst = Layout[1];
2584 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2585 if (opcode == BLOCK_LAYOUT_BYREF)
2586 byref_word_count = (inst & 0xF)+1;
2587 else if (opcode == BLOCK_LAYOUT_WEAK)
2588 weak_word_count = (inst & 0xF)+1;
2589 else
2590 return 0;
2591 }
2592 else if (opcode == BLOCK_LAYOUT_BYREF) {
2593 byref_word_count = (inst & 0xF)+1;
2594 inst = Layout[1];
2595 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2596 if (opcode == BLOCK_LAYOUT_WEAK)
2597 weak_word_count = (inst & 0xF)+1;
2598 else
2599 return 0;
2600 }
2601 else
2602 return 0;
2603 break;
2604
2605 case 1:
2606 inst = Layout[0];
2607 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2608 if (opcode == BLOCK_LAYOUT_STRONG)
2609 strong_word_count = (inst & 0xF)+1;
2610 else if (opcode == BLOCK_LAYOUT_BYREF)
2611 byref_word_count = (inst & 0xF)+1;
2612 else if (opcode == BLOCK_LAYOUT_WEAK)
2613 weak_word_count = (inst & 0xF)+1;
2614 else
2615 return 0;
2616 break;
2617
2618 default:
2619 return 0;
2620 }
2621
2622 // Cannot inline when any of the word counts is 15. Because this is one less
2623 // than the actual work count (so 15 means 16 actual word counts),
2624 // and we can only display 0 thru 15 word counts.
2625 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2626 return 0;
2627
2628 unsigned count =
2629 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2630
2631 if (size == count) {
2632 if (strong_word_count)
2633 Result = strong_word_count;
2634 Result <<= 4;
2635 if (byref_word_count)
2636 Result += byref_word_count;
2637 Result <<= 4;
2638 if (weak_word_count)
2639 Result += weak_word_count;
2640 }
2641 }
2642 return Result;
2643}
2644
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002645llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
2646 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2647 if (RunSkipBlockVars.empty())
2648 return nullPtr;
John McCallc8e01702013-04-16 22:48:15 +00002649 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2650 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002651 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2652
2653 // Sort on byte position; captures might not be allocated in order,
2654 // and unions can do funny things.
2655 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2656 SmallVector<unsigned char, 16> Layout;
2657
2658 unsigned size = RunSkipBlockVars.size();
2659 for (unsigned i = 0; i < size; i++) {
2660 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2661 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2662 CharUnits end_byte_pos = start_byte_pos;
2663 unsigned j = i+1;
2664 while (j < size) {
2665 if (opcode == RunSkipBlockVars[j].opcode) {
2666 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2667 i++;
2668 }
2669 else
2670 break;
2671 }
2672 CharUnits size_in_bytes =
2673 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2674 if (j < size) {
2675 CharUnits gap =
2676 RunSkipBlockVars[j].block_var_bytepos -
2677 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2678 size_in_bytes += gap;
2679 }
2680 CharUnits residue_in_bytes = CharUnits::Zero();
2681 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2682 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2683 size_in_bytes -= residue_in_bytes;
2684 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2685 }
2686
2687 unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
2688 while (size_in_words >= 16) {
2689 // Note that value in imm. is one less that the actual
2690 // value. So, 0xf means 16 words follow!
2691 unsigned char inst = (opcode << 4) | 0xf;
2692 Layout.push_back(inst);
2693 size_in_words -= 16;
2694 }
2695 if (size_in_words > 0) {
2696 // Note that value in imm. is one less that the actual
2697 // value. So, we subtract 1 away!
2698 unsigned char inst = (opcode << 4) | (size_in_words-1);
2699 Layout.push_back(inst);
2700 }
2701 if (residue_in_bytes > CharUnits::Zero()) {
2702 unsigned char inst =
2703 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
2704 Layout.push_back(inst);
2705 }
2706 }
2707
John McCall7f416cc2015-09-08 08:05:57 +00002708 while (!Layout.empty()) {
2709 unsigned char inst = Layout.back();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002710 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2711 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2712 Layout.pop_back();
2713 else
2714 break;
2715 }
2716
2717 uint64_t Result = InlineLayoutInstruction(Layout);
2718 if (Result != 0) {
2719 // Block variable layout instruction has been inlined.
2720 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2721 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002722 printf("\n Inline BYREF variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002723 else
John McCall7f416cc2015-09-08 08:05:57 +00002724 printf("\n Inline block variable layout: ");
2725 printf("0x0%" PRIx64 "", Result);
2726 if (auto numStrong = (Result & 0xF00) >> 8)
2727 printf(", BL_STRONG:%d", (int) numStrong);
2728 if (auto numByref = (Result & 0x0F0) >> 4)
2729 printf(", BL_BYREF:%d", (int) numByref);
2730 if (auto numWeak = (Result & 0x00F) >> 0)
2731 printf(", BL_WEAK:%d", (int) numWeak);
2732 printf(", BL_OPERATOR:0\n");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002733 }
Vedant Kumar3ed0df02015-12-21 19:43:25 +00002734 return llvm::ConstantInt::get(CGM.IntPtrTy, Result);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002735 }
2736
2737 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2738 Layout.push_back(inst);
2739 std::string BitMap;
2740 for (unsigned i = 0, e = Layout.size(); i != e; i++)
2741 BitMap += Layout[i];
2742
2743 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2744 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002745 printf("\n Byref variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002746 else
John McCall7f416cc2015-09-08 08:05:57 +00002747 printf("\n Block variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002748 for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
2749 unsigned char inst = BitMap[i];
2750 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2751 unsigned delta = 1;
2752 switch (opcode) {
2753 case BLOCK_LAYOUT_OPERATOR:
2754 printf("BL_OPERATOR:");
2755 delta = 0;
2756 break;
2757 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2758 printf("BL_NON_OBJECT_BYTES:");
2759 break;
2760 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2761 printf("BL_NON_OBJECT_WORD:");
2762 break;
2763 case BLOCK_LAYOUT_STRONG:
2764 printf("BL_STRONG:");
2765 break;
2766 case BLOCK_LAYOUT_BYREF:
2767 printf("BL_BYREF:");
2768 break;
2769 case BLOCK_LAYOUT_WEAK:
2770 printf("BL_WEAK:");
2771 break;
2772 case BLOCK_LAYOUT_UNRETAINED:
2773 printf("BL_UNRETAINED:");
2774 break;
2775 }
2776 // Actual value of word count is one more that what is in the imm.
2777 // field of the instruction
2778 printf("%d", (inst & 0xf) + delta);
2779 if (i < e-1)
2780 printf(", ");
2781 else
2782 printf("\n");
2783 }
2784 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00002785
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00002786 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2787 /*ForceNonFragileABI=*/true,
2788 /*NullTerminate=*/false);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002789 return getConstantGEP(VMContext, Entry, 0, 0);
2790}
2791
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002792llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2793 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002794 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2795
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002796 RunSkipBlockVars.clear();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002797 bool hasUnion = false;
2798
John McCallc8e01702013-04-16 22:48:15 +00002799 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2800 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002801 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2802
2803 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2804
2805 // Calculate the basic layout of the block structure.
2806 const llvm::StructLayout *layout =
2807 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
2808
2809 // Ignore the optional 'this' capture: C++ objects are not assumed
2810 // to be GC'ed.
Fariborz Jahanian4cf177e2012-12-04 17:20:57 +00002811 if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
2812 UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
2813 blockInfo.BlockHeaderForcedGapOffset,
2814 blockInfo.BlockHeaderForcedGapSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002815 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002816 for (const auto &CI : blockDecl->captures()) {
2817 const VarDecl *variable = CI.getVariable();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002818 QualType type = variable->getType();
2819
2820 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2821
2822 // Ignore constant captures.
2823 if (capture.isConstant()) continue;
2824
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002825 CharUnits fieldOffset =
2826 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002827
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002828 assert(!type->isArrayType() && "array variable should not be caught");
Aaron Ballman9371dd22014-03-14 18:34:04 +00002829 if (!CI.isByRef())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002830 if (const RecordType *record = type->getAs<RecordType>()) {
2831 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2832 continue;
2833 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002834 CharUnits fieldSize;
Aaron Ballman9371dd22014-03-14 18:34:04 +00002835 if (CI.isByRef())
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002836 fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2837 else
2838 fieldSize = CGM.getContext().getTypeSizeInChars(type);
Aaron Ballman9371dd22014-03-14 18:34:04 +00002839 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002840 fieldOffset, fieldSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002841 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002842 return getBitmapBlockLayout(false);
2843}
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002844
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002845llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2846 QualType T) {
2847 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2848 assert(!T->isArrayType() && "__block array variable should not be caught");
2849 CharUnits fieldOffset;
2850 RunSkipBlockVars.clear();
2851 bool hasUnion = false;
2852 if (const RecordType *record = T->getAs<RecordType>()) {
2853 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
2854 llvm::Constant *Result = getBitmapBlockLayout(true);
Vedant Kumar2f5bb1152015-12-21 20:21:15 +00002855 if (isa<llvm::ConstantInt>(Result))
2856 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002857 return Result;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002858 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002859 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2860 return nullPtr;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002861}
2862
John McCall882987f2013-02-28 19:01:20 +00002863llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00002864 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00002865 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002866 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00002867 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2868
Owen Andersonade90fd2009-07-29 18:54:39 +00002869 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00002870 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002871}
2872
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002873void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00002874 // FIXME: We shouldn't need this, the protocol decl should contain enough
2875 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00002876 DefinedProtocols.insert(PD->getIdentifier());
2877
2878 // If we have generated a forward reference to this protocol, emit
2879 // it now. Otherwise do nothing, the protocol objects are lazily
2880 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002881 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00002882 GetOrEmitProtocol(PD);
2883}
2884
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002885llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002886 if (DefinedProtocols.count(PD->getIdentifier()))
2887 return GetOrEmitProtocol(PD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002888
Daniel Dunbarc475d422008-10-29 22:36:39 +00002889 return GetOrEmitProtocolRef(PD);
2890}
2891
Douglas Gregor24ae22c2016-04-01 23:23:52 +00002892llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
2893 CodeGenFunction &CGF,
2894 const ObjCInterfaceDecl *ID,
2895 ObjCCommonTypesHelper &ObjCTypes) {
2896 llvm::Constant *lookUpClassFn = ObjCTypes.getLookUpClassFn();
2897
2898 llvm::Value *className =
2899 CGF.CGM.GetAddrOfConstantCString(ID->getObjCRuntimeNameAsString())
2900 .getPointer();
2901 ASTContext &ctx = CGF.CGM.getContext();
2902 className =
2903 CGF.Builder.CreateBitCast(className,
2904 CGF.ConvertType(
2905 ctx.getPointerType(ctx.CharTy.withConst())));
2906 llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className);
2907 call->setDoesNotThrow();
2908 return call;
2909}
2910
Daniel Dunbarb036db82008-08-13 03:21:16 +00002911/*
Rafael Espindolaf9e1e5e2014-02-20 14:09:04 +00002912// Objective-C 1.0 extensions
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002913struct _objc_protocol {
2914struct _objc_protocol_extension *isa;
2915char *protocol_name;
2916struct _objc_protocol_list *protocol_list;
2917struct _objc__method_prototype_list *instance_methods;
2918struct _objc__method_prototype_list *class_methods
2919};
Daniel Dunbarb036db82008-08-13 03:21:16 +00002920
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002921See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00002922*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00002923llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00002924 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbarc475d422008-10-29 22:36:39 +00002925
2926 // Early exit if a defining object has already been generated.
2927 if (Entry && Entry->hasInitializer())
2928 return Entry;
2929
Douglas Gregora715bff2012-01-01 19:51:50 +00002930 // Use the protocol definition, if there is one.
2931 if (const ObjCProtocolDecl *Def = PD->getDefinition())
2932 PD = Def;
2933
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002934 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002935 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002936 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2937
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002938 // Construct method lists.
John McCall176f8922016-11-30 02:39:18 +00002939 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002940
John McCall176f8922016-11-30 02:39:18 +00002941 ConstantInitBuilder builder(CGM);
2942 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
2943 values.add(EmitProtocolExtension(PD, methodLists));
2944 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
2945 values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
2946 PD->protocol_begin(), PD->protocol_end()));
2947 values.add(methodLists.emitMethodList(this, PD,
2948 ProtocolMethodLists::RequiredInstanceMethods));
2949 values.add(methodLists.emitMethodList(this, PD,
2950 ProtocolMethodLists::RequiredClassMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002951
Daniel Dunbarb036db82008-08-13 03:21:16 +00002952 if (Entry) {
Rafael Espindola5d117f32014-03-06 01:10:46 +00002953 // Already created, update the initializer.
Rafael Espindolab3262952014-05-09 00:43:37 +00002954 assert(Entry->hasPrivateLinkage());
John McCall176f8922016-11-30 02:39:18 +00002955 values.finishAndSetAsInitializer(Entry);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002956 } else {
John McCall176f8922016-11-30 02:39:18 +00002957 Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(),
2958 CGM.getPointerAlign(),
2959 /*constant*/ false,
2960 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002961 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
John McCallf9582a72012-03-30 21:29:05 +00002962
2963 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002964 }
Rafael Espindola060062a2014-03-06 22:15:10 +00002965 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00002966
2967 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002968}
2969
Daniel Dunbarc475d422008-10-29 22:36:39 +00002970llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002971 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
2972
2973 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002974 // We use the initializer as a marker of whether this is a forward
2975 // reference or not. At module finalization we add the empty
2976 // contents for protocols which were referenced but never defined.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00002977 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
2978 false, llvm::GlobalValue::PrivateLinkage,
2979 nullptr, "OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002980 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002981 // FIXME: Is this necessary? Why only for protocol?
2982 Entry->setAlignment(4);
2983 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002984
Daniel Dunbarb036db82008-08-13 03:21:16 +00002985 return Entry;
2986}
2987
2988/*
2989 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002990 uint32_t size;
2991 struct objc_method_description_list *optional_instance_methods;
2992 struct objc_method_description_list *optional_class_methods;
2993 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002994 const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00002995 struct objc_property_list *class_properties;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002996 };
2997*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002998llvm::Constant *
2999CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00003000 const ProtocolMethodLists &methodLists) {
3001 auto optInstanceMethods =
3002 methodLists.emitMethodList(this, PD,
3003 ProtocolMethodLists::OptionalInstanceMethods);
3004 auto optClassMethods =
3005 methodLists.emitMethodList(this, PD,
3006 ProtocolMethodLists::OptionalClassMethods);
3007
3008 auto extendedMethodTypes =
3009 EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
3010 methodLists.emitExtendedTypesArray(this),
3011 ObjCTypes);
3012
3013 auto instanceProperties =
3014 EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD,
3015 ObjCTypes, false);
3016 auto classProperties =
3017 EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr,
3018 PD, ObjCTypes, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003019
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003020 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00003021 if (optInstanceMethods->isNullValue() &&
3022 optClassMethods->isNullValue() &&
3023 extendedMethodTypes->isNullValue() &&
3024 instanceProperties->isNullValue() &&
3025 classProperties->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003026 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003027 }
Daniel Dunbarb036db82008-08-13 03:21:16 +00003028
John McCall176f8922016-11-30 02:39:18 +00003029 uint64_t size =
3030 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3031
3032 ConstantInitBuilder builder(CGM);
3033 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3034 values.addInt(ObjCTypes.IntTy, size);
3035 values.add(optInstanceMethods);
3036 values.add(optClassMethods);
3037 values.add(instanceProperties);
3038 values.add(extendedMethodTypes);
3039 values.add(classProperties);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003040
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003041 // No special section, but goes in llvm.used
John McCall176f8922016-11-30 02:39:18 +00003042 return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00003043 StringRef(), CGM.getPointerAlign(), true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003044}
3045
3046/*
3047 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00003048 struct objc_protocol_list *next;
3049 long count;
3050 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00003051 };
3052*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00003053llvm::Constant *
John McCall176f8922016-11-30 02:39:18 +00003054CGObjCMac::EmitProtocolList(Twine name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00003055 ObjCProtocolDecl::protocol_iterator begin,
3056 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003057 // Just return null for empty protocol lists
John McCall176f8922016-11-30 02:39:18 +00003058 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00003059 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003060
John McCall176f8922016-11-30 02:39:18 +00003061 ConstantInitBuilder builder(CGM);
3062 auto values = builder.beginStruct();
Daniel Dunbarb036db82008-08-13 03:21:16 +00003063
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003064 // This field is only used by the runtime.
John McCall176f8922016-11-30 02:39:18 +00003065 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003066
John McCall176f8922016-11-30 02:39:18 +00003067 // Reserve a slot for the count.
3068 auto countSlot = values.addPlaceholder();
3069
3070 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3071 for (; begin != end; ++begin) {
3072 refsArray.add(GetProtocolRef(*begin));
3073 }
3074 auto count = refsArray.size();
3075
3076 // This list is null terminated.
3077 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3078
3079 refsArray.finishAndAddTo(values);
3080 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3081
3082 StringRef section;
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003083 if (CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00003084 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003085
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003086 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003087 CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false);
Owen Andersonade90fd2009-07-29 18:54:39 +00003088 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003089}
3090
John McCall176f8922016-11-30 02:39:18 +00003091static void
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003092PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
John McCall176f8922016-11-30 02:39:18 +00003093 SmallVectorImpl<const ObjCPropertyDecl *> &Properties,
Aaron Ballmandc4bea42014-03-13 18:47:37 +00003094 const ObjCProtocolDecl *Proto,
Manman Renad0e7912016-01-29 19:22:54 +00003095 bool IsClassProperty) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00003096 for (const auto *P : Proto->protocols())
John McCall176f8922016-11-30 02:39:18 +00003097 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Manman Renad0e7912016-01-29 19:22:54 +00003098
3099 for (const auto *PD : Proto->properties()) {
3100 if (IsClassProperty != PD->isClassProperty())
3101 continue;
David Blaikie82e95a32014-11-19 07:49:47 +00003102 if (!PropertySet.insert(PD->getIdentifier()).second)
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003103 continue;
John McCall176f8922016-11-30 02:39:18 +00003104 Properties.push_back(PD);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003105 }
3106}
3107
Daniel Dunbarb036db82008-08-13 03:21:16 +00003108/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003109 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00003110 const char * const name;
3111 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003112 };
3113
3114 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00003115 uint32_t entsize; // sizeof (struct _objc_property)
3116 uint32_t prop_count;
3117 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003118 };
3119*/
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003120llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003121 const Decl *Container,
3122 const ObjCContainerDecl *OCD,
Manman Renad0e7912016-01-29 19:22:54 +00003123 const ObjCCommonTypesHelper &ObjCTypes,
3124 bool IsClassProperty) {
Manman Ren01b705e2016-04-19 19:05:03 +00003125 if (IsClassProperty) {
3126 // Make this entry NULL for OS X with deployment target < 10.11, for iOS
3127 // with deployment target < 9.0.
3128 const llvm::Triple &Triple = CGM.getTarget().getTriple();
3129 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3130 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3131 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3132 }
3133
John McCall176f8922016-11-30 02:39:18 +00003134 SmallVector<const ObjCPropertyDecl *, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003135 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Nico Weber08c93332015-12-03 17:44:51 +00003136
Nico Weber08c93332015-12-03 17:44:51 +00003137 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3138 for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
Manman Renad0e7912016-01-29 19:22:54 +00003139 for (auto *PD : ClassExt->properties()) {
3140 if (IsClassProperty != PD->isClassProperty())
3141 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003142 PropertySet.insert(PD->getIdentifier());
John McCall176f8922016-11-30 02:39:18 +00003143 Properties.push_back(PD);
Nico Weber08c93332015-12-03 17:44:51 +00003144 }
Manman Renad0e7912016-01-29 19:22:54 +00003145
3146 for (const auto *PD : OCD->properties()) {
3147 if (IsClassProperty != PD->isClassProperty())
3148 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003149 // Don't emit duplicate metadata for properties that were already in a
3150 // class extension.
3151 if (!PropertySet.insert(PD->getIdentifier()).second)
3152 continue;
John McCall176f8922016-11-30 02:39:18 +00003153 Properties.push_back(PD);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003154 }
Nico Weber08c93332015-12-03 17:44:51 +00003155
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003156 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003157 for (const auto *P : OID->all_referenced_protocols())
John McCall176f8922016-11-30 02:39:18 +00003158 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003159 }
3160 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
Aaron Ballman19a41762014-03-14 12:55:57 +00003161 for (const auto *P : CD->protocols())
John McCall176f8922016-11-30 02:39:18 +00003162 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003163 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003164
3165 // Return null for empty list.
3166 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003167 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003168
John McCall176f8922016-11-30 02:39:18 +00003169 unsigned propertySize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00003170 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
John McCall176f8922016-11-30 02:39:18 +00003171
3172 ConstantInitBuilder builder(CGM);
3173 auto values = builder.beginStruct();
3174 values.addInt(ObjCTypes.IntTy, propertySize);
3175 values.addInt(ObjCTypes.IntTy, Properties.size());
3176 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3177 for (auto PD : Properties) {
3178 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3179 property.add(GetPropertyName(PD->getIdentifier()));
3180 property.add(GetPropertyTypeString(PD, Container));
3181 property.finishAndAddTo(propertiesArray);
3182 }
3183 propertiesArray.finishAndAddTo(values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003184
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003185 StringRef Section;
3186 if (CGM.getTriple().isOSBinFormatMachO())
3187 Section = (ObjCABI == 2) ? "__DATA, __objc_const"
3188 : "__OBJC,__property,regular,no_dead_strip";
3189
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003190 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003191 CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003192 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003193}
3194
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003195llvm::Constant *
3196CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
3197 ArrayRef<llvm::Constant*> MethodTypes,
3198 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003199 // Return null for empty list.
3200 if (MethodTypes.empty())
3201 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3202
3203 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3204 MethodTypes.size());
3205 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
3206
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003207 StringRef Section;
3208 if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3209 Section = "__DATA, __objc_const";
3210
3211 llvm::GlobalVariable *GV =
3212 CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003213 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
3214}
3215
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003216/*
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003217 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003218 char *category_name;
3219 char *class_name;
3220 struct _objc_method_list *instance_methods;
3221 struct _objc_method_list *class_methods;
3222 struct _objc_protocol_list *protocols;
3223 uint32_t size; // <rdar://4585769>
3224 struct _objc_property_list *instance_properties;
Manman Ren96df0b32016-01-29 23:45:01 +00003225 struct _objc_property_list *class_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003226 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003227*/
Daniel Dunbar92992502008-08-15 22:20:32 +00003228void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00003229 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003230
Mike Stump18bb9282009-05-16 07:57:57 +00003231 // FIXME: This is poor design, the OCD should have a pointer to the category
3232 // decl. Additionally, note that Category can be null for the @implementation
3233 // w/o an @interface case. Sema should just create one for us as it does for
3234 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003235 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003236 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003237 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003238
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003239 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003240 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
3241 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003242
John McCall176f8922016-11-30 02:39:18 +00003243 ConstantInitBuilder Builder(CGM);
3244 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
Aaron Ballmanf26acce2014-03-13 19:50:17 +00003245
John McCall176f8922016-11-30 02:39:18 +00003246 enum {
3247 InstanceMethods,
3248 ClassMethods,
3249 NumMethodLists
3250 };
3251 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3252 for (const auto *MD : OCD->methods()) {
3253 Methods[unsigned(MD->isClassMethod())].push_back(MD);
3254 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003255
John McCall176f8922016-11-30 02:39:18 +00003256 Values.add(GetClassName(OCD->getName()));
3257 Values.add(GetClassName(Interface->getObjCRuntimeNameAsString()));
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00003258 LazySymbols.insert(Interface->getIdentifier());
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003259
John McCall176f8922016-11-30 02:39:18 +00003260 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3261 Methods[InstanceMethods]));
3262 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3263 Methods[ClassMethods]));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003264 if (Category) {
John McCall176f8922016-11-30 02:39:18 +00003265 Values.add(
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003266 EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003267 Category->protocol_begin(), Category->protocol_end()));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003268 } else {
John McCall176f8922016-11-30 02:39:18 +00003269 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003270 }
John McCall176f8922016-11-30 02:39:18 +00003271 Values.addInt(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003272
3273 // If there is no category @interface then there can be no properties.
3274 if (Category) {
John McCall176f8922016-11-30 02:39:18 +00003275 Values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
3276 OCD, Category, ObjCTypes, false));
3277 Values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
3278 OCD, Category, ObjCTypes, true));
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003279 } else {
John McCall176f8922016-11-30 02:39:18 +00003280 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3281 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003282 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003283
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003284 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003285 CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values,
John McCall7f416cc2015-09-08 08:05:57 +00003286 "__OBJC,__category,regular,no_dead_strip",
3287 CGM.getPointerAlign(), true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003288 DefinedCategories.push_back(GV);
Justin Lebar5e83dfe2016-10-21 21:45:01 +00003289 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003290 // method definition entries must be clear for next implementation.
3291 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003292}
3293
John McCallef19dbb2012-10-17 04:53:23 +00003294enum FragileClassFlags {
John McCall460ce582015-10-22 18:38:17 +00003295 /// Apparently: is not a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003296 FragileABI_Class_Factory = 0x00001,
John McCall460ce582015-10-22 18:38:17 +00003297
3298 /// Is a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003299 FragileABI_Class_Meta = 0x00002,
John McCall460ce582015-10-22 18:38:17 +00003300
3301 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003302 FragileABI_Class_HasCXXStructors = 0x02000,
John McCall460ce582015-10-22 18:38:17 +00003303
3304 /// Has hidden visibility.
John McCall09ec1ec2015-10-21 22:06:03 +00003305 FragileABI_Class_Hidden = 0x20000,
John McCall460ce582015-10-22 18:38:17 +00003306
3307 /// Class implementation was compiled under ARC.
3308 FragileABI_Class_CompiledByARC = 0x04000000,
3309
3310 /// Class implementation was compiled under MRC and has MRC weak ivars.
3311 /// Exclusive with CompiledByARC.
3312 FragileABI_Class_HasMRCWeakIvars = 0x08000000,
John McCallef19dbb2012-10-17 04:53:23 +00003313};
3314
3315enum NonFragileClassFlags {
3316 /// Is a meta-class.
3317 NonFragileABI_Class_Meta = 0x00001,
3318
3319 /// Is a root class.
3320 NonFragileABI_Class_Root = 0x00002,
3321
John McCall460ce582015-10-22 18:38:17 +00003322 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003323 NonFragileABI_Class_HasCXXStructors = 0x00004,
3324
3325 /// Has hidden visibility.
3326 NonFragileABI_Class_Hidden = 0x00010,
3327
3328 /// Has the exception attribute.
3329 NonFragileABI_Class_Exception = 0x00020,
3330
3331 /// (Obsolete) ARC-specific: this class has a .release_ivars method
3332 NonFragileABI_Class_HasIvarReleaser = 0x00040,
3333
3334 /// Class implementation was compiled under ARC.
John McCall0d54a172012-10-17 04:53:31 +00003335 NonFragileABI_Class_CompiledByARC = 0x00080,
3336
3337 /// Class has non-trivial destructors, but zero-initialization is okay.
John McCall460ce582015-10-22 18:38:17 +00003338 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100,
3339
3340 /// Class implementation was compiled under MRC and has MRC weak ivars.
3341 /// Exclusive with CompiledByARC.
3342 NonFragileABI_Class_HasMRCWeakIvars = 0x00200,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003343};
3344
John McCall460ce582015-10-22 18:38:17 +00003345static bool hasWeakMember(QualType type) {
3346 if (type.getObjCLifetime() == Qualifiers::OCL_Weak) {
3347 return true;
3348 }
3349
3350 if (auto recType = type->getAs<RecordType>()) {
3351 for (auto field : recType->getDecl()->fields()) {
3352 if (hasWeakMember(field->getType()))
3353 return true;
3354 }
3355 }
3356
3357 return false;
3358}
3359
3360/// For compatibility, we only want to set the "HasMRCWeakIvars" flag
3361/// (and actually fill in a layout string) if we really do have any
3362/// __weak ivars.
3363static bool hasMRCWeakIvars(CodeGenModule &CGM,
3364 const ObjCImplementationDecl *ID) {
3365 if (!CGM.getLangOpts().ObjCWeak) return false;
3366 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
3367
3368 for (const ObjCIvarDecl *ivar =
3369 ID->getClassInterface()->all_declared_ivar_begin();
3370 ivar; ivar = ivar->getNextIvar()) {
3371 if (hasWeakMember(ivar->getType()))
3372 return true;
3373 }
3374
3375 return false;
3376}
3377
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003378/*
3379 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003380 Class isa;
3381 Class super_class;
3382 const char *name;
3383 long version;
3384 long info;
3385 long instance_size;
3386 struct _objc_ivar_list *ivars;
3387 struct _objc_method_list *methods;
3388 struct _objc_cache *cache;
3389 struct _objc_protocol_list *protocols;
3390 // Objective-C 1.0 extensions (<rdr://4585769>)
3391 const char *ivar_layout;
3392 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003393 };
3394
3395 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003396*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003397void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003398 DefinedSymbols.insert(ID->getIdentifier());
3399
Chris Lattner86d7d912008-11-24 03:54:41 +00003400 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003401 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003402 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003403 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003404 llvm::Constant *Protocols =
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003405 EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(),
3406 Interface->all_referenced_protocol_begin(),
3407 Interface->all_referenced_protocol_end());
John McCallef19dbb2012-10-17 04:53:23 +00003408 unsigned Flags = FragileABI_Class_Factory;
John McCall0d54a172012-10-17 04:53:31 +00003409 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCallef19dbb2012-10-17 04:53:23 +00003410 Flags |= FragileABI_Class_HasCXXStructors;
John McCall09ec1ec2015-10-21 22:06:03 +00003411
John McCall460ce582015-10-22 18:38:17 +00003412 bool hasMRCWeak = false;
3413
John McCall09ec1ec2015-10-21 22:06:03 +00003414 if (CGM.getLangOpts().ObjCAutoRefCount)
3415 Flags |= FragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00003416 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
3417 Flags |= FragileABI_Class_HasMRCWeakIvars;
John McCall09ec1ec2015-10-21 22:06:03 +00003418
John McCall3fd13f062015-10-21 18:06:47 +00003419 CharUnits Size =
3420 CGM.getContext().getASTObjCImplementationLayout(ID).getSize();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003421
3422 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00003423 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003424 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003425
John McCall176f8922016-11-30 02:39:18 +00003426 enum {
3427 InstanceMethods,
3428 ClassMethods,
3429 NumMethodLists
3430 };
3431 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3432 for (const auto *MD : ID->methods()) {
3433 Methods[unsigned(MD->isClassMethod())].push_back(MD);
3434 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003435
Aaron Ballmand85eff42014-03-14 15:02:45 +00003436 for (const auto *PID : ID->property_impls()) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003437 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3438 ObjCPropertyDecl *PD = PID->getPropertyDecl();
3439
3440 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003441 if (GetMethodDefinition(MD))
3442 Methods[InstanceMethods].push_back(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003443 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003444 if (GetMethodDefinition(MD))
3445 Methods[InstanceMethods].push_back(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003446 }
3447 }
3448
John McCall176f8922016-11-30 02:39:18 +00003449 ConstantInitBuilder builder(CGM);
3450 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3451 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003452 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003453 // Record a reference to the super class.
3454 LazySymbols.insert(Super->getIdentifier());
3455
John McCall176f8922016-11-30 02:39:18 +00003456 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3457 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003458 } else {
John McCall176f8922016-11-30 02:39:18 +00003459 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003460 }
John McCall176f8922016-11-30 02:39:18 +00003461 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003462 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003463 values.addInt(ObjCTypes.LongTy, 0);
3464 values.addInt(ObjCTypes.LongTy, Flags);
3465 values.addInt(ObjCTypes.LongTy, Size.getQuantity());
3466 values.add(EmitIvarList(ID, false));
3467 values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods,
3468 Methods[InstanceMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003469 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003470 values.addNullPointer(ObjCTypes.CachePtrTy);
3471 values.add(Protocols);
3472 values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size));
3473 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3474 /*isMetaclass*/ false));
3475
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003476 std::string Name("OBJC_CLASS_");
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003477 Name += ClassName;
3478 const char *Section = "__OBJC,__class,regular,no_dead_strip";
3479 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003480 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003481 if (GV) {
3482 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3483 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003484 values.finishAndSetAsInitializer(GV);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003485 GV->setSection(Section);
John McCall7f416cc2015-09-08 08:05:57 +00003486 GV->setAlignment(CGM.getPointerAlign().getQuantity());
Rafael Espindola060062a2014-03-06 22:15:10 +00003487 CGM.addCompilerUsedGlobal(GV);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003488 } else
John McCall176f8922016-11-30 02:39:18 +00003489 GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003490 DefinedClasses.push_back(GV);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00003491 ImplementedClasses.push_back(Interface);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003492 // method definition entries must be clear for next implementation.
3493 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003494}
3495
3496llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3497 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00003498 ArrayRef<const ObjCMethodDecl*> Methods) {
John McCallef19dbb2012-10-17 04:53:23 +00003499 unsigned Flags = FragileABI_Class_Meta;
Micah Villmowdd31ca12012-10-08 16:25:52 +00003500 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003501
John McCall457a04e2010-10-22 21:05:15 +00003502 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003503 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003504
John McCall176f8922016-11-30 02:39:18 +00003505 ConstantInitBuilder builder(CGM);
3506 auto values = builder.beginStruct(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003507 // The isa for the metaclass is the root of the hierarchy.
3508 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3509 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3510 Root = Super;
John McCall176f8922016-11-30 02:39:18 +00003511 values.addBitCast(GetClassName(Root->getObjCRuntimeNameAsString()),
3512 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003513 // The super class for the metaclass is emitted as the name of the
3514 // super class. The runtime fixes this up to point to the
3515 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003516 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
John McCall176f8922016-11-30 02:39:18 +00003517 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3518 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003519 } else {
John McCall176f8922016-11-30 02:39:18 +00003520 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003521 }
John McCall176f8922016-11-30 02:39:18 +00003522 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003523 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003524 values.addInt(ObjCTypes.LongTy, 0);
3525 values.addInt(ObjCTypes.LongTy, Flags);
3526 values.addInt(ObjCTypes.LongTy, Size);
3527 values.add(EmitIvarList(ID, true));
3528 values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods,
3529 Methods));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003530 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003531 values.addNullPointer(ObjCTypes.CachePtrTy);
3532 values.add(Protocols);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003533 // ivar_layout for metaclass is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003534 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Renad0e7912016-01-29 19:22:54 +00003535 // The class extension is used to store class properties for metaclasses.
John McCall176f8922016-11-30 02:39:18 +00003536 values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/,
3537 /*isMetaclass*/true));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003538
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003539 std::string Name("OBJC_METACLASS_");
Benjamin Kramer1bbcbd02012-07-31 11:45:39 +00003540 Name += ID->getName();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003541
3542 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003543 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003544 if (GV) {
3545 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3546 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003547 values.finishAndSetAsInitializer(GV);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003548 } else {
John McCall176f8922016-11-30 02:39:18 +00003549 GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
3550 /*constant*/ false,
3551 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003552 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003553 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00003554 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003555
3556 return GV;
3557}
3558
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003559llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003560 std::string Name = "OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003561
Mike Stump18bb9282009-05-16 07:57:57 +00003562 // FIXME: Should we look these up somewhere other than the module. Its a bit
3563 // silly since we only generate these while processing an implementation, so
3564 // exactly one pointer would work if know when we entered/exitted an
3565 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003566
3567 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00003568 // Previously, metaclass with internal linkage may have been defined.
3569 // pass 'true' as 2nd argument so it is returned.
Rafael Espindola21039aa2014-02-27 16:26:32 +00003570 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3571 if (!GV)
3572 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003573 llvm::GlobalValue::PrivateLinkage, nullptr,
3574 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003575
3576 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3577 "Forward metaclass reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003578 return GV;
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003579}
3580
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003581llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003582 std::string Name = "OBJC_CLASS_" + ID->getNameAsString();
Rafael Espindola21039aa2014-02-27 16:26:32 +00003583 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3584
3585 if (!GV)
3586 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003587 llvm::GlobalValue::PrivateLinkage, nullptr,
3588 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003589
3590 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3591 "Forward class metadata reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003592 return GV;
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003593}
3594
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003595/*
John McCall3fd13f062015-10-21 18:06:47 +00003596 Emit a "class extension", which in this specific context means extra
3597 data that doesn't fit in the normal fragile-ABI class structure, and
3598 has nothing to do with the language concept of a class extension.
3599
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003600 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003601 uint32_t size;
3602 const char *weak_ivar_layout;
3603 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003604 };
3605*/
3606llvm::Constant *
John McCall3fd13f062015-10-21 18:06:47 +00003607CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
Manman Renad0e7912016-01-29 19:22:54 +00003608 CharUnits InstanceSize, bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00003609 bool isMetaclass) {
3610 // Weak ivar layout.
3611 llvm::Constant *layout;
3612 if (isMetaclass) {
3613 layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
3614 } else {
3615 layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
3616 hasMRCWeakIvars);
3617 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003618
John McCall176f8922016-11-30 02:39:18 +00003619 // Properties.
3620 llvm::Constant *propertyList =
3621 EmitPropertyList((isMetaclass ? Twine("\01l_OBJC_$_CLASS_PROP_LIST_")
3622 : Twine("\01l_OBJC_$_PROP_LIST_"))
3623 + ID->getName(),
3624 ID, ID->getClassInterface(), ObjCTypes, isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003625
3626 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00003627 if (layout->isNullValue() && propertyList->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003628 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003629 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003630
John McCall176f8922016-11-30 02:39:18 +00003631 uint64_t size =
3632 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3633
3634 ConstantInitBuilder builder(CGM);
3635 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3636 values.addInt(ObjCTypes.IntTy, size);
3637 values.add(layout);
3638 values.add(propertyList);
3639
3640 return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00003641 "__OBJC,__class_ext,regular,no_dead_strip",
3642 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003643}
3644
3645/*
3646 struct objc_ivar {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003647 char *ivar_name;
3648 char *ivar_type;
3649 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003650 };
3651
3652 struct objc_ivar_list {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003653 int ivar_count;
3654 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003655 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003656*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003657llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003658 bool ForClass) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003659 // When emitting the root class GCC emits ivar entries for the
3660 // actual class structure. It is not clear if we need to follow this
3661 // behavior; for now lets try and get away with not doing it. If so,
3662 // the cleanest solution would be to make up an ObjCInterfaceDecl
3663 // for the class.
3664 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00003665 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003666
Jordy Rosea91768e2011-07-22 02:08:32 +00003667 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003668
John McCall176f8922016-11-30 02:39:18 +00003669 ConstantInitBuilder builder(CGM);
3670 auto ivarList = builder.beginStruct();
3671 auto countSlot = ivarList.addPlaceholder();
3672 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3673
Jordy Rosea91768e2011-07-22 02:08:32 +00003674 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00003675 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00003676 // Ignore unnamed bit-fields.
3677 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003678 continue;
John McCall176f8922016-11-30 02:39:18 +00003679
3680 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3681 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3682 ivar.add(GetMethodVarType(IVD));
3683 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3684 ivar.finishAndAddTo(ivars);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003685 }
3686
3687 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00003688 auto count = ivars.size();
3689 if (count == 0) {
3690 ivars.abandon();
3691 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00003692 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003693 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003694
John McCall176f8922016-11-30 02:39:18 +00003695 ivars.finishAndAddTo(ivarList);
3696 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003697
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003698 llvm::GlobalVariable *GV;
3699 if (ForClass)
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003700 GV =
John McCall176f8922016-11-30 02:39:18 +00003701 CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003702 "__OBJC,__class_vars,regular,no_dead_strip",
3703 CGM.getPointerAlign(), true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003704 else
John McCall176f8922016-11-30 02:39:18 +00003705 GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003706 "__OBJC,__instance_vars,regular,no_dead_strip",
3707 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003708 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003709}
3710
John McCall176f8922016-11-30 02:39:18 +00003711/// Build a struct objc_method_description constant for the given method.
3712///
3713/// struct objc_method_description {
3714/// SEL method_name;
3715/// char *method_types;
3716/// };
3717void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
3718 const ObjCMethodDecl *MD) {
3719 auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy);
3720 description.addBitCast(GetMethodVarName(MD->getSelector()),
3721 ObjCTypes.SelectorPtrTy);
3722 description.add(GetMethodVarType(MD));
3723 description.finishAndAddTo(builder);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003724}
3725
John McCall176f8922016-11-30 02:39:18 +00003726/// Build a struct objc_method constant for the given method.
3727///
3728/// struct objc_method {
3729/// SEL method_name;
3730/// char *method_types;
3731/// void *method;
3732/// };
3733void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
3734 const ObjCMethodDecl *MD) {
3735 llvm::Function *fn = GetMethodDefinition(MD);
3736 assert(fn && "no definition registered for method");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003737
John McCall176f8922016-11-30 02:39:18 +00003738 auto method = builder.beginStruct(ObjCTypes.MethodTy);
3739 method.addBitCast(GetMethodVarName(MD->getSelector()),
3740 ObjCTypes.SelectorPtrTy);
3741 method.add(GetMethodVarType(MD));
3742 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
3743 method.finishAndAddTo(builder);
3744}
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003745
John McCall176f8922016-11-30 02:39:18 +00003746/// Build a struct objc_method_list or struct objc_method_description_list,
3747/// as appropriate.
3748///
3749/// struct objc_method_list {
3750/// struct objc_method_list *obsolete;
3751/// int count;
3752/// struct objc_method methods_list[count];
3753/// };
3754///
3755/// struct objc_method_description_list {
3756/// int count;
3757/// struct objc_method_description list[count];
3758/// };
3759llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3760 ArrayRef<const ObjCMethodDecl *> methods) {
3761 StringRef prefix;
3762 StringRef section;
3763 bool forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003764 switch (MLT) {
3765 case MethodListType::CategoryInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003766 prefix = "OBJC_CATEGORY_INSTANCE_METHODS_";
3767 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3768 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003769 break;
3770 case MethodListType::CategoryClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003771 prefix = "OBJC_CATEGORY_CLASS_METHODS_";
3772 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3773 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003774 break;
3775 case MethodListType::InstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003776 prefix = "OBJC_INSTANCE_METHODS_";
3777 section = "__OBJC,__inst_meth,regular,no_dead_strip";
3778 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003779 break;
3780 case MethodListType::ClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003781 prefix = "OBJC_CLASS_METHODS_";
3782 section = "__OBJC,__cls_meth,regular,no_dead_strip";
3783 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003784 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003785 case MethodListType::ProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003786 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_";
3787 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3788 forProtocol = true;
3789 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003790 case MethodListType::ProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003791 prefix = "OBJC_PROTOCOL_CLASS_METHODS_";
3792 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3793 forProtocol = true;
3794 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003795 case MethodListType::OptionalProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003796 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3797 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3798 forProtocol = true;
3799 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003800 case MethodListType::OptionalProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003801 prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3802 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3803 forProtocol = true;
3804 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003805 }
3806
John McCall176f8922016-11-30 02:39:18 +00003807 // Return null for empty list.
3808 if (methods.empty())
3809 return llvm::Constant::getNullValue(forProtocol
3810 ? ObjCTypes.MethodDescriptionListPtrTy
3811 : ObjCTypes.MethodListPtrTy);
3812
3813 // For protocols, this is an objc_method_description_list, which has
3814 // a slightly different structure.
3815 if (forProtocol) {
3816 ConstantInitBuilder builder(CGM);
3817 auto values = builder.beginStruct();
3818 values.addInt(ObjCTypes.IntTy, methods.size());
3819 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3820 for (auto MD : methods) {
3821 emitMethodDescriptionConstant(methodArray, MD);
3822 }
3823 methodArray.finishAndAddTo(values);
3824
3825 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3826 CGM.getPointerAlign(), true);
3827 return llvm::ConstantExpr::getBitCast(GV,
3828 ObjCTypes.MethodDescriptionListPtrTy);
3829 }
3830
3831 // Otherwise, it's an objc_method_list.
3832 ConstantInitBuilder builder(CGM);
3833 auto values = builder.beginStruct();
3834 values.addNullPointer(ObjCTypes.Int8PtrTy);
3835 values.addInt(ObjCTypes.IntTy, methods.size());
3836 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3837 for (auto MD : methods) {
3838 emitMethodConstant(methodArray, MD);
3839 }
3840 methodArray.finishAndAddTo(values);
3841
3842 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003843 CGM.getPointerAlign(), true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003844 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003845}
3846
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00003847llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003848 const ObjCContainerDecl *CD) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003849 SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00003850 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003851
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00003852 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00003853 llvm::FunctionType *MethodTy =
John McCalla729c622012-02-17 03:33:10 +00003854 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003855 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00003856 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003857 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00003858 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003859 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003860 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003861
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003862 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003863}
3864
Alp Toker541d5072014-06-07 23:30:53 +00003865llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
John McCall176f8922016-11-30 02:39:18 +00003866 ConstantStructBuilder &Init,
3867 StringRef Section,
3868 CharUnits Align,
3869 bool AddToUsed) {
3870 llvm::GlobalVariable *GV =
3871 Init.finishAndCreateGlobal(Name, Align, /*constant*/ false,
3872 llvm::GlobalValue::PrivateLinkage);
3873 if (!Section.empty())
3874 GV->setSection(Section);
3875 if (AddToUsed)
3876 CGM.addCompilerUsedGlobal(GV);
3877 return GV;
3878}
3879
3880llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
Alp Toker541d5072014-06-07 23:30:53 +00003881 llvm::Constant *Init,
3882 StringRef Section,
John McCall7f416cc2015-09-08 08:05:57 +00003883 CharUnits Align,
Alp Toker541d5072014-06-07 23:30:53 +00003884 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003885 llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003886 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00003887 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00003888 llvm::GlobalValue::PrivateLinkage, Init, Name);
Alp Toker541d5072014-06-07 23:30:53 +00003889 if (!Section.empty())
Daniel Dunbar30c65362009-03-09 20:09:19 +00003890 GV->setSection(Section);
John McCall7f416cc2015-09-08 08:05:57 +00003891 GV->setAlignment(Align.getQuantity());
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003892 if (AddToUsed)
Rafael Espindola060062a2014-03-06 22:15:10 +00003893 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003894 return GV;
3895}
3896
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003897llvm::GlobalVariable *
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003898CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type,
3899 bool ForceNonFragileABI,
3900 bool NullTerminate) {
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003901 StringRef Label;
3902 switch (Type) {
3903 case ObjCLabelType::ClassName: Label = "OBJC_CLASS_NAME_"; break;
3904 case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break;
3905 case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break;
3906 case ObjCLabelType::PropertyName: Label = "OBJC_PROP_NAME_ATTR_"; break;
3907 }
3908
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003909 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
3910
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003911 StringRef Section;
3912 switch (Type) {
3913 case ObjCLabelType::ClassName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003914 Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals"
3915 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003916 break;
3917 case ObjCLabelType::MethodVarName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003918 Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
3919 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003920 break;
3921 case ObjCLabelType::MethodVarType:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003922 Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals"
3923 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003924 break;
3925 case ObjCLabelType::PropertyName:
3926 Section = "__TEXT,__cstring,cstring_literals";
3927 break;
3928 }
3929
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00003930 llvm::Constant *Value =
3931 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003932 llvm::GlobalVariable *GV =
Saleem Abdulrasool0c54dc82016-09-18 16:12:04 +00003933 new llvm::GlobalVariable(CGM.getModule(), Value->getType(),
3934 /*isConstant=*/true,
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003935 llvm::GlobalValue::PrivateLinkage, Value, Label);
Saleem Abdulrasool3f307512016-09-18 16:12:14 +00003936 if (CGM.getTriple().isOSBinFormatMachO())
3937 GV->setSection(Section);
3938 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00003939 GV->setAlignment(CharUnits::One().getQuantity());
3940 CGM.addCompilerUsedGlobal(GV);
3941
3942 return GV;
3943}
3944
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003945llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003946 // Abuse this interface function as a place to finalize.
3947 FinishModule();
Craig Topper8a13c412014-05-21 05:09:00 +00003948 return nullptr;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003949}
3950
Chris Lattnerd4808922009-03-22 21:03:39 +00003951llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003952 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003953}
3954
Chris Lattnerd4808922009-03-22 21:03:39 +00003955llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003956 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003957}
3958
Ted Kremeneke65b0862012-03-06 20:05:56 +00003959llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
3960 bool copy) {
3961 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
3962}
3963
David Chisnall168b80f2010-12-26 22:13:16 +00003964llvm::Constant *CGObjCMac::GetGetStructFunction() {
3965 return ObjCTypes.getCopyStructFn();
3966}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00003967
David Chisnall168b80f2010-12-26 22:13:16 +00003968llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00003969 return ObjCTypes.getCopyStructFn();
3970}
3971
David Chisnall0d75e062012-12-17 18:54:24 +00003972llvm::Constant *CGObjCMac::GetCppAtomicObjectGetFunction() {
3973 return ObjCTypes.getCppAtomicObjectFunction();
3974}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00003975
David Chisnall0d75e062012-12-17 18:54:24 +00003976llvm::Constant *CGObjCMac::GetCppAtomicObjectSetFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00003977 return ObjCTypes.getCppAtomicObjectFunction();
3978}
3979
Chris Lattnerd4808922009-03-22 21:03:39 +00003980llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003981 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00003982}
3983
John McCallbd309292010-07-06 01:34:17 +00003984void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
3985 return EmitTryOrSynchronizedStmt(CGF, S);
3986}
3987
3988void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
3989 const ObjCAtSynchronizedStmt &S) {
3990 return EmitTryOrSynchronizedStmt(CGF, S);
3991}
3992
John McCall65bea082010-07-21 06:59:36 +00003993namespace {
David Blaikie7e70d682015-08-18 22:40:54 +00003994 struct PerformFragileFinally final : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00003995 const Stmt &S;
John McCall7f416cc2015-09-08 08:05:57 +00003996 Address SyncArgSlot;
3997 Address CallTryExitVar;
3998 Address ExceptionData;
John McCall65bea082010-07-21 06:59:36 +00003999 ObjCTypesHelper &ObjCTypes;
4000 PerformFragileFinally(const Stmt *S,
John McCall7f416cc2015-09-08 08:05:57 +00004001 Address SyncArgSlot,
4002 Address CallTryExitVar,
4003 Address ExceptionData,
John McCall65bea082010-07-21 06:59:36 +00004004 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00004005 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00004006 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4007
Craig Topper4f12f102014-03-12 06:41:41 +00004008 void Emit(CodeGenFunction &CGF, Flags flags) override {
John McCall65bea082010-07-21 06:59:36 +00004009 // Check whether we need to call objc_exception_try_exit.
4010 // In optimized code, this branch will always be folded.
4011 llvm::BasicBlock *FinallyCallExit =
4012 CGF.createBasicBlock("finally.call_exit");
4013 llvm::BasicBlock *FinallyNoCallExit =
4014 CGF.createBasicBlock("finally.no_call_exit");
4015 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
4016 FinallyCallExit, FinallyNoCallExit);
4017
4018 CGF.EmitBlock(FinallyCallExit);
John McCall882987f2013-02-28 19:01:20 +00004019 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004020 ExceptionData.getPointer());
John McCall65bea082010-07-21 06:59:36 +00004021
4022 CGF.EmitBlock(FinallyNoCallExit);
4023
4024 if (isa<ObjCAtTryStmt>(S)) {
4025 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00004026 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
John McCall638d4f52013-04-03 00:56:07 +00004027 // Don't try to do the @finally if this is an EH cleanup.
4028 if (flags.isForEHCleanup()) return;
4029
John McCallcebe0ca2010-08-11 00:16:14 +00004030 // Save the current cleanup destination in case there's
4031 // control flow inside the finally statement.
4032 llvm::Value *CurCleanupDest =
4033 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
4034
John McCall65bea082010-07-21 06:59:36 +00004035 CGF.EmitStmt(FinallyStmt->getFinallyBody());
4036
John McCallcebe0ca2010-08-11 00:16:14 +00004037 if (CGF.HaveInsertPoint()) {
4038 CGF.Builder.CreateStore(CurCleanupDest,
4039 CGF.getNormalCleanupDestSlot());
4040 } else {
4041 // Currently, the end of the cleanup must always exist.
4042 CGF.EnsureInsertPoint();
4043 }
4044 }
John McCall65bea082010-07-21 06:59:36 +00004045 } else {
4046 // Emit objc_sync_exit(expr); as finally's sole statement for
4047 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00004048 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall882987f2013-02-28 19:01:20 +00004049 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg);
John McCall65bea082010-07-21 06:59:36 +00004050 }
4051 }
4052 };
John McCall42227ed2010-07-31 23:20:56 +00004053
4054 class FragileHazards {
4055 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004056 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00004057 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
4058
4059 llvm::InlineAsm *ReadHazard;
4060 llvm::InlineAsm *WriteHazard;
4061
4062 llvm::FunctionType *GetAsmFnType();
4063
4064 void collectLocals();
4065 void emitReadHazard(CGBuilderTy &Builder);
4066
4067 public:
4068 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00004069
John McCall42227ed2010-07-31 23:20:56 +00004070 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00004071 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004072 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004073} // end anonymous namespace
John McCall42227ed2010-07-31 23:20:56 +00004074
4075/// Create the fragile-ABI read and write hazards based on the current
4076/// state of the function, which is presumed to be immediately prior
4077/// to a @try block. These hazards are used to maintain correct
4078/// semantics in the face of optimization and the fragile ABI's
4079/// cavalier use of setjmp/longjmp.
4080FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
4081 collectLocals();
4082
4083 if (Locals.empty()) return;
4084
4085 // Collect all the blocks in the function.
4086 for (llvm::Function::iterator
4087 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
4088 BlocksBeforeTry.insert(&*I);
4089
4090 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4091
4092 // Create a read hazard for the allocas. This inhibits dead-store
4093 // optimizations and forces the values to memory. This hazard is
4094 // inserted before any 'throwing' calls in the protected scope to
4095 // reflect the possibility that the variables might be read from the
4096 // catch block if the call throws.
4097 {
4098 std::string Constraint;
4099 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
4100 if (I) Constraint += ',';
4101 Constraint += "*m";
4102 }
4103
4104 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
4105 }
4106
4107 // Create a write hazard for the allocas. This inhibits folding
4108 // loads across the hazard. This hazard is inserted at the
4109 // beginning of the catch path to reflect the possibility that the
4110 // variables might have been written within the protected scope.
4111 {
4112 std::string Constraint;
4113 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
4114 if (I) Constraint += ',';
4115 Constraint += "=*m";
4116 }
4117
4118 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
4119 }
4120}
4121
4122/// Emit a write hazard at the current location.
4123void FragileHazards::emitWriteHazard() {
4124 if (Locals.empty()) return;
4125
John McCall882987f2013-02-28 19:01:20 +00004126 CGF.EmitNounwindRuntimeCall(WriteHazard, Locals);
John McCall42227ed2010-07-31 23:20:56 +00004127}
4128
John McCall42227ed2010-07-31 23:20:56 +00004129void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
4130 assert(!Locals.empty());
John McCall882987f2013-02-28 19:01:20 +00004131 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4132 call->setDoesNotThrow();
4133 call->setCallingConv(CGF.getRuntimeCC());
John McCall42227ed2010-07-31 23:20:56 +00004134}
4135
4136/// Emit read hazards in all the protected blocks, i.e. all the blocks
4137/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00004138void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00004139 if (Locals.empty()) return;
4140
John McCall7f416cc2015-09-08 08:05:57 +00004141 CGBuilderTy Builder(CGF, CGF.getLLVMContext());
John McCall42227ed2010-07-31 23:20:56 +00004142
4143 // Iterate through all blocks, skipping those prior to the try.
4144 for (llvm::Function::iterator
4145 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
4146 llvm::BasicBlock &BB = *FI;
4147 if (BlocksBeforeTry.count(&BB)) continue;
4148
4149 // Walk through all the calls in the block.
4150 for (llvm::BasicBlock::iterator
4151 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
4152 llvm::Instruction &I = *BI;
4153
4154 // Ignore instructions that aren't non-intrinsic calls.
4155 // These are the only calls that can possibly call longjmp.
4156 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
4157 if (isa<llvm::IntrinsicInst>(I))
4158 continue;
4159
4160 // Ignore call sites marked nounwind. This may be questionable,
4161 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
4162 llvm::CallSite CS(&I);
4163 if (CS.doesNotThrow()) continue;
4164
John McCall2dd7d442010-08-04 05:59:32 +00004165 // Insert a read hazard before the call. This will ensure that
4166 // any writes to the locals are performed before making the
4167 // call. If the call throws, then this is sufficient to
4168 // guarantee correctness as long as it doesn't also write to any
4169 // locals.
John McCall42227ed2010-07-31 23:20:56 +00004170 Builder.SetInsertPoint(&BB, BI);
4171 emitReadHazard(Builder);
4172 }
4173 }
4174}
4175
4176static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
4177 if (V) S.insert(V);
4178}
4179
John McCall7f416cc2015-09-08 08:05:57 +00004180static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) {
4181 if (V.isValid()) S.insert(V.getPointer());
4182}
4183
John McCall42227ed2010-07-31 23:20:56 +00004184void FragileHazards::collectLocals() {
4185 // Compute a set of allocas to ignore.
4186 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
4187 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
4188 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00004189
4190 // Collect all the allocas currently in the function. This is
4191 // probably way too aggressive.
4192 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
4193 for (llvm::BasicBlock::iterator
4194 I = Entry.begin(), E = Entry.end(); I != E; ++I)
4195 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
4196 Locals.push_back(&*I);
4197}
4198
4199llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004200 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00004201 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
4202 tys[i] = Locals[i]->getType();
4203 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00004204}
4205
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004206/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004207
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004208 Objective-C setjmp-longjmp (sjlj) Exception Handling
4209 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004210
John McCallbd309292010-07-06 01:34:17 +00004211 A catch buffer is a setjmp buffer plus:
4212 - a pointer to the exception that was caught
4213 - a pointer to the previous exception data buffer
4214 - two pointers of reserved storage
4215 Therefore catch buffers form a stack, with a pointer to the top
4216 of the stack kept in thread-local storage.
4217
4218 objc_exception_try_enter pushes a catch buffer onto the EH stack.
4219 objc_exception_try_exit pops the given catch buffer, which is
4220 required to be the top of the EH stack.
4221 objc_exception_throw pops the top of the EH stack, writes the
4222 thrown exception into the appropriate field, and longjmps
4223 to the setjmp buffer. It crashes the process (with a printf
4224 and an abort()) if there are no catch buffers on the stack.
4225 objc_exception_extract just reads the exception pointer out of the
4226 catch buffer.
4227
4228 There's no reason an implementation couldn't use a light-weight
4229 setjmp here --- something like __builtin_setjmp, but API-compatible
4230 with the heavyweight setjmp. This will be more important if we ever
4231 want to implement correct ObjC/C++ exception interactions for the
4232 fragile ABI.
4233
4234 Note that for this use of setjmp/longjmp to be correct, we may need
4235 to mark some local variables volatile: if a non-volatile local
4236 variable is modified between the setjmp and the longjmp, it has
4237 indeterminate value. For the purposes of LLVM IR, it may be
4238 sufficient to make loads and stores within the @try (to variables
4239 declared outside the @try) volatile. This is necessary for
4240 optimized correctness, but is not currently being done; this is
4241 being tracked as rdar://problem/8160285
4242
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004243 The basic framework for a @try-catch-finally is as follows:
4244 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004245 objc_exception_data d;
4246 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00004247 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004248
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004249 objc_exception_try_enter(&d);
4250 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004251 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004252 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004253 // exception path
4254 id _caught = objc_exception_extract(&d);
4255
4256 // enter new try scope for handlers
4257 if (!setjmp(d.jmp_buf)) {
4258 ... match exception and execute catch blocks ...
4259
4260 // fell off end, rethrow.
4261 _rethrow = _caught;
4262 ... jump-through-finally to finally_rethrow ...
4263 } else {
4264 // exception in catch block
4265 _rethrow = objc_exception_extract(&d);
4266 _call_try_exit = false;
4267 ... jump-through-finally to finally_rethrow ...
4268 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004269 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004270 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004271
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004272 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00004273 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004274 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00004275
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004276 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004277 ... dispatch to finally destination ...
4278
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004279 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004280 objc_exception_throw(_rethrow);
4281
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004282 finally_end:
4283 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004284
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004285 This framework differs slightly from the one gcc uses, in that gcc
4286 uses _rethrow to determine if objc_exception_try_exit should be called
4287 and if the object should be rethrown. This breaks in the face of
4288 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004289
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004290 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004291
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004292 - If there are no catch blocks, then we avoid emitting the second
4293 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004294
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004295 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
4296 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004297
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004298 - FIXME: If there is no @finally block we can do a few more
4299 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004300
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004301 Rethrows and Jumps-Through-Finally
4302 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004303
John McCallbd309292010-07-06 01:34:17 +00004304 '@throw;' is supported by pushing the currently-caught exception
4305 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004306
John McCallbd309292010-07-06 01:34:17 +00004307 Branches through the @finally block are handled with an ordinary
4308 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
4309 exceptions are not compatible with C++ exceptions, and this is
4310 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004311
John McCallbd309292010-07-06 01:34:17 +00004312 @synchronized(expr) { stmt; } is emitted as if it were:
4313 id synch_value = expr;
4314 objc_sync_enter(synch_value);
4315 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004316*/
4317
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00004318void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
4319 const Stmt &S) {
4320 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00004321
4322 // A destination for the fall-through edges of the catch handlers to
4323 // jump to.
4324 CodeGenFunction::JumpDest FinallyEnd =
4325 CGF.getJumpDestInCurrentScope("finally.end");
4326
4327 // A destination for the rethrow edge of the catch handlers to jump
4328 // to.
4329 CodeGenFunction::JumpDest FinallyRethrow =
4330 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004331
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004332 // For @synchronized, call objc_sync_enter(sync.expr). The
4333 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00004334 // @synchronized. We can't avoid a temp here because we need the
4335 // value to be preserved. If the backend ever does liveness
4336 // correctly after setjmp, this will be unnecessary.
John McCall7f416cc2015-09-08 08:05:57 +00004337 Address SyncArgSlot = Address::invalid();
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004338 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00004339 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004340 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4341 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004342 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);
John McCall2dd7d442010-08-04 05:59:32 +00004343
John McCall7f416cc2015-09-08 08:05:57 +00004344 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(),
4345 CGF.getPointerAlign(), "sync.arg");
John McCall2dd7d442010-08-04 05:59:32 +00004346 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004347 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004348
John McCall2dd7d442010-08-04 05:59:32 +00004349 // Allocate memory for the setjmp buffer. This needs to be kept
4350 // live throughout the try and catch blocks.
John McCall7f416cc2015-09-08 08:05:57 +00004351 Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
4352 CGF.getPointerAlign(),
4353 "exceptiondata.ptr");
John McCall2dd7d442010-08-04 05:59:32 +00004354
John McCall42227ed2010-07-31 23:20:56 +00004355 // Create the fragile hazards. Note that this will not capture any
4356 // of the allocas required for exception processing, but will
4357 // capture the current basic block (which extends all the way to the
4358 // setjmp call) as "before the @try".
4359 FragileHazards Hazards(CGF);
4360
John McCallbd309292010-07-06 01:34:17 +00004361 // Create a flag indicating whether the cleanup needs to call
4362 // objc_exception_try_exit. This is true except when
4363 // - no catches match and we're branching through the cleanup
4364 // just to rethrow the exception, or
4365 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00004366 // The setjmp-safety rule here is that we should always store to this
4367 // variable in a place that dominates the branch through the cleanup
4368 // without passing through any setjmps.
John McCall7f416cc2015-09-08 08:05:57 +00004369 Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
4370 CharUnits::One(),
4371 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004372
John McCall9916e3f2010-10-04 23:42:51 +00004373 // A slot containing the exception to rethrow. Only needed when we
4374 // have both a @catch and a @finally.
John McCall7f416cc2015-09-08 08:05:57 +00004375 Address PropagatingExnVar = Address::invalid();
John McCall9916e3f2010-10-04 23:42:51 +00004376
John McCallbd309292010-07-06 01:34:17 +00004377 // Push a normal cleanup to leave the try scope.
John McCall638d4f52013-04-03 00:56:07 +00004378 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00004379 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00004380 CallTryExitVar,
4381 ExceptionData,
4382 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00004383
4384 // Enter a try block:
4385 // - Call objc_exception_try_enter to push ExceptionData on top of
4386 // the EH stack.
Nico Weber6307cf02015-02-26 20:43:00 +00004387 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004388 ExceptionData.getPointer());
John McCallbd309292010-07-06 01:34:17 +00004389
4390 // - Call setjmp on the exception data buffer.
4391 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
4392 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
David Blaikie6b2a8302015-04-03 17:47:16 +00004393 llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
John McCall7f416cc2015-09-08 08:05:57 +00004394 ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes,
4395 "setjmp_buffer");
Nico Weber6307cf02015-02-26 20:43:00 +00004396 llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
4397 ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004398 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00004399
4400 // If setjmp returned 0, enter the protected block; otherwise,
4401 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00004402 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
4403 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00004404 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00004405 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4406 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004407
John McCallbd309292010-07-06 01:34:17 +00004408 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004409 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00004410 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004411 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00004412 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00004413
4414 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004415
John McCallbd309292010-07-06 01:34:17 +00004416 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00004417 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004418
John McCall42227ed2010-07-31 23:20:56 +00004419 // Don't optimize loads of the in-scope locals across this point.
4420 Hazards.emitWriteHazard();
4421
John McCallbd309292010-07-06 01:34:17 +00004422 // For a @synchronized (or a @try with no catches), just branch
4423 // through the cleanup to the rethrow block.
4424 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4425 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00004426 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004427 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00004428
4429 // Otherwise, we have to match against the caught exceptions.
4430 } else {
John McCall2dd7d442010-08-04 05:59:32 +00004431 // Retrieve the exception object. We may emit multiple blocks but
4432 // nothing can cross this so the value is already in SSA form.
4433 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004434 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004435 ExceptionData.getPointer(), "caught");
John McCall2dd7d442010-08-04 05:59:32 +00004436
John McCallbd309292010-07-06 01:34:17 +00004437 // Push the exception to rethrow onto the EH value stack for the
4438 // benefit of any @throws in the handlers.
4439 CGF.ObjCEHValueStack.push_back(Caught);
4440
Douglas Gregor96c79492010-04-23 22:50:49 +00004441 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004442
Craig Topper8a13c412014-05-21 05:09:00 +00004443 bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr);
John McCallbd309292010-07-06 01:34:17 +00004444
Craig Topper8a13c412014-05-21 05:09:00 +00004445 llvm::BasicBlock *CatchBlock = nullptr;
4446 llvm::BasicBlock *CatchHandler = nullptr;
John McCall2dd7d442010-08-04 05:59:32 +00004447 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00004448 // Save the currently-propagating exception before
4449 // objc_exception_try_enter clears the exception slot.
4450 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
John McCall7f416cc2015-09-08 08:05:57 +00004451 CGF.getPointerAlign(),
John McCall9916e3f2010-10-04 23:42:51 +00004452 "propagating_exception");
4453 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
4454
John McCall2dd7d442010-08-04 05:59:32 +00004455 // Enter a new exception try block (in case a @catch block
4456 // throws an exception).
John McCall882987f2013-02-28 19:01:20 +00004457 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004458 ExceptionData.getPointer());
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004459
John McCall2dd7d442010-08-04 05:59:32 +00004460 llvm::CallInst *SetJmpResult =
John McCall882987f2013-02-28 19:01:20 +00004461 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(),
4462 SetJmpBuffer, "setjmp.result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004463 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004464
John McCall2dd7d442010-08-04 05:59:32 +00004465 llvm::Value *Threw =
4466 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4467
4468 CatchBlock = CGF.createBasicBlock("catch");
4469 CatchHandler = CGF.createBasicBlock("catch_for_catch");
4470 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4471
4472 CGF.EmitBlock(CatchBlock);
4473 }
4474
4475 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004476
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004477 // Handle catch list. As a special case we check if everything is
4478 // matched and avoid generating code for falling off the end if
4479 // so.
4480 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00004481 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
4482 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004483
Douglas Gregor46a572b2010-04-26 16:46:50 +00004484 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Craig Topper8a13c412014-05-21 05:09:00 +00004485 const ObjCObjectPointerType *OPT = nullptr;
Daniel Dunbar523208f2008-09-27 07:36:24 +00004486
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004487 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004488 if (!CatchParam) {
4489 AllMatched = true;
4490 } else {
John McCall9dd450b2009-09-21 23:43:11 +00004491 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004492
John McCallbd309292010-07-06 01:34:17 +00004493 // catch(id e) always matches under this ABI, since only
4494 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00004495 // FIXME: For the time being we also match id<X>; this should
4496 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00004497 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004498 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004499 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004500
John McCallbd309292010-07-06 01:34:17 +00004501 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004502 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00004503 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4504
Anders Carlsson9396a892008-09-11 09:15:33 +00004505 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00004506 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004507 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00004508
4509 // These types work out because ConvertType(id) == i8*.
John McCall17f02752015-10-30 00:56:02 +00004510 EmitInitOfCatchParam(CGF, Caught, CatchParam);
Anders Carlsson9396a892008-09-11 09:15:33 +00004511 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004512
Anders Carlsson9396a892008-09-11 09:15:33 +00004513 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004514
4515 // The scope of the catch variable ends right here.
4516 CatchVarCleanups.ForceCleanup();
4517
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004518 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004519 break;
4520 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004521
Steve Naroff7cae42b2009-07-10 23:34:53 +00004522 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00004523 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00004524
4525 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00004526 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
4527 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004528
4529 // Check if the @catch block matches the exception object.
John McCall882987f2013-02-28 19:01:20 +00004530 llvm::Value *Class = EmitClassRef(CGF, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004531
John McCall882987f2013-02-28 19:01:20 +00004532 llvm::Value *matchArgs[] = { Class, Caught };
John McCallbd309292010-07-06 01:34:17 +00004533 llvm::CallInst *Match =
John McCall882987f2013-02-28 19:01:20 +00004534 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(),
4535 matchArgs, "match");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004536
John McCallbd309292010-07-06 01:34:17 +00004537 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
4538 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004539
4540 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00004541 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004542
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004543 // Emit the @catch block.
4544 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00004545
4546 // Collect any cleanups for the catch variable. The scope lasts until
4547 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00004548 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00004549
John McCall1c9c3fd2010-10-15 04:57:14 +00004550 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004551 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004552
John McCallbd309292010-07-06 01:34:17 +00004553 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004554 llvm::Value *Tmp =
4555 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004556 CGF.ConvertType(CatchParam->getType()));
John McCall17f02752015-10-30 00:56:02 +00004557 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004558
Anders Carlsson9396a892008-09-11 09:15:33 +00004559 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004560
4561 // We're done with the catch variable.
4562 CatchVarCleanups.ForceCleanup();
4563
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004564 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004565
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004566 CGF.EmitBlock(NextCatchBlock);
4567 }
4568
John McCallbd309292010-07-06 01:34:17 +00004569 CGF.ObjCEHValueStack.pop_back();
4570
John McCall2dd7d442010-08-04 05:59:32 +00004571 // If nothing wanted anything to do with the caught exception,
4572 // kill the extract call.
4573 if (Caught->use_empty())
4574 Caught->eraseFromParent();
4575
4576 if (!AllMatched)
4577 CGF.EmitBranchThroughCleanup(FinallyRethrow);
4578
4579 if (HasFinally) {
4580 // Emit the exception handler for the @catch blocks.
4581 CGF.EmitBlock(CatchHandler);
4582
4583 // In theory we might now need a write hazard, but actually it's
4584 // unnecessary because there's no local-accessing code between
4585 // the try's write hazard and here.
4586 //Hazards.emitWriteHazard();
4587
John McCall9916e3f2010-10-04 23:42:51 +00004588 // Extract the new exception and save it to the
4589 // propagating-exception slot.
John McCall7f416cc2015-09-08 08:05:57 +00004590 assert(PropagatingExnVar.isValid());
John McCall9916e3f2010-10-04 23:42:51 +00004591 llvm::CallInst *NewCaught =
John McCall882987f2013-02-28 19:01:20 +00004592 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004593 ExceptionData.getPointer(), "caught");
John McCall9916e3f2010-10-04 23:42:51 +00004594 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4595
John McCall2dd7d442010-08-04 05:59:32 +00004596 // Don't pop the catch handler; the throw already did.
4597 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004598 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004599 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004600 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004601
John McCall42227ed2010-07-31 23:20:56 +00004602 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00004603 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004604
John McCallbd309292010-07-06 01:34:17 +00004605 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00004606 CGF.Builder.restoreIP(TryFallthroughIP);
4607 if (CGF.HaveInsertPoint())
4608 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00004609 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00004610 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004611
John McCallbd309292010-07-06 01:34:17 +00004612 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00004613 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00004614 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00004615 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00004616 // If we have a propagating-exception variable, check it.
4617 llvm::Value *PropagatingExn;
John McCall7f416cc2015-09-08 08:05:57 +00004618 if (PropagatingExnVar.isValid()) {
John McCall9916e3f2010-10-04 23:42:51 +00004619 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00004620
John McCall9916e3f2010-10-04 23:42:51 +00004621 // Otherwise, just look in the buffer for the exception to throw.
4622 } else {
4623 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004624 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004625 ExceptionData.getPointer());
John McCall9916e3f2010-10-04 23:42:51 +00004626 PropagatingExn = Caught;
4627 }
4628
John McCall882987f2013-02-28 19:01:20 +00004629 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(),
4630 PropagatingExn);
John McCallbd309292010-07-06 01:34:17 +00004631 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00004632 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004633
John McCall42227ed2010-07-31 23:20:56 +00004634 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004635}
4636
4637void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004638 const ObjCAtThrowStmt &S,
4639 bool ClearInsertionPoint) {
Anders Carlssone005aa12008-09-09 16:16:55 +00004640 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004641
Anders Carlssone005aa12008-09-09 16:16:55 +00004642 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00004643 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004644 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004645 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00004646 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004647 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004648 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00004649 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00004650 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004651
John McCall882987f2013-02-28 19:01:20 +00004652 CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
John McCallbd309292010-07-06 01:34:17 +00004653 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004654 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004655
4656 // Clear the insertion point to indicate we are in unreachable code.
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004657 if (ClearInsertionPoint)
4658 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004659}
4660
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004661/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004662/// object: objc_read_weak (id *src)
4663///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004664llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004665 Address AddrWeakObj) {
4666 llvm::Type* DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004667 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4668 ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004669 llvm::Value *read_weak =
4670 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004671 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00004672 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004673 return read_weak;
4674}
4675
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004676/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4677/// objc_assign_weak (id src, id *dst)
4678///
4679void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004680 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004681 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004682 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004683 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004684 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004685 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4686 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004687 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4688 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004689 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4690 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004691 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00004692 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4693 args, "weakassign");
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004694}
4695
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004696/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4697/// objc_assign_global (id src, id *dst)
4698///
4699void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004700 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00004701 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004702 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004703 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004704 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004705 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004706 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4707 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004708 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4709 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004710 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4711 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004712 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00004713 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00004714 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4715 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00004716 else
John McCall882987f2013-02-28 19:01:20 +00004717 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4718 args, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004719}
4720
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004721/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004722/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004723///
4724void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004725 llvm::Value *src, Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004726 llvm::Value *ivarOffset) {
4727 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00004728 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004729 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004730 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004731 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004732 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4733 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004734 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4735 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004736 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4737 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004738 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00004739 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004740}
4741
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004742/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
4743/// objc_assign_strongCast (id src, id *dst)
4744///
4745void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004746 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004747 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004748 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004749 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004750 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004751 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4752 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004753 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4754 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004755 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4756 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004757 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00004758 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004759 args, "strongassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004760}
4761
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004762void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004763 Address DestPtr,
4764 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00004765 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004766 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
4767 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004768 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size };
John McCall882987f2013-02-28 19:01:20 +00004769 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004770}
4771
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004772/// EmitObjCValueForIvar - Code Gen for ivar reference.
4773///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004774LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4775 QualType ObjectTy,
4776 llvm::Value *BaseValue,
4777 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004778 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00004779 const ObjCInterfaceDecl *ID =
4780 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00004781 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4782 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004783}
4784
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004785llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00004786 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004787 const ObjCIvarDecl *Ivar) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004788 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4789 return llvm::ConstantInt::get(
4790 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
4791 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004792}
4793
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004794/* *** Private Interface *** */
4795
4796/// EmitImageInfo - Emit the image info marker used to encode some module
4797/// level information.
4798///
4799/// See: <rdr://4810609&4810587&4810587>
4800/// struct IMAGE_INFO {
4801/// unsigned version;
4802/// unsigned flags;
4803/// };
4804enum ImageInfoFlags {
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004805 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004806 eImageInfo_GarbageCollected = (1 << 1),
4807 eImageInfo_GCOnly = (1 << 2),
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004808 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
Daniel Dunbar75e909f2009-04-20 07:11:47 +00004809
Daniel Dunbar5e639272010-04-25 20:39:01 +00004810 // A flag indicating that the module has no instances of a @synthesize of a
4811 // superclass variable. <rdar://problem/6803242>
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004812 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
Manman Ren96df0b32016-01-29 23:45:01 +00004813 eImageInfo_ImageIsSimulated = (1 << 5),
4814 eImageInfo_ClassProperties = (1 << 6)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004815};
4816
Daniel Dunbar5e639272010-04-25 20:39:01 +00004817void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004818 unsigned version = 0; // Version is unused?
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004819 const char *Section = (ObjCABI == 1) ?
4820 "__OBJC, __image_info,regular" :
4821 "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004822
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004823 // Generate module-level named metadata to convey this information to the
4824 // linker and code-gen.
4825 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004826
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004827 // Add the ObjC ABI version to the module flags.
4828 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
4829 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
4830 version);
4831 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
4832 llvm::MDString::get(VMContext,Section));
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004833
David Blaikiebbafb8a2012-03-11 07:00:24 +00004834 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004835 // Non-GC overrides those files which specify GC.
4836 Mod.addModuleFlag(llvm::Module::Override,
4837 "Objective-C Garbage Collection", (uint32_t)0);
4838 } else {
4839 // Add the ObjC garbage collection value.
4840 Mod.addModuleFlag(llvm::Module::Error,
4841 "Objective-C Garbage Collection",
4842 eImageInfo_GarbageCollected);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004843
David Blaikiebbafb8a2012-03-11 07:00:24 +00004844 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004845 // Add the ObjC GC Only value.
4846 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
4847 eImageInfo_GCOnly);
4848
4849 // Require that GC be specified and set to eImageInfo_GarbageCollected.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +00004850 llvm::Metadata *Ops[2] = {
4851 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
4852 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
4853 llvm::Type::getInt32Ty(VMContext), eImageInfo_GarbageCollected))};
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004854 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
4855 llvm::MDNode::get(VMContext, Ops));
4856 }
4857 }
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004858
4859 // Indicate whether we're compiling this to run on a simulator.
4860 const llvm::Triple &Triple = CGM.getTarget().getTriple();
Tim Northover756447a2015-10-30 16:30:36 +00004861 if ((Triple.isiOS() || Triple.isWatchOS()) &&
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004862 (Triple.getArch() == llvm::Triple::x86 ||
4863 Triple.getArch() == llvm::Triple::x86_64))
4864 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
4865 eImageInfo_ImageIsSimulated);
Manman Ren96df0b32016-01-29 23:45:01 +00004866
4867 // Indicate whether we are generating class properties.
4868 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Class Properties",
4869 eImageInfo_ClassProperties);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004870}
4871
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004872// struct objc_module {
4873// unsigned long version;
4874// unsigned long size;
4875// const char *name;
4876// Symtab symtab;
4877// };
4878
4879// FIXME: Get from somewhere
4880static const int ModuleVersion = 7;
4881
4882void CGObjCMac::EmitModuleInfo() {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004883 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004884
John McCall176f8922016-11-30 02:39:18 +00004885 ConstantInitBuilder builder(CGM);
4886 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
4887 values.addInt(ObjCTypes.LongTy, ModuleVersion);
4888 values.addInt(ObjCTypes.LongTy, Size);
4889 // This used to be the filename, now it is unused. <rdr://4327263>
4890 values.add(GetClassName(StringRef("")));
4891 values.add(EmitModuleSymbols());
4892 CreateMetadataVar("OBJC_MODULES", values,
John McCall7f416cc2015-09-08 08:05:57 +00004893 "__OBJC,__module_info,regular,no_dead_strip",
4894 CGM.getPointerAlign(), true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004895}
4896
4897llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004898 unsigned NumClasses = DefinedClasses.size();
4899 unsigned NumCategories = DefinedCategories.size();
4900
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004901 // Return null if no symbols were defined.
4902 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00004903 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004904
John McCall176f8922016-11-30 02:39:18 +00004905 ConstantInitBuilder builder(CGM);
4906 auto values = builder.beginStruct();
4907 values.addInt(ObjCTypes.LongTy, 0);
4908 values.addNullPointer(ObjCTypes.SelectorPtrTy);
4909 values.addInt(ObjCTypes.ShortTy, NumClasses);
4910 values.addInt(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004911
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004912 // The runtime expects exactly the list of defined classes followed
4913 // by the list of defined categories, in a single array.
John McCall176f8922016-11-30 02:39:18 +00004914 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00004915 for (unsigned i=0; i<NumClasses; i++) {
4916 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
4917 assert(ID);
4918 if (ObjCImplementationDecl *IMP = ID->getImplementation())
4919 // We are implementing a weak imported interface. Give it external linkage
4920 if (ID->isWeakImported() && !IMP->isWeakImported())
4921 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
John McCall176f8922016-11-30 02:39:18 +00004922
4923 array.addBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00004924 }
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004925 for (unsigned i=0; i<NumCategories; i++)
John McCall176f8922016-11-30 02:39:18 +00004926 array.addBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004927
John McCall176f8922016-11-30 02:39:18 +00004928 array.finishAndAddTo(values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004929
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00004930 llvm::GlobalVariable *GV = CreateMetadataVar(
John McCall176f8922016-11-30 02:39:18 +00004931 "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip",
John McCall7f416cc2015-09-08 08:05:57 +00004932 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00004933 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004934}
4935
John McCall882987f2013-02-28 19:01:20 +00004936llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
4937 IdentifierInfo *II) {
John McCall31168b02011-06-15 23:02:42 +00004938 LazySymbols.insert(II);
4939
4940 llvm::GlobalVariable *&Entry = ClassReferences[II];
4941
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004942 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004943 llvm::Constant *Casted =
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00004944 llvm::ConstantExpr::getBitCast(GetClassName(II->getName()),
John McCall31168b02011-06-15 23:02:42 +00004945 ObjCTypes.ClassPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00004946 Entry = CreateMetadataVar(
4947 "OBJC_CLASS_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00004948 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
4949 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004950 }
John McCall31168b02011-06-15 23:02:42 +00004951
John McCall7f416cc2015-09-08 08:05:57 +00004952 return CGF.Builder.CreateAlignedLoad(Entry, CGF.getPointerAlign());
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004953}
4954
John McCall882987f2013-02-28 19:01:20 +00004955llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00004956 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00004957 // If the class has the objc_runtime_visible attribute, we need to
4958 // use the Objective-C runtime to get the class.
4959 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
4960 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
4961
John McCall882987f2013-02-28 19:01:20 +00004962 return EmitClassRefFromId(CGF, ID->getIdentifier());
John McCall31168b02011-06-15 23:02:42 +00004963}
4964
John McCall882987f2013-02-28 19:01:20 +00004965llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00004966 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
John McCall882987f2013-02-28 19:01:20 +00004967 return EmitClassRefFromId(CGF, II);
John McCall31168b02011-06-15 23:02:42 +00004968}
4969
John McCall7f416cc2015-09-08 08:05:57 +00004970llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
4971 return CGF.Builder.CreateLoad(EmitSelectorAddr(CGF, Sel));
4972}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004973
John McCall7f416cc2015-09-08 08:05:57 +00004974Address CGObjCMac::EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel) {
4975 CharUnits Align = CGF.getPointerAlign();
4976
4977 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004978 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004979 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00004980 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004981 ObjCTypes.SelectorPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00004982 Entry = CreateMetadataVar(
4983 "OBJC_SELECTOR_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00004984 "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true);
Michael Gottesman5c205962013-02-05 23:08:45 +00004985 Entry->setExternallyInitialized(true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004986 }
4987
John McCall7f416cc2015-09-08 08:05:57 +00004988 return Address(Entry, Align);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004989}
4990
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00004991llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
4992 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
4993 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004994 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00004995 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004996}
4997
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004998llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
4999 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
5000 I = MethodDefinitions.find(MD);
5001 if (I != MethodDefinitions.end())
5002 return I->second;
5003
Craig Topper8a13c412014-05-21 05:09:00 +00005004 return nullptr;
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005005}
5006
Fariborz Jahanian01dff422009-03-05 19:17:31 +00005007/// GetIvarLayoutName - Returns a unique constant for the given
5008/// ivar layout bitmap.
5009llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005010 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00005011 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00005012}
5013
John McCall3fd13f062015-10-21 18:06:47 +00005014void IvarLayoutBuilder::visitRecord(const RecordType *RT,
5015 CharUnits offset) {
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005016 const RecordDecl *RD = RT->getDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005017
John McCall3fd13f062015-10-21 18:06:47 +00005018 // If this is a union, remember that we had one, because it might mess
5019 // up the ordering of layout entries.
5020 if (RD->isUnion())
5021 IsDisordered = true;
5022
5023 const ASTRecordLayout *recLayout = nullptr;
5024 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5025 [&](const FieldDecl *field) -> CharUnits {
5026 if (!recLayout)
5027 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5028 auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
5029 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5030 });
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005031}
5032
John McCall3fd13f062015-10-21 18:06:47 +00005033template <class Iterator, class GetOffsetFn>
5034void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
5035 CharUnits aggregateOffset,
5036 const GetOffsetFn &getOffset) {
5037 for (; begin != end; ++begin) {
5038 auto field = *begin;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005039
John McCall3fd13f062015-10-21 18:06:47 +00005040 // Skip over bitfields.
5041 if (field->isBitField()) {
5042 continue;
5043 }
5044
5045 // Compute the offset of the field within the aggregate.
5046 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5047
5048 visitField(field, fieldOffset);
5049 }
5050}
5051
5052/// Collect layout information for the given fields into IvarsInfo.
5053void IvarLayoutBuilder::visitField(const FieldDecl *field,
5054 CharUnits fieldOffset) {
5055 QualType fieldType = field->getType();
5056
5057 // Drill down into arrays.
5058 uint64_t numElts = 1;
5059 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5060 numElts *= arrayType->getSize().getZExtValue();
5061 fieldType = arrayType->getElementType();
5062 }
5063
5064 assert(!fieldType->isArrayType() && "ivar of non-constant array type?");
5065
5066 // If we ended up with a zero-sized array, we've done what we can do within
5067 // the limits of this layout encoding.
5068 if (numElts == 0) return;
5069
5070 // Recurse if the base element type is a record type.
5071 if (auto recType = fieldType->getAs<RecordType>()) {
5072 size_t oldEnd = IvarsInfo.size();
5073
5074 visitRecord(recType, fieldOffset);
5075
5076 // If we have an array, replicate the first entry's layout information.
5077 auto numEltEntries = IvarsInfo.size() - oldEnd;
5078 if (numElts != 1 && numEltEntries != 0) {
5079 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5080 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5081 // Copy the last numEltEntries onto the end of the array, adjusting
5082 // each for the element size.
5083 for (size_t i = 0; i != numEltEntries; ++i) {
5084 auto firstEntry = IvarsInfo[oldEnd + i];
5085 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5086 firstEntry.SizeInWords));
5087 }
5088 }
5089 }
5090
Fariborz Jahanian524bb202009-03-10 16:22:08 +00005091 return;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00005092 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005093
John McCall3fd13f062015-10-21 18:06:47 +00005094 // Classify the element type.
5095 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005096
John McCall3fd13f062015-10-21 18:06:47 +00005097 // If it matches what we're looking for, add an entry.
5098 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
5099 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5100 assert(CGM.getContext().getTypeSizeInChars(fieldType)
5101 == CGM.getPointerSize());
5102 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5103 }
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00005104}
5105
John McCall3fd13f062015-10-21 18:06:47 +00005106/// buildBitmap - This routine does the horsework of taking the offsets of
5107/// strong/weak references and creating a bitmap. The bitmap is also
5108/// returned in the given buffer, suitable for being passed to \c dump().
5109llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5110 llvm::SmallVectorImpl<unsigned char> &buffer) {
5111 // The bitmap is a series of skip/scan instructions, aligned to word
5112 // boundaries. The skip is performed first.
5113 const unsigned char MaxNibble = 0xF;
5114 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5115 const unsigned char ScanMask = 0x0F, ScanShift = 0;
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005116
John McCall3fd13f062015-10-21 18:06:47 +00005117 assert(!IvarsInfo.empty() && "generating bitmap for no data");
5118
5119 // Sort the ivar info on byte position in case we encounterred a
5120 // union nested in the ivar list.
5121 if (IsDisordered) {
5122 // This isn't a stable sort, but our algorithm should handle it fine.
5123 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5124 } else {
Craig Toppera3467052016-01-03 19:43:20 +00005125 assert(std::is_sorted(IvarsInfo.begin(), IvarsInfo.end()));
John McCall3fd13f062015-10-21 18:06:47 +00005126 }
5127 assert(IvarsInfo.back().Offset < InstanceEnd);
5128
5129 assert(buffer.empty());
5130
5131 // Skip the next N words.
5132 auto skip = [&](unsigned numWords) {
5133 assert(numWords > 0);
5134
5135 // Try to merge into the previous byte. Since scans happen second, we
5136 // can't do this if it includes a scan.
5137 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5138 unsigned lastSkip = buffer.back() >> SkipShift;
5139 if (lastSkip < MaxNibble) {
5140 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5141 numWords -= claimed;
5142 lastSkip += claimed;
5143 buffer.back() = (lastSkip << SkipShift);
5144 }
5145 }
5146
5147 while (numWords >= MaxNibble) {
5148 buffer.push_back(MaxNibble << SkipShift);
5149 numWords -= MaxNibble;
5150 }
5151 if (numWords) {
5152 buffer.push_back(numWords << SkipShift);
5153 }
5154 };
5155
5156 // Scan the next N words.
5157 auto scan = [&](unsigned numWords) {
5158 assert(numWords > 0);
5159
5160 // Try to merge into the previous byte. Since scans happen second, we can
5161 // do this even if it includes a skip.
5162 if (!buffer.empty()) {
5163 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5164 if (lastScan < MaxNibble) {
5165 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5166 numWords -= claimed;
5167 lastScan += claimed;
5168 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5169 }
5170 }
5171
5172 while (numWords >= MaxNibble) {
5173 buffer.push_back(MaxNibble << ScanShift);
5174 numWords -= MaxNibble;
5175 }
5176 if (numWords) {
5177 buffer.push_back(numWords << ScanShift);
5178 }
5179 };
5180
5181 // One past the end of the last scan.
5182 unsigned endOfLastScanInWords = 0;
5183 const CharUnits WordSize = CGM.getPointerSize();
5184
5185 // Consider all the scan requests.
5186 for (auto &request : IvarsInfo) {
5187 CharUnits beginOfScan = request.Offset - InstanceBegin;
5188
5189 // Ignore scan requests that don't start at an even multiple of the
5190 // word size. We can't encode them.
5191 if ((beginOfScan % WordSize) != 0) continue;
5192
5193 // Ignore scan requests that start before the instance start.
5194 // This assumes that scans never span that boundary. The boundary
5195 // isn't the true start of the ivars, because in the fragile-ARC case
5196 // it's rounded up to word alignment, but the test above should leave
5197 // us ignoring that possibility.
5198 if (beginOfScan.isNegative()) {
5199 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5200 continue;
5201 }
5202
5203 unsigned beginOfScanInWords = beginOfScan / WordSize;
5204 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5205
5206 // If the scan starts some number of words after the last one ended,
5207 // skip forward.
5208 if (beginOfScanInWords > endOfLastScanInWords) {
5209 skip(beginOfScanInWords - endOfLastScanInWords);
5210
5211 // Otherwise, start scanning where the last left off.
5212 } else {
5213 beginOfScanInWords = endOfLastScanInWords;
5214
5215 // If that leaves us with nothing to scan, ignore this request.
5216 if (beginOfScanInWords >= endOfScanInWords) continue;
5217 }
5218
5219 // Scan to the end of the request.
5220 assert(beginOfScanInWords < endOfScanInWords);
5221 scan(endOfScanInWords - beginOfScanInWords);
5222 endOfLastScanInWords = endOfScanInWords;
5223 }
5224
John McCallf5ea0722015-10-29 23:36:14 +00005225 if (buffer.empty())
5226 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5227
John McCall3fd13f062015-10-21 18:06:47 +00005228 // For GC layouts, emit a skip to the end of the allocation so that we
5229 // have precise information about the entire thing. This isn't useful
5230 // or necessary for the ARC-style layout strings.
5231 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5232 unsigned lastOffsetInWords =
5233 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5234 if (lastOffsetInWords > endOfLastScanInWords) {
5235 skip(lastOffsetInWords - endOfLastScanInWords);
5236 }
5237 }
5238
5239 // Null terminate the string.
5240 buffer.push_back(0);
5241
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005242 auto *Entry = CGObjC.CreateCStringLiteral(
5243 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
John McCall3fd13f062015-10-21 18:06:47 +00005244 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005245}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005246
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005247/// BuildIvarLayout - Builds ivar layout bitmap for the class
5248/// implementation for the __strong or __weak case.
5249/// The layout map displays which words in ivar list must be skipped
5250/// and which must be scanned by GC (see below). String is built of bytes.
5251/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
5252/// of words to skip and right nibble is count of words to scan. So, each
5253/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
5254/// represented by a 0x00 byte which also ends the string.
5255/// 1. when ForStrongLayout is true, following ivars are scanned:
5256/// - id, Class
5257/// - object *
5258/// - __strong anything
5259///
5260/// 2. When ForStrongLayout is false, following ivars are scanned:
5261/// - __weak anything
5262///
John McCall3fd13f062015-10-21 18:06:47 +00005263llvm::Constant *
5264CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5265 CharUnits beginOffset, CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +00005266 bool ForStrongLayout, bool HasMRCWeakIvars) {
5267 // If this is MRC, and we're either building a strong layout or there
5268 // are no weak ivars, bail out early.
Chris Lattnerece04092012-02-07 00:39:47 +00005269 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikiebbafb8a2012-03-11 07:00:24 +00005270 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
John McCall460ce582015-10-22 18:38:17 +00005271 !CGM.getLangOpts().ObjCAutoRefCount &&
5272 (ForStrongLayout || !HasMRCWeakIvars))
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005273 return llvm::Constant::getNullValue(PtrTy);
5274
Jordy Rosea91768e2011-07-22 02:08:32 +00005275 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
John McCall3fd13f062015-10-21 18:06:47 +00005276 SmallVector<const ObjCIvarDecl*, 32> ivars;
5277
5278 // GC layout strings include the complete object layout, possibly
5279 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5280 // up.
5281 //
5282 // ARC layout strings only include the class's ivars. In non-fragile
John McCallf5ea0722015-10-29 23:36:14 +00005283 // runtimes, that means starting at InstanceStart, rounded up to word
5284 // alignment. In fragile runtimes, there's no InstanceStart, so it means
John McCalld80218f2015-11-19 02:27:55 +00005285 // starting at the offset of the first ivar, rounded up to word alignment.
John McCall460ce582015-10-22 18:38:17 +00005286 //
5287 // MRC weak layout strings follow the ARC style.
John McCall3fd13f062015-10-21 18:06:47 +00005288 CharUnits baseOffset;
John McCall460ce582015-10-22 18:38:17 +00005289 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Jordy Rosea91768e2011-07-22 02:08:32 +00005290 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005291 IVD; IVD = IVD->getNextIvar())
John McCall3fd13f062015-10-21 18:06:47 +00005292 ivars.push_back(IVD);
5293
5294 if (isNonFragileABI()) {
5295 baseOffset = beginOffset; // InstanceStart
John McCalld80218f2015-11-19 02:27:55 +00005296 } else if (!ivars.empty()) {
5297 baseOffset =
5298 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
John McCall3fd13f062015-10-21 18:06:47 +00005299 } else {
5300 baseOffset = CharUnits::Zero();
5301 }
John McCallf5ea0722015-10-29 23:36:14 +00005302
Rui Ueyama83aa9792016-01-14 21:00:27 +00005303 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005304 }
5305 else {
John McCall3fd13f062015-10-21 18:06:47 +00005306 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005307
John McCall3fd13f062015-10-21 18:06:47 +00005308 baseOffset = CharUnits::Zero();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005309 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005310
John McCall3fd13f062015-10-21 18:06:47 +00005311 if (ivars.empty())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005312 return llvm::Constant::getNullValue(PtrTy);
5313
John McCall3fd13f062015-10-21 18:06:47 +00005314 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005315
John McCall3fd13f062015-10-21 18:06:47 +00005316 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5317 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5318 return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
5319 });
5320
5321 if (!builder.hasBitmapData())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005322 return llvm::Constant::getNullValue(PtrTy);
John McCall3fd13f062015-10-21 18:06:47 +00005323
5324 llvm::SmallVector<unsigned char, 4> buffer;
5325 llvm::Constant *C = builder.buildBitmap(*this, buffer);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005326
John McCallf5ea0722015-10-29 23:36:14 +00005327 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005328 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005329 ForStrongLayout ? "strong" : "weak",
Ben Langmuire013bdc2014-07-11 00:43:47 +00005330 OMD->getClassInterface()->getName().str().c_str());
John McCall3fd13f062015-10-21 18:06:47 +00005331 builder.dump(buffer);
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005332 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005333 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00005334}
5335
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005336llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005337 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
Chris Lattner3def9ae2012-02-06 22:16:34 +00005338 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005339 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005340 Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
Owen Anderson170229f2009-07-14 23:10:40 +00005341 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005342}
5343
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005344// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005345llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005346 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5347}
5348
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005349llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005350 std::string TypeStr;
5351 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5352
5353 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005354 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005355 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005356 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005357}
5358
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005359llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5360 bool Extended) {
John McCall843dfcc2016-11-29 21:57:00 +00005361 std::string TypeStr =
5362 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005363
5364 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbar3241fae2009-04-14 23:14:47 +00005365 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005366 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005367 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005368}
5369
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005370// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005371llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005372 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005373 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005374 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
Owen Anderson170229f2009-07-14 23:10:40 +00005375 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005376}
5377
5378// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00005379// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005380llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005381CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5382 const Decl *Container) {
John McCall843dfcc2016-11-29 21:57:00 +00005383 std::string TypeStr =
5384 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005385 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5386}
5387
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005388void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005389 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005390 SmallVectorImpl<char> &Name) {
Daniel Dunbard2386812009-10-19 01:21:19 +00005391 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00005392 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00005393 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
5394 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005395 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00005396 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer2f569922012-02-07 11:57:45 +00005397 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00005398 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00005399}
5400
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005401void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005402 EmitModuleInfo();
5403
Daniel Dunbarc475d422008-10-29 22:36:39 +00005404 // Emit the dummy bodies for any protocols which were referenced but
5405 // never defined.
John McCall176f8922016-11-30 02:39:18 +00005406 for (auto &entry : Protocols) {
5407 llvm::GlobalVariable *global = entry.second;
5408 if (global->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00005409 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005410
John McCall176f8922016-11-30 02:39:18 +00005411 ConstantInitBuilder builder(CGM);
5412 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5413 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5414 values.add(GetClassName(entry.first->getName()));
5415 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5416 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5417 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5418 values.finishAndSetAsInitializer(global);
5419 CGM.addCompilerUsedGlobal(global);
Daniel Dunbarc475d422008-10-29 22:36:39 +00005420 }
5421
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005422 // Add assembler directives to add lazy undefined symbol references
5423 // for classes which are referenced but not defined. This is
5424 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00005425 //
5426 // FIXME: It would be nice if we had an LLVM construct for this.
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005427 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5428 CGM.getTriple().isOSBinFormatMachO()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005429 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00005430 Asm += CGM.getModule().getModuleInlineAsm();
5431 if (!Asm.empty() && Asm.back() != '\n')
5432 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005433
Daniel Dunbard027a922009-09-07 00:20:42 +00005434 llvm::raw_svector_ostream OS(Asm);
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005435 for (const auto *Sym : DefinedSymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005436 OS << "\t.objc_class_name_" << Sym->getName() << "=0\n"
5437 << "\t.globl .objc_class_name_" << Sym->getName() << "\n";
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005438 for (const auto *Sym : LazySymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005439 OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n";
5440 for (const auto &Category : DefinedCategoryNames)
5441 OS << "\t.objc_category_name_" << Category << "=0\n"
5442 << "\t.globl .objc_category_name_" << Category << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00005443
Daniel Dunbard027a922009-09-07 00:20:42 +00005444 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005445 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005446}
5447
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005448CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00005449 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5450 ObjCEmptyVtableVar(nullptr) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005451 ObjCABI = 2;
5452}
5453
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005454/* *** */
5455
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005456ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Craig Topper8a13c412014-05-21 05:09:00 +00005457 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00005458{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005459 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5460 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005461
John McCall176f8922016-11-30 02:39:18 +00005462 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5463 IntTy = CGM.IntTy;
5464 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
Chris Lattnerece04092012-02-07 00:39:47 +00005465 Int8PtrTy = CGM.Int8PtrTy;
5466 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005467
Tim Northover238b5082014-03-29 13:42:40 +00005468 // arm64 targets use "int" ivar offset variables. All others,
5469 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
Tim Northover40956e62014-07-23 12:32:58 +00005470 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
Tim Northover238b5082014-03-29 13:42:40 +00005471 IvarOffsetVarTy = IntTy;
5472 else
5473 IvarOffsetVarTy = LongTy;
5474
John McCall176f8922016-11-30 02:39:18 +00005475 ObjectPtrTy =
5476 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5477 PtrObjectPtrTy =
5478 llvm::PointerType::getUnqual(ObjectPtrTy);
5479 SelectorPtrTy =
5480 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005481
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005482 // I'm not sure I like this. The implicit coordination is a bit
5483 // gross. We should solve this in a reasonable fashion because this
5484 // is a pretty common task (match some runtime data structure with
5485 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005486
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005487 // FIXME: This is leaked.
5488 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005489
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005490 // struct _objc_super {
5491 // id self;
5492 // Class cls;
5493 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00005494 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005495 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005496 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005497 &Ctx.Idents.get("_objc_super"));
Craig Topper8a13c412014-05-21 05:09:00 +00005498 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5499 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5500 false, ICIS_NoInit));
5501 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5502 nullptr, Ctx.getObjCClassType(), nullptr,
5503 nullptr, false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005504 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005505
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005506 SuperCTy = Ctx.getTagDeclType(RD);
5507 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005508
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005509 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005510 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5511
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005512 // struct _prop_t {
5513 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005514 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005515 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005516 PropertyTy = llvm::StructType::create("struct._prop_t",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005517 Int8PtrTy, Int8PtrTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005518
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005519 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005520 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005521 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005522 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005523 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005524 PropertyListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005525 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005526 llvm::ArrayType::get(PropertyTy, 0), nullptr);
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005527 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005528 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005529
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005530 // struct _objc_method {
5531 // SEL _cmd;
5532 // char *method_type;
5533 // char *_imp;
5534 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005535 MethodTy = llvm::StructType::create("struct._objc_method",
5536 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005537 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005538
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005539 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00005540 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005541 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005542}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005543
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005544ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005545 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005546 // struct _objc_method_description {
5547 // SEL name;
5548 // char *types;
5549 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005550 MethodDescriptionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005551 llvm::StructType::create("struct._objc_method_description",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005552 SelectorPtrTy, Int8PtrTy, nullptr);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005553
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005554 // struct _objc_method_description_list {
5555 // int count;
5556 // struct _objc_method_description[1];
5557 // }
Reid Kleckneree7cf842014-12-01 22:02:27 +00005558 MethodDescriptionListTy = llvm::StructType::create(
5559 "struct._objc_method_description_list", IntTy,
5560 llvm::ArrayType::get(MethodDescriptionTy, 0), nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005561
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005562 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005563 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005564 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005565
Daniel Dunbarb036db82008-08-13 03:21:16 +00005566 // Protocol description structures
5567
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005568 // struct _objc_protocol_extension {
5569 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5570 // struct _objc_method_description_list *optional_instance_methods;
5571 // struct _objc_method_description_list *optional_class_methods;
5572 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005573 // const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00005574 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005575 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005576 ProtocolExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005577 llvm::StructType::create("struct._objc_protocol_extension",
5578 IntTy, MethodDescriptionListPtrTy,
5579 MethodDescriptionListPtrTy, PropertyListPtrTy,
Manman Rence7bff52016-01-29 23:46:55 +00005580 Int8PtrPtrTy, PropertyListPtrTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005581
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005582 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005583 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005584
Daniel Dunbarc475d422008-10-29 22:36:39 +00005585 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00005586
Chris Lattnera5f58b02011-07-09 17:41:47 +00005587 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005588 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00005589
Chris Lattnera5f58b02011-07-09 17:41:47 +00005590 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005591 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005592 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005593 LongTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00005594 llvm::ArrayType::get(ProtocolTy, 0),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005595 nullptr);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005596
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005597 // struct _objc_protocol {
5598 // struct _objc_protocol_extension *isa;
5599 // char *protocol_name;
5600 // struct _objc_protocol **_objc_protocol_list;
5601 // struct _objc_method_description_list *instance_methods;
5602 // struct _objc_method_description_list *class_methods;
5603 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005604 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5605 llvm::PointerType::getUnqual(ProtocolListTy),
5606 MethodDescriptionListPtrTy,
5607 MethodDescriptionListPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005608 nullptr);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005609
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005610 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005611 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005612
Owen Anderson9793f0e2009-07-29 22:16:19 +00005613 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005614
5615 // Class description structures
5616
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005617 // struct _objc_ivar {
5618 // char *ivar_name;
5619 // char *ivar_type;
5620 // int ivar_offset;
5621 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005622 IvarTy = llvm::StructType::create("struct._objc_ivar",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005623 Int8PtrTy, Int8PtrTy, IntTy, nullptr);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005624
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005625 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005626 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005627 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005628 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005629
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005630 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005631 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005632 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005633 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005634
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005635 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005636 ClassExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005637 llvm::StructType::create("struct._objc_class_extension",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005638 IntTy, Int8PtrTy, PropertyListPtrTy, nullptr);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005639 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005640
Chris Lattner5ec04a52011-08-12 17:43:31 +00005641 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005642
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005643 // struct _objc_class {
5644 // Class isa;
5645 // Class super_class;
5646 // char *name;
5647 // long version;
5648 // long info;
5649 // long instance_size;
5650 // struct _objc_ivar_list *ivars;
5651 // struct _objc_method_list *methods;
5652 // struct _objc_cache *cache;
5653 // struct _objc_protocol_list *protocols;
5654 // char *ivar_layout;
5655 // struct _objc_class_ext *ext;
5656 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005657 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
5658 llvm::PointerType::getUnqual(ClassTy),
5659 Int8PtrTy,
5660 LongTy,
5661 LongTy,
5662 LongTy,
5663 IvarListPtrTy,
5664 MethodListPtrTy,
5665 CachePtrTy,
5666 ProtocolListPtrTy,
5667 Int8PtrTy,
5668 ClassExtensionPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005669 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005670
Owen Anderson9793f0e2009-07-29 22:16:19 +00005671 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005672
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005673 // struct _objc_category {
5674 // char *category_name;
5675 // char *class_name;
5676 // struct _objc_method_list *instance_method;
5677 // struct _objc_method_list *class_method;
Manman Renb3736772016-01-25 22:37:47 +00005678 // struct _objc_protocol_list *protocols;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005679 // uint32_t size; // sizeof(struct _objc_category)
5680 // struct _objc_property_list *instance_properties;// category's @property
Manman Ren96df0b32016-01-29 23:45:01 +00005681 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005682 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005683 CategoryTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005684 llvm::StructType::create("struct._objc_category",
5685 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5686 MethodListPtrTy, ProtocolListPtrTy,
Manman Ren96df0b32016-01-29 23:45:01 +00005687 IntTy, PropertyListPtrTy, PropertyListPtrTy,
5688 nullptr);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005689
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005690 // Global metadata structures
5691
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005692 // struct _objc_symtab {
5693 // long sel_ref_cnt;
5694 // SEL *refs;
5695 // short cls_def_cnt;
5696 // short cat_def_cnt;
5697 // char *defs[cls_def_cnt + cat_def_cnt];
5698 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005699 SymtabTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005700 llvm::StructType::create("struct._objc_symtab",
5701 LongTy, SelectorPtrTy, ShortTy, ShortTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005702 llvm::ArrayType::get(Int8PtrTy, 0), nullptr);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005703 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005704
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00005705 // struct _objc_module {
5706 // long version;
5707 // long size; // sizeof(struct _objc_module)
5708 // char *name;
5709 // struct _objc_symtab* symtab;
5710 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005711 ModuleTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005712 llvm::StructType::create("struct._objc_module",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005713 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, nullptr);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00005714
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005715
Mike Stump18bb9282009-05-16 07:57:57 +00005716 // FIXME: This is the size of the setjmp buffer and should be target
5717 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00005718 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005719
Anders Carlsson9ff22482008-09-09 10:10:21 +00005720 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00005721 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005722
5723 ExceptionDataTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005724 llvm::StructType::create("struct._objc_exception_data",
Chris Lattnerece04092012-02-07 00:39:47 +00005725 llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005726 StackPtrTy, nullptr);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005727}
5728
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005729ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005730 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005731 // struct _method_list_t {
5732 // uint32_t entsize; // sizeof(struct _objc_method)
5733 // uint32_t method_count;
5734 // struct _objc_method method_list[method_count];
5735 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005736 MethodListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005737 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005738 llvm::ArrayType::get(MethodTy, 0), nullptr);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005739 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005740 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005741
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005742 // struct _protocol_t {
5743 // id isa; // NULL
5744 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005745 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005746 // const struct method_list_t * const instance_methods;
5747 // const struct method_list_t * const class_methods;
5748 // const struct method_list_t *optionalInstanceMethods;
5749 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005750 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005751 // const uint32_t size; // sizeof(struct _protocol_t)
5752 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005753 // const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00005754 // const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00005755 // const struct _prop_list_t * class_properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005756 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005757
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005758 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005759 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005760 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005761
Chris Lattnera5f58b02011-07-09 17:41:47 +00005762 ProtocolnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005763 llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
5764 llvm::PointerType::getUnqual(ProtocolListnfABITy),
5765 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5766 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005767 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
Manman Rence7bff52016-01-29 23:46:55 +00005768 Int8PtrTy, PropertyListPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005769 nullptr);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005770
5771 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005772 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005773
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005774 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005775 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005776 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005777 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005778 ProtocolListnfABITy->setBody(LongTy,
5779 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005780 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005781
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005782 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005783 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005784
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005785 // struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00005786 // unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005787 // char *name;
5788 // char *type;
5789 // uint32_t alignment;
5790 // uint32_t size;
5791 // }
Tim Northover238b5082014-03-29 13:42:40 +00005792 IvarnfABITy = llvm::StructType::create(
5793 "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005794 Int8PtrTy, Int8PtrTy, IntTy, IntTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005795
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005796 // struct _ivar_list_t {
5797 // uint32 entsize; // sizeof(struct _ivar_t)
5798 // uint32 count;
5799 // struct _iver_t list[count];
5800 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005801 IvarListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005802 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005803 llvm::ArrayType::get(IvarnfABITy, 0), nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005804
Owen Anderson9793f0e2009-07-29 22:16:19 +00005805 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005806
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005807 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005808 // uint32_t const flags;
5809 // uint32_t const instanceStart;
5810 // uint32_t const instanceSize;
5811 // uint32_t const reserved; // only when building for 64bit targets
5812 // const uint8_t * const ivarLayout;
5813 // const char *const name;
5814 // const struct _method_list_t * const baseMethods;
5815 // const struct _objc_protocol_list *const baseProtocols;
5816 // const struct _ivar_list_t *const ivars;
5817 // const uint8_t * const weakIvarLayout;
5818 // const struct _prop_list_t * const properties;
5819 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005820
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005821 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattner5ec04a52011-08-12 17:43:31 +00005822 ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
5823 IntTy, IntTy, IntTy, Int8PtrTy,
5824 Int8PtrTy, MethodListnfABIPtrTy,
5825 ProtocolListnfABIPtrTy,
5826 IvarListnfABIPtrTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005827 Int8PtrTy, PropertyListPtrTy,
5828 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005829
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005830 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00005831 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00005832 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
5833 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005834
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005835 // struct _class_t {
5836 // struct _class_t *isa;
5837 // struct _class_t * const superclass;
5838 // void *cache;
5839 // IMP *vtable;
5840 // struct class_ro_t *ro;
5841 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005842
Chris Lattner5ec04a52011-08-12 17:43:31 +00005843 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005844 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
5845 llvm::PointerType::getUnqual(ClassnfABITy),
5846 CachePtrTy,
5847 llvm::PointerType::getUnqual(ImpnfABITy),
5848 llvm::PointerType::getUnqual(ClassRonfABITy),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005849 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005850
Fariborz Jahanian71394042009-01-23 23:53:38 +00005851 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005852 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005853
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005854 // struct _category_t {
5855 // const char * const name;
5856 // struct _class_t *const cls;
5857 // const struct _method_list_t * const instance_methods;
5858 // const struct _method_list_t * const class_methods;
5859 // const struct _protocol_list_t * const protocols;
5860 // const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00005861 // const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00005862 // const uint32_t size;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00005863 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005864 CategorynfABITy = llvm::StructType::create("struct._category_t",
5865 Int8PtrTy, ClassnfABIPtrTy,
5866 MethodListnfABIPtrTy,
5867 MethodListnfABIPtrTy,
5868 ProtocolListnfABIPtrTy,
5869 PropertyListPtrTy,
Manman Ren96df0b32016-01-29 23:45:01 +00005870 PropertyListPtrTy,
Manman Ren42ff3902016-02-24 17:49:50 +00005871 IntTy,
Reid Kleckneree7cf842014-12-01 22:02:27 +00005872 nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005873
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005874 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005875 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5876 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005877
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005878 // MessageRefTy - LLVM for:
5879 // struct _message_ref_t {
5880 // IMP messenger;
5881 // SEL name;
5882 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005883
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005884 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00005885 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005886 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005887 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005888 &Ctx.Idents.get("_message_ref_t"));
Craig Topper8a13c412014-05-21 05:09:00 +00005889 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5890 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
Richard Smith2b013182012-06-10 03:12:00 +00005891 ICIS_NoInit));
Craig Topper8a13c412014-05-21 05:09:00 +00005892 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5893 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
5894 false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005895 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005896
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005897 MessageRefCTy = Ctx.getTagDeclType(RD);
5898 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
5899 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005900
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005901 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005902 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005903
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005904 // SuperMessageRefTy - LLVM for:
5905 // struct _super_message_ref_t {
5906 // SUPER_IMP messenger;
5907 // SEL name;
5908 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005909 SuperMessageRefTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005910 llvm::StructType::create("struct._super_message_ref_t",
Reid Kleckneree7cf842014-12-01 22:02:27 +00005911 ImpnfABITy, SelectorPtrTy, nullptr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005912
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005913 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005914 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005915
Daniel Dunbarb1559a42009-03-01 04:46:24 +00005916
5917 // struct objc_typeinfo {
5918 // const void** vtable; // objc_ehtype_vtable + 2
5919 // const char* name; // c++ typeinfo string
5920 // Class cls;
5921 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005922 EHTypeTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005923 llvm::StructType::create("struct._objc_typeinfo",
5924 llvm::PointerType::getUnqual(Int8PtrTy),
Reid Kleckneree7cf842014-12-01 22:02:27 +00005925 Int8PtrTy, ClassnfABIPtrTy, nullptr);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005926 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005927}
5928
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005929llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00005930 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005931
Craig Topper8a13c412014-05-21 05:09:00 +00005932 return nullptr;
Fariborz Jahanian71394042009-01-23 23:53:38 +00005933}
5934
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00005935void CGObjCNonFragileABIMac::AddModuleClassList(
5936 ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
5937 StringRef SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00005938 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005939
Daniel Dunbar19573e72009-05-15 21:48:48 +00005940 if (!NumClasses)
5941 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005942
Chris Lattner3def9ae2012-02-06 22:16:34 +00005943 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005944 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00005945 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00005946 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00005947 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005948 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00005949 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00005950 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005951
Daniel Dunbar19573e72009-05-15 21:48:48 +00005952 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005953 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00005954 llvm::GlobalValue::PrivateLinkage,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005955 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005956 SymbolName);
Micah Villmowdd31ca12012-10-08 16:25:52 +00005957 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00005958 GV->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00005959 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005960}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005961
Fariborz Jahanian71394042009-01-23 23:53:38 +00005962void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
5963 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005964
Daniel Dunbar19573e72009-05-15 21:48:48 +00005965 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005966 // L_OBJC_LABEL_CLASS_$.
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005967
5968 for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) {
5969 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5970 assert(ID);
5971 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5972 // We are implementing a weak imported interface. Give it external linkage
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00005973 if (ID->isWeakImported() && !IMP->isWeakImported()) {
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005974 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00005975 DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5976 }
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005977 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005978
5979 AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$",
Daniel Dunbar19573e72009-05-15 21:48:48 +00005980 "__DATA, __objc_classlist, regular, no_dead_strip");
Rafael Espindola554256c2014-02-26 22:25:45 +00005981
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005982 AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$",
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005983 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005984
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005985 // Build list of all implemented category addresses in array
5986 // L_OBJC_LABEL_CATEGORY_$.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005987 AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$",
Daniel Dunbar19573e72009-05-15 21:48:48 +00005988 "__DATA, __objc_catlist, regular, no_dead_strip");
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005989 AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$",
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005990 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005991
Daniel Dunbar5e639272010-04-25 20:39:01 +00005992 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005993}
5994
John McCall9e8bb002011-05-14 03:10:52 +00005995/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
5996/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005997/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005998/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00005999bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
6000 // At various points we've experimented with using vtable-based
6001 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006002 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006003 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00006004 return false;
John McCall9e8bb002011-05-14 03:10:52 +00006005 case CodeGenOptions::NonLegacy:
6006 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006007 case CodeGenOptions::Mixed:
6008 break;
6009 }
6010
6011 // If so, see whether this selector is in the white-list of things which must
6012 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00006013 if (VTableDispatchMethods.empty()) {
6014 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
6015 VTableDispatchMethods.insert(GetNullarySelector("class"));
6016 VTableDispatchMethods.insert(GetNullarySelector("self"));
6017 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
6018 VTableDispatchMethods.insert(GetNullarySelector("length"));
6019 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006020
John McCall9e8bb002011-05-14 03:10:52 +00006021 // These are vtable-based if GC is disabled.
6022 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006023 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00006024 VTableDispatchMethods.insert(GetNullarySelector("retain"));
6025 VTableDispatchMethods.insert(GetNullarySelector("release"));
6026 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
6027 }
6028
6029 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
6030 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
6031 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
6032 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
6033 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
6034 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
6035 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
6036
6037 // These are vtable-based if GC is enabled.
6038 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006039 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00006040 VTableDispatchMethods.insert(GetNullarySelector("hash"));
6041 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
6042
6043 // "countByEnumeratingWithState:objects:count"
6044 IdentifierInfo *KeyIdents[] = {
6045 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
6046 &CGM.getContext().Idents.get("objects"),
6047 &CGM.getContext().Idents.get("count")
6048 };
6049 VTableDispatchMethods.insert(
6050 CGM.getContext().Selectors.getSelector(3, KeyIdents));
6051 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006052 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006053
John McCall9e8bb002011-05-14 03:10:52 +00006054 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006055}
6056
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006057/// BuildClassRoTInitializer - generate meta-data for:
6058/// struct _class_ro_t {
6059/// uint32_t const flags;
6060/// uint32_t const instanceStart;
6061/// uint32_t const instanceSize;
6062/// uint32_t const reserved; // only when building for 64bit targets
6063/// const uint8_t * const ivarLayout;
6064/// const char *const name;
6065/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006066/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006067/// const struct _ivar_list_t *const ivars;
6068/// const uint8_t * const weakIvarLayout;
6069/// const struct _prop_list_t * const properties;
6070/// }
6071///
6072llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006073 unsigned flags,
6074 unsigned InstanceStart,
6075 unsigned InstanceSize,
6076 const ObjCImplementationDecl *ID) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006077 std::string ClassName = ID->getObjCRuntimeNameAsString();
John McCall31168b02011-06-15 23:02:42 +00006078
John McCall3fd13f062015-10-21 18:06:47 +00006079 CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
6080 CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
6081
John McCall460ce582015-10-22 18:38:17 +00006082 bool hasMRCWeak = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00006083 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCallef19dbb2012-10-17 04:53:23 +00006084 flags |= NonFragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00006085 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
6086 flags |= NonFragileABI_Class_HasMRCWeakIvars;
John McCall31168b02011-06-15 23:02:42 +00006087
John McCall176f8922016-11-30 02:39:18 +00006088 ConstantInitBuilder builder(CGM);
6089 auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
6090
6091 values.addInt(ObjCTypes.IntTy, flags);
6092 values.addInt(ObjCTypes.IntTy, InstanceStart);
6093 values.addInt(ObjCTypes.IntTy, InstanceSize);
6094 values.add((flags & NonFragileABI_Class_Meta)
6095 ? GetIvarLayoutName(nullptr, ObjCTypes)
6096 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
6097 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
6098
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006099 // const struct _method_list_t * const baseMethods;
John McCall176f8922016-11-30 02:39:18 +00006100 SmallVector<const ObjCMethodDecl*, 16> methods;
John McCallef19dbb2012-10-17 04:53:23 +00006101 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00006102 for (const auto *MD : ID->class_methods())
6103 methods.push_back(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006104 } else {
John McCall176f8922016-11-30 02:39:18 +00006105 for (const auto *MD : ID->instance_methods())
6106 methods.push_back(MD);
Aaron Ballmanf26acce2014-03-13 19:50:17 +00006107
Aaron Ballmand85eff42014-03-14 15:02:45 +00006108 for (const auto *PID : ID->property_impls()) {
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00006109 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
6110 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006111
John McCall176f8922016-11-30 02:39:18 +00006112 if (auto MD = PD->getGetterMethodDecl())
6113 if (GetMethodDefinition(MD))
6114 methods.push_back(MD);
6115 if (auto MD = PD->getSetterMethodDecl())
6116 if (GetMethodDefinition(MD))
6117 methods.push_back(MD);
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00006118 }
6119 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006120 }
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006121
John McCall176f8922016-11-30 02:39:18 +00006122 values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
6123 (flags & NonFragileABI_Class_Meta)
6124 ? MethodListType::ClassMethods
6125 : MethodListType::InstanceMethods,
6126 methods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006127
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006128 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6129 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
John McCall176f8922016-11-30 02:39:18 +00006130 values.add(EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006131 + OID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006132 OID->all_referenced_protocol_begin(),
6133 OID->all_referenced_protocol_end()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006134
John McCallef19dbb2012-10-17 04:53:23 +00006135 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00006136 values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
6137 values.add(GetIvarLayoutName(nullptr, ObjCTypes));
6138 values.add(EmitPropertyList(
Manman Renad0e7912016-01-29 19:22:54 +00006139 "\01l_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006140 ID, ID->getClassInterface(), ObjCTypes, true));
John McCallef19dbb2012-10-17 04:53:23 +00006141 } else {
John McCall176f8922016-11-30 02:39:18 +00006142 values.add(EmitIvarList(ID));
6143 values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
6144 values.add(EmitPropertyList(
Manman Renad0e7912016-01-29 19:22:54 +00006145 "\01l_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006146 ID, ID->getClassInterface(), ObjCTypes, false));
John McCallef19dbb2012-10-17 04:53:23 +00006147 }
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006148
John McCall176f8922016-11-30 02:39:18 +00006149 llvm::SmallString<64> roLabel;
6150 llvm::raw_svector_ostream(roLabel)
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006151 << ((flags & NonFragileABI_Class_Meta) ? "\01l_OBJC_METACLASS_RO_$_"
6152 : "\01l_OBJC_CLASS_RO_$_")
6153 << ClassName;
6154
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006155 llvm::GlobalVariable *CLASS_RO_GV =
John McCall176f8922016-11-30 02:39:18 +00006156 values.finishAndCreateGlobal(roLabel, CGM.getPointerAlign(),
6157 /*constant*/ false,
6158 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006159 if (CGM.getTriple().isOSBinFormatMachO())
6160 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006161 return CLASS_RO_GV;
6162}
6163
6164/// BuildClassMetaData - This routine defines that to-level meta-data
6165/// for the given ClassName for:
6166/// struct _class_t {
6167/// struct _class_t *isa;
6168/// struct _class_t * const superclass;
6169/// void *cache;
6170/// IMP *vtable;
6171/// struct class_ro_t *ro;
6172/// }
6173///
Rafael Espindola554256c2014-02-26 22:25:45 +00006174llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassMetaData(
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006175 const std::string &ClassName, llvm::Constant *IsAGV, llvm::Constant *SuperClassGV,
Rafael Espindola554256c2014-02-26 22:25:45 +00006176 llvm::Constant *ClassRoGV, bool HiddenVisibility, bool Weak) {
John McCall176f8922016-11-30 02:39:18 +00006177 ConstantInitBuilder builder(CGM);
6178 auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
6179 values.add(IsAGV);
6180 if (SuperClassGV) {
6181 values.add(SuperClassGV);
6182 } else {
6183 values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
6184 }
6185 values.add(ObjCEmptyCacheVar);
6186 values.add(ObjCEmptyVtableVar);
6187 values.add(ClassRoGV);
6188
Rafael Espindola554256c2014-02-26 22:25:45 +00006189 llvm::GlobalVariable *GV = GetClassGlobal(ClassName, Weak);
John McCall176f8922016-11-30 02:39:18 +00006190 values.finishAndSetAsInitializer(GV);
6191
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006192 if (CGM.getTriple().isOSBinFormatMachO())
6193 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006194 GV->setAlignment(
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006195 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006196 if (!CGM.getTriple().isOSBinFormatCOFF())
6197 if (HiddenVisibility)
6198 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006199 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006200}
6201
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006202bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00006203CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Craig Topper8a13c412014-05-21 05:09:00 +00006204 return OD->getClassMethod(GetNullarySelector("load")) != nullptr;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006205}
6206
Daniel Dunbar961202372009-05-03 12:57:56 +00006207void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00006208 uint32_t &InstanceStart,
6209 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006210 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00006211 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006212
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006213 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00006214 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006215
6216 // If there are no fields, the start is the same as the end.
6217 if (!RL.getFieldCount())
6218 InstanceStart = InstanceSize;
6219 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00006220 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00006221}
6222
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006223static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
6224 StringRef Name) {
6225 IdentifierInfo &II = CGM.getContext().Idents.get(Name);
6226 TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
6227 DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
6228
6229 const VarDecl *VD = nullptr;
6230 for (const auto &Result : DC->lookup(&II))
6231 if ((VD = dyn_cast<VarDecl>(Result)))
6232 break;
6233
6234 if (!VD)
6235 return llvm::GlobalValue::DLLImportStorageClass;
6236 if (VD->hasAttr<DLLExportAttr>())
6237 return llvm::GlobalValue::DLLExportStorageClass;
6238 if (VD->hasAttr<DLLImportAttr>())
6239 return llvm::GlobalValue::DLLImportStorageClass;
6240 return llvm::GlobalValue::DefaultStorageClass;
6241}
6242
Fariborz Jahanian71394042009-01-23 23:53:38 +00006243void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00006244 if (!ObjCEmptyCacheVar) {
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006245 ObjCEmptyCacheVar =
6246 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false,
6247 llvm::GlobalValue::ExternalLinkage, nullptr,
6248 "_objc_empty_cache");
6249 if (CGM.getTriple().isOSBinFormatCOFF())
6250 ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache"));
Craig Topper8a13c412014-05-21 05:09:00 +00006251
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006252 // Only OS X with deployment version <10.9 use the empty vtable symbol
Fariborz Jahanian42d49552013-10-24 17:40:28 +00006253 const llvm::Triple &Triple = CGM.getTarget().getTriple();
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006254 if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006255 ObjCEmptyVtableVar =
6256 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false,
6257 llvm::GlobalValue::ExternalLinkage, nullptr,
6258 "_objc_empty_vtable");
John McCall176f8922016-11-30 02:39:18 +00006259 else
6260 ObjCEmptyVtableVar =
6261 llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
Fariborz Jahanian71394042009-01-23 23:53:38 +00006262 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006263
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00006264 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006265 uint32_t InstanceStart =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006266 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006267 uint32_t InstanceSize = InstanceStart;
John McCallef19dbb2012-10-17 04:53:23 +00006268 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006269
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006270 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006271
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006272 StringRef ClassName = ID->getObjCRuntimeNameAsString();
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006273 const auto *CI = ID->getClassInterface();
6274 assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0");
6275
John McCall0d54a172012-10-17 04:53:31 +00006276 // Build the flags for the metaclass.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006277 bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
6278 ? !CI->hasAttr<DLLExportAttr>()
6279 : CI->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006280 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006281 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006282
6283 // FIXME: why is this flag set on the metaclass?
6284 // ObjC metaclasses have no fields and don't really get constructed.
6285 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006286 flags |= NonFragileABI_Class_HasCXXStructors;
John McCall0d54a172012-10-17 04:53:31 +00006287 if (!ID->hasNonZeroConstructors())
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006288 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
John McCall0d54a172012-10-17 04:53:31 +00006289 }
6290
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006291 if (!CI->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006292 // class is root
John McCallef19dbb2012-10-17 04:53:23 +00006293 flags |= NonFragileABI_Class_Root;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006294
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006295 SuperClassGV = GetClassGlobal((getClassSymbolPrefix() + ClassName).str(),
6296 CI->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006297 if (CGM.getTriple().isOSBinFormatCOFF())
6298 if (CI->hasAttr<DLLImportAttr>())
6299 SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006300
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006301 IsAGV = GetClassGlobal((getMetaclassSymbolPrefix() + ClassName).str(),
6302 CI->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006303 if (CGM.getTriple().isOSBinFormatCOFF())
6304 if (CI->hasAttr<DLLImportAttr>())
6305 IsAGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006306 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006307 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00006308 const ObjCInterfaceDecl *Root = ID->getClassInterface();
6309 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
6310 Root = Super;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006311
6312 const auto *Super = CI->getSuperClass();
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006313 StringRef RootClassName = Root->getObjCRuntimeNameAsString();
6314 StringRef SuperClassName = Super->getObjCRuntimeNameAsString();
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006315
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006316 IsAGV = GetClassGlobal((getMetaclassSymbolPrefix() + RootClassName).str(),
6317 Root->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006318 if (CGM.getTriple().isOSBinFormatCOFF())
6319 if (Root->hasAttr<DLLImportAttr>())
6320 IsAGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006321
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00006322 // work on super class metadata symbol.
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006323 SuperClassGV =
6324 GetClassGlobal((getMetaclassSymbolPrefix() + SuperClassName).str(),
6325 Super->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006326 if (CGM.getTriple().isOSBinFormatCOFF())
6327 if (Super->hasAttr<DLLImportAttr>())
6328 SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006329 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006330
6331 llvm::GlobalVariable *CLASS_RO_GV =
6332 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6333
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006334 llvm::GlobalVariable *MetaTClass =
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006335 BuildClassMetaData((getMetaclassSymbolPrefix() + ClassName).str(), IsAGV,
6336 SuperClassGV, CLASS_RO_GV, classIsHidden,
6337 CI->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006338 if (CGM.getTriple().isOSBinFormatCOFF())
6339 if (CI->hasAttr<DLLExportAttr>())
6340 MetaTClass->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Fariborz Jahanian67260552009-11-17 21:37:35 +00006341 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00006342
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006343 // Metadata for the class
John McCallef19dbb2012-10-17 04:53:23 +00006344 flags = 0;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006345 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006346 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006347
6348 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006349 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006350
John McCall0d54a172012-10-17 04:53:31 +00006351 // Set a flag to enable a runtime optimization when a class has
6352 // fields that require destruction but which don't require
6353 // anything except zero-initialization during construction. This
6354 // is most notably true of __strong and __weak types, but you can
6355 // also imagine there being C++ types with non-trivial default
6356 // constructors that merely set all fields to null.
6357 if (!ID->hasNonZeroConstructors())
6358 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6359 }
6360
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006361 if (hasObjCExceptionAttribute(CGM.getContext(), CI))
John McCallef19dbb2012-10-17 04:53:23 +00006362 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006363
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006364 if (!CI->getSuperClass()) {
John McCallef19dbb2012-10-17 04:53:23 +00006365 flags |= NonFragileABI_Class_Root;
Craig Topper8a13c412014-05-21 05:09:00 +00006366 SuperClassGV = nullptr;
Chris Lattnerb433b272009-04-19 06:02:28 +00006367 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006368 // Has a root. Current class is not a root.
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006369 const auto *Super = CI->getSuperClass();
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006370 StringRef SuperClassName = Super->getObjCRuntimeNameAsString();
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006371
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006372 SuperClassGV =
6373 GetClassGlobal((getClassSymbolPrefix() + SuperClassName).str(),
6374 Super->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006375 if (CGM.getTriple().isOSBinFormatCOFF())
6376 if (Super->hasAttr<DLLImportAttr>())
6377 SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006378 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006379
Daniel Dunbar961202372009-05-03 12:57:56 +00006380 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006381 CLASS_RO_GV =
6382 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006383
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006384 llvm::GlobalVariable *ClassMD =
Saleem Abdulrasool10fd1ff2016-07-16 22:42:06 +00006385 BuildClassMetaData((getClassSymbolPrefix() + ClassName).str(), MetaTClass,
6386 SuperClassGV, CLASS_RO_GV, classIsHidden,
6387 CI->isWeakImported());
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006388 if (CGM.getTriple().isOSBinFormatCOFF())
6389 if (CI->hasAttr<DLLExportAttr>())
6390 ClassMD->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006391 DefinedClasses.push_back(ClassMD);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006392 ImplementedClasses.push_back(CI);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006393
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006394 // Determine if this class is also "non-lazy".
6395 if (ImplementationIsNonLazy(ID))
6396 DefinedNonLazyClasses.push_back(ClassMD);
6397
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006398 // Force the definition of the EHType if necessary.
John McCallef19dbb2012-10-17 04:53:23 +00006399 if (flags & NonFragileABI_Class_Exception)
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006400 GetInterfaceEHType(CI, true);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006401 // Make sure method definition entries are all clear for next implementation.
6402 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00006403}
6404
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006405/// GenerateProtocolRef - This routine is called to generate code for
6406/// a protocol reference expression; as in:
6407/// @code
6408/// @protocol(Proto1);
6409/// @endcode
6410/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
6411/// which will hold address of the protocol meta-data.
6412///
John McCall882987f2013-02-28 19:01:20 +00006413llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006414 const ObjCProtocolDecl *PD) {
6415
Fariborz Jahanian464423d2009-04-10 18:47:34 +00006416 // This routine is called for @protocol only. So, we must build definition
6417 // of protocol's meta-data (not a reference to it!)
6418 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006419 llvm::Constant *Init =
6420 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00006421 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006422
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006423 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006424 ProtocolName += PD->getObjCRuntimeNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006425
John McCall7f416cc2015-09-08 08:05:57 +00006426 CharUnits Align = CGF.getPointerAlign();
6427
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006428 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
6429 if (PTGV)
John McCall7f416cc2015-09-08 08:05:57 +00006430 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006431 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006432 CGM.getModule(),
6433 Init->getType(), false,
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006434 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006435 Init,
6436 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006437 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006438 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
John McCall7f416cc2015-09-08 08:05:57 +00006439 PTGV->setAlignment(Align.getQuantity());
Rafael Espindola060062a2014-03-06 22:15:10 +00006440 CGM.addCompilerUsedGlobal(PTGV);
John McCall7f416cc2015-09-08 08:05:57 +00006441 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006442}
6443
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006444/// GenerateCategory - Build metadata for a category implementation.
6445/// struct _category_t {
6446/// const char * const name;
6447/// struct _class_t *const cls;
6448/// const struct _method_list_t * const instance_methods;
6449/// const struct _method_list_t * const class_methods;
6450/// const struct _protocol_list_t * const protocols;
6451/// const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00006452/// const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00006453/// const uint32_t size;
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006454/// }
6455///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006456void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006457 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006458 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006459
6460 llvm::SmallString<64> ExtCatName(Prefix);
6461 ExtCatName += Interface->getObjCRuntimeNameAsString();
6462 ExtCatName += "_$_";
6463 ExtCatName += OCD->getNameAsString();
6464
6465 llvm::SmallString<64> ExtClassName(getClassSymbolPrefix());
6466 ExtClassName += Interface->getObjCRuntimeNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006467
John McCall176f8922016-11-30 02:39:18 +00006468 ConstantInitBuilder builder(CGM);
6469 auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
6470 values.add(GetClassName(OCD->getIdentifier()->getName()));
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006471 // meta-class entry symbol
Rafael Espindola554256c2014-02-26 22:25:45 +00006472 llvm::GlobalVariable *ClassGV =
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006473 GetClassGlobal(ExtClassName.str(), Interface->isWeakImported());
Rafael Espindola554256c2014-02-26 22:25:45 +00006474
John McCall176f8922016-11-30 02:39:18 +00006475 values.add(ClassGV);
6476 std::string listName =
Saleem Abdulrasool209150a2016-10-24 21:25:57 +00006477 (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006478
John McCall176f8922016-11-30 02:39:18 +00006479 SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
6480 SmallVector<const ObjCMethodDecl *, 8> classMethods;
6481 for (const auto *MD : OCD->methods()) {
6482 if (MD->isInstanceMethod()) {
6483 instanceMethods.push_back(MD);
6484 } else {
6485 classMethods.push_back(MD);
6486 }
6487 }
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006488
John McCall176f8922016-11-30 02:39:18 +00006489 values.add(emitMethodList(listName, MethodListType::CategoryInstanceMethods,
6490 instanceMethods));
6491 values.add(emitMethodList(listName, MethodListType::CategoryClassMethods,
6492 classMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006493
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006494 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00006495 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006496 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006497 SmallString<256> ExtName;
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006498 llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006499 << OCD->getName();
John McCall176f8922016-11-30 02:39:18 +00006500 values.add(EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006501 + Interface->getObjCRuntimeNameAsString() + "_$_"
6502 + Category->getName(),
John McCall176f8922016-11-30 02:39:18 +00006503 Category->protocol_begin(),
6504 Category->protocol_end()));
6505 values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
6506 OCD, Category, ObjCTypes, false));
6507 values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
6508 OCD, Category, ObjCTypes, true));
Mike Stump658fe022009-07-30 22:28:39 +00006509 } else {
John McCall176f8922016-11-30 02:39:18 +00006510 values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
6511 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6512 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006513 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006514
Manman Ren42ff3902016-02-24 17:49:50 +00006515 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
John McCall176f8922016-11-30 02:39:18 +00006516 values.addInt(ObjCTypes.IntTy, Size);
Manman Ren42ff3902016-02-24 17:49:50 +00006517
John McCall176f8922016-11-30 02:39:18 +00006518 llvm::GlobalVariable *GCATV =
6519 values.finishAndCreateGlobal(ExtCatName.str(), CGM.getPointerAlign(),
6520 /*constant*/ false,
6521 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006522 if (CGM.getTriple().isOSBinFormatMachO())
6523 GCATV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006524 CGM.addCompilerUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006525 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006526
6527 // Determine if this category is also "non-lazy".
6528 if (ImplementationIsNonLazy(OCD))
6529 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006530 // method definition entries must be clear for next implementation.
6531 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006532}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006533
John McCall176f8922016-11-30 02:39:18 +00006534/// emitMethodConstant - Return a struct objc_method constant. If
6535/// forProtocol is true, the implementation will be null; otherwise,
6536/// the method must have a definition registered with the runtime.
6537///
6538/// struct _objc_method {
6539/// SEL _cmd;
6540/// char *method_type;
6541/// char *_imp;
6542/// }
6543void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
6544 const ObjCMethodDecl *MD,
6545 bool forProtocol) {
6546 auto method = builder.beginStruct(ObjCTypes.MethodTy);
6547 method.addBitCast(GetMethodVarName(MD->getSelector()),
6548 ObjCTypes.SelectorPtrTy);
6549 method.add(GetMethodVarType(MD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006550
John McCall176f8922016-11-30 02:39:18 +00006551 if (forProtocol) {
6552 // Protocol methods have no implementation. So, this entry is always NULL.
6553 method.addNullPointer(ObjCTypes.Int8PtrTy);
6554 } else {
6555 llvm::Function *fn = GetMethodDefinition(MD);
6556 assert(fn && "no definition for method?");
6557 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
6558 }
6559
6560 method.finishAndAddTo(builder);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006561}
6562
John McCall176f8922016-11-30 02:39:18 +00006563/// Build meta-data for method declarations.
6564///
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006565/// struct _method_list_t {
6566/// uint32_t entsize; // sizeof(struct _objc_method)
6567/// uint32_t method_count;
6568/// struct _objc_method method_list[method_count];
6569/// }
6570///
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00006571llvm::Constant *
John McCall176f8922016-11-30 02:39:18 +00006572CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
6573 ArrayRef<const ObjCMethodDecl *> methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006574 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006575 if (methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006576 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006577
John McCall176f8922016-11-30 02:39:18 +00006578 StringRef prefix;
6579 bool forProtocol;
6580 switch (kind) {
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006581 case MethodListType::CategoryInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006582 prefix = "\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_";
6583 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006584 break;
6585 case MethodListType::CategoryClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006586 prefix = "\01l_OBJC_$_CATEGORY_CLASS_METHODS_";
6587 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006588 break;
6589 case MethodListType::InstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006590 prefix = "\01l_OBJC_$_INSTANCE_METHODS_";
6591 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006592 break;
6593 case MethodListType::ClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006594 prefix = "\01l_OBJC_$_CLASS_METHODS_";
6595 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006596 break;
6597
6598 case MethodListType::ProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006599 prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_";
6600 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006601 break;
6602 case MethodListType::ProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006603 prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_";
6604 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006605 break;
6606 case MethodListType::OptionalProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00006607 prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_";
6608 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006609 break;
6610 case MethodListType::OptionalProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00006611 prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_";
6612 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006613 break;
6614 }
6615
John McCall176f8922016-11-30 02:39:18 +00006616 ConstantInitBuilder builder(CGM);
6617 auto values = builder.beginStruct();
6618
6619 // sizeof(struct _objc_method)
6620 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
6621 values.addInt(ObjCTypes.IntTy, Size);
6622 // method_count
6623 values.addInt(ObjCTypes.IntTy, methods.size());
6624 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
6625 for (auto MD : methods) {
6626 emitMethodConstant(methodArray, MD, forProtocol);
6627 }
6628 methodArray.finishAndAddTo(values);
6629
6630 auto *GV = values.finishAndCreateGlobal(prefix + name, CGM.getPointerAlign(),
6631 /*constant*/ false,
6632 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006633 if (CGM.getTriple().isOSBinFormatMachO())
6634 GV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006635 CGM.addCompilerUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006636 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006637}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006638
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006639/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6640/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006641llvm::GlobalVariable *
6642CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6643 const ObjCIvarDecl *Ivar) {
6644 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006645 llvm::SmallString<64> Name("OBJC_IVAR_$_");
6646 Name += Container->getObjCRuntimeNameAsString();
6647 Name += ".";
6648 Name += Ivar->getName();
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006649 llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
6650 if (!IvarOffsetGV) {
6651 IvarOffsetGV =
6652 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy,
6653 false, llvm::GlobalValue::ExternalLinkage,
6654 nullptr, Name.str());
6655 if (CGM.getTriple().isOSBinFormatCOFF()) {
6656 bool IsPrivateOrPackage =
6657 Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6658 Ivar->getAccessControl() == ObjCIvarDecl::Package;
6659
6660 if (ID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
6661 IvarOffsetGV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
6662 else if (ID->hasAttr<DLLImportAttr>())
6663 IvarOffsetGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
6664 }
6665 }
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006666 return IvarOffsetGV;
6667}
6668
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006669llvm::Constant *
6670CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6671 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00006672 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006673 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Tim Northover238b5082014-03-29 13:42:40 +00006674 IvarOffsetGV->setInitializer(
6675 llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006676 IvarOffsetGV->setAlignment(
Tim Northover238b5082014-03-29 13:42:40 +00006677 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006678
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006679 if (!CGM.getTriple().isOSBinFormatCOFF()) {
6680 // FIXME: This matches gcc, but shouldn't the visibility be set on the use
6681 // as well (i.e., in ObjCIvarOffsetVariable).
6682 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6683 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6684 ID->getVisibility() == HiddenVisibility)
6685 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6686 else
6687 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
6688 }
6689
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006690 if (CGM.getTriple().isOSBinFormatMachO())
6691 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006692 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006693}
6694
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006695/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006696/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006697/// IvarListnfABIPtrTy.
6698/// struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00006699/// unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006700/// char *name;
6701/// char *type;
6702/// uint32_t alignment;
6703/// uint32_t size;
6704/// }
6705/// struct _ivar_list_t {
6706/// uint32 entsize; // sizeof(struct _ivar_t)
6707/// uint32 count;
6708/// struct _iver_t list[count];
6709/// }
6710///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00006711
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006712llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006713 const ObjCImplementationDecl *ID) {
6714
John McCall176f8922016-11-30 02:39:18 +00006715 ConstantInitBuilder builder(CGM);
6716 auto ivarList = builder.beginStruct();
6717 ivarList.addInt(ObjCTypes.IntTy,
6718 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
6719 auto ivarCountSlot = ivarList.addPlaceholder();
6720 auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006721
Jordy Rosea91768e2011-07-22 02:08:32 +00006722 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006723 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006724
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006725 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006726
Jordy Rosea91768e2011-07-22 02:08:32 +00006727 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00006728 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00006729 // Ignore unnamed bit-fields.
6730 if (!IVD->getDeclName())
6731 continue;
John McCall176f8922016-11-30 02:39:18 +00006732
6733 auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
6734 ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
6735 ComputeIvarBaseOffset(CGM, ID, IVD)));
6736 ivar.add(GetMethodVarName(IVD->getIdentifier()));
6737 ivar.add(GetMethodVarType(IVD));
Chris Lattner2192fe52011-07-18 04:24:23 +00006738 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006739 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmowdd31ca12012-10-08 16:25:52 +00006740 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006741 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006742 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006743 Align = llvm::Log2_32(Align);
John McCall176f8922016-11-30 02:39:18 +00006744 ivar.addInt(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00006745 // NOTE. Size of a bitfield does not match gcc's, because of the
6746 // way bitfields are treated special in each. But I am told that
6747 // 'size' for bitfield ivars is ignored by the runtime so it does
6748 // not matter. If it matters, there is enough info to get the
6749 // bitfield right!
John McCall176f8922016-11-30 02:39:18 +00006750 ivar.addInt(ObjCTypes.IntTy, Size);
6751 ivar.finishAndAddTo(ivars);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006752 }
6753 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006754 if (ivars.empty()) {
6755 ivars.abandon();
6756 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00006757 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCall176f8922016-11-30 02:39:18 +00006758 }
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006759
John McCall176f8922016-11-30 02:39:18 +00006760 auto ivarCount = ivars.size();
6761 ivars.finishAndAddTo(ivarList);
6762 ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
6763
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006764 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
6765 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00006766 ivarList.finishAndCreateGlobal(Prefix + OID->getObjCRuntimeNameAsString(),
6767 CGM.getPointerAlign(), /*constant*/ false,
6768 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006769 if (CGM.getTriple().isOSBinFormatMachO())
6770 GV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006771 CGM.addCompilerUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00006772 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006773}
6774
6775llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006776 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006777 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006778
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006779 if (!Entry) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006780 // We use the initializer as a marker of whether this is a forward
6781 // reference or not. At module finalization we add the empty
6782 // contents for protocols which were referenced but never defined.
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006783 llvm::SmallString<64> Protocol;
6784 llvm::raw_svector_ostream(Protocol) << "\01l_OBJC_PROTOCOL_$_"
6785 << PD->getObjCRuntimeNameAsString();
6786
6787 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6788 false, llvm::GlobalValue::ExternalLinkage,
6789 nullptr, Protocol);
6790 if (!CGM.getTriple().isOSBinFormatMachO())
6791 Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
6792 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006793
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006794 return Entry;
6795}
6796
6797/// GetOrEmitProtocol - Generate the protocol meta-data:
6798/// @code
6799/// struct _protocol_t {
6800/// id isa; // NULL
6801/// const char * const protocol_name;
6802/// const struct _protocol_list_t * protocol_list; // super protocols
6803/// const struct method_list_t * const instance_methods;
6804/// const struct method_list_t * const class_methods;
6805/// const struct method_list_t *optionalInstanceMethods;
6806/// const struct method_list_t *optionalClassMethods;
6807/// const struct _prop_list_t * properties;
6808/// const uint32_t size; // sizeof(struct _protocol_t)
6809/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006810/// const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006811/// const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00006812/// const struct _prop_list_t * class_properties;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006813/// }
6814/// @endcode
6815///
6816
6817llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006818 const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00006819 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006820
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006821 // Early exit if a defining object has already been generated.
6822 if (Entry && Entry->hasInitializer())
6823 return Entry;
6824
Douglas Gregora715bff2012-01-01 19:51:50 +00006825 // Use the protocol definition, if there is one.
6826 if (const ObjCProtocolDecl *Def = PD->getDefinition())
6827 PD = Def;
6828
John McCall176f8922016-11-30 02:39:18 +00006829 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006830
John McCall176f8922016-11-30 02:39:18 +00006831 ConstantInitBuilder builder(CGM);
6832 auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
Douglas Gregora9d84932011-05-27 01:19:52 +00006833
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006834 // isa is NULL
John McCall176f8922016-11-30 02:39:18 +00006835 values.addNullPointer(ObjCTypes.ObjectPtrTy);
6836 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
6837 values.add(EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_"
6838 + PD->getObjCRuntimeNameAsString(),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006839 PD->protocol_begin(),
John McCall176f8922016-11-30 02:39:18 +00006840 PD->protocol_end()));
6841 values.add(methodLists.emitMethodList(this, PD,
6842 ProtocolMethodLists::RequiredInstanceMethods));
6843 values.add(methodLists.emitMethodList(this, PD,
6844 ProtocolMethodLists::RequiredClassMethods));
6845 values.add(methodLists.emitMethodList(this, PD,
6846 ProtocolMethodLists::OptionalInstanceMethods));
6847 values.add(methodLists.emitMethodList(this, PD,
6848 ProtocolMethodLists::OptionalClassMethods));
6849 values.add(EmitPropertyList(
6850 "\01l_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
6851 nullptr, PD, ObjCTypes, false));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006852 uint32_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006853 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
John McCall176f8922016-11-30 02:39:18 +00006854 values.addInt(ObjCTypes.IntTy, Size);
6855 values.addInt(ObjCTypes.IntTy, 0);
6856 values.add(EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006857 + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006858 methodLists.emitExtendedTypesArray(this),
6859 ObjCTypes));
6860
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006861 // const char *demangledName;
John McCall176f8922016-11-30 02:39:18 +00006862 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Rence7bff52016-01-29 23:46:55 +00006863
John McCall176f8922016-11-30 02:39:18 +00006864 values.add(EmitPropertyList(
Manman Rence7bff52016-01-29 23:46:55 +00006865 "\01l_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006866 nullptr, PD, ObjCTypes, true));
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006867
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006868 if (Entry) {
Rafael Espindola24615092014-09-12 20:14:20 +00006869 // Already created, fix the linkage and update the initializer.
6870 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
John McCall176f8922016-11-30 02:39:18 +00006871 values.finishAndSetAsInitializer(Entry);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006872 } else {
John McCall176f8922016-11-30 02:39:18 +00006873 llvm::SmallString<64> symbolName;
6874 llvm::raw_svector_ostream(symbolName)
6875 << "\01l_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006876
John McCall176f8922016-11-30 02:39:18 +00006877 Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
6878 /*constant*/ false,
6879 llvm::GlobalValue::WeakAnyLinkage);
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006880 if (!CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00006881 Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
John McCallf9582a72012-03-30 21:29:05 +00006882
6883 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006884 }
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006885 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Rafael Espindola060062a2014-03-06 22:15:10 +00006886 CGM.addCompilerUsedGlobal(Entry);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006887
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006888 // Use this protocol meta-data to build protocol list table in section
6889 // __DATA, __objc_protolist
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006890 llvm::SmallString<64> ProtocolRef;
6891 llvm::raw_svector_ostream(ProtocolRef) << "\01l_OBJC_LABEL_PROTOCOL_$_"
6892 << PD->getObjCRuntimeNameAsString();
6893
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006894 llvm::GlobalVariable *PTGV =
6895 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006896 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006897 ProtocolRef);
6898 if (!CGM.getTriple().isOSBinFormatMachO())
6899 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006900 PTGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006901 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006902 if (CGM.getTriple().isOSBinFormatMachO())
6903 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006904 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Rafael Espindola060062a2014-03-06 22:15:10 +00006905 CGM.addCompilerUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006906 return Entry;
6907}
6908
6909/// EmitProtocolList - Generate protocol list meta-data:
6910/// @code
6911/// struct _protocol_list_t {
6912/// long protocol_count; // Note, this is 32/64 bit
6913/// struct _protocol_t[protocol_count];
6914/// }
6915/// @endcode
6916///
6917llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006918CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006919 ObjCProtocolDecl::protocol_iterator begin,
6920 ObjCProtocolDecl::protocol_iterator end) {
Dmitri Gribenkof8579502013-01-12 19:30:44 +00006921 SmallVector<llvm::Constant *, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006922
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006923 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006924 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00006925 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006926
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006927 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006928 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006929 Name.toVector(TmpName);
6930 llvm::GlobalVariable *GV =
6931 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006932 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006933 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006934
John McCall176f8922016-11-30 02:39:18 +00006935 ConstantInitBuilder builder(CGM);
6936 auto values = builder.beginStruct();
6937 auto countSlot = values.addPlaceholder();
6938
6939 // A null-terminated array of protocols.
6940 auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006941 for (; begin != end; ++begin)
John McCall176f8922016-11-30 02:39:18 +00006942 array.add(GetProtocolRef(*begin)); // Implemented???
6943 auto count = array.size();
6944 array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006945
John McCall176f8922016-11-30 02:39:18 +00006946 array.finishAndAddTo(values);
6947 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006948
John McCall176f8922016-11-30 02:39:18 +00006949 GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
6950 /*constant*/ false,
6951 llvm::GlobalValue::PrivateLinkage);
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006952 if (CGM.getTriple().isOSBinFormatMachO())
6953 GV->setSection("__DATA, __objc_const");
Rafael Espindola060062a2014-03-06 22:15:10 +00006954 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006955 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006956 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006957}
6958
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006959/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
6960/// This code gen. amounts to generating code for:
6961/// @code
6962/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
6963/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006964///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00006965LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00006966 CodeGen::CodeGenFunction &CGF,
6967 QualType ObjectTy,
6968 llvm::Value *BaseValue,
6969 const ObjCIvarDecl *Ivar,
6970 unsigned CVRQualifiers) {
6971 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006972 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00006973 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006974 Offset);
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006975}
6976
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006977llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006978 CodeGen::CodeGenFunction &CGF,
6979 const ObjCInterfaceDecl *Interface,
6980 const ObjCIvarDecl *Ivar) {
Tim Northover238b5082014-03-29 13:42:40 +00006981 llvm::Value *IvarOffsetValue = ObjCIvarOffsetVariable(Interface, Ivar);
John McCall7f416cc2015-09-08 08:05:57 +00006982 IvarOffsetValue = CGF.Builder.CreateAlignedLoad(IvarOffsetValue,
6983 CGF.getSizeAlign(), "ivar");
Tim Northover238b5082014-03-29 13:42:40 +00006984 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
6985 cast<llvm::LoadInst>(IvarOffsetValue)
6986 ->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
Craig Topper5fc8fc22014-08-27 06:28:36 +00006987 llvm::MDNode::get(VMContext, None));
Tim Northover238b5082014-03-29 13:42:40 +00006988
6989 // This could be 32bit int or 64bit integer depending on the architecture.
6990 // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
6991 // as this is what caller always expectes.
6992 if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
6993 IvarOffsetValue = CGF.Builder.CreateIntCast(
6994 IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
6995 return IvarOffsetValue;
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006996}
6997
John McCall234eac82011-05-13 23:16:18 +00006998static void appendSelectorForMessageRefTable(std::string &buffer,
6999 Selector selector) {
7000 if (selector.isUnarySelector()) {
7001 buffer += selector.getNameForSlot(0);
7002 return;
7003 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007004
John McCall234eac82011-05-13 23:16:18 +00007005 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
7006 buffer += selector.getNameForSlot(i);
7007 buffer += '_';
7008 }
7009}
7010
Eric Christopherd160c502016-01-29 01:35:53 +00007011/// Emit a "vtable" message send. We emit a weak hidden-visibility
John McCall9e8bb002011-05-14 03:10:52 +00007012/// struct, initially containing the selector pointer and a pointer to
7013/// a "fixup" variant of the appropriate objc_msgSend. To call, we
7014/// load and call the function pointer, passing the address of the
7015/// struct as the second parameter. The runtime determines whether
7016/// the selector is currently emitted using vtable dispatch; if so, it
7017/// substitutes a stub function which simply tail-calls through the
7018/// appropriate vtable slot, and if not, it substitues a stub function
7019/// which tail-calls objc_msgSend. Both stubs adjust the selector
7020/// argument to correctly point to the selector.
7021RValue
7022CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
7023 ReturnValueSlot returnSlot,
7024 QualType resultType,
7025 Selector selector,
7026 llvm::Value *arg0,
7027 QualType arg0Type,
7028 bool isSuper,
7029 const CallArgList &formalArgs,
7030 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00007031 // Compute the actual arguments.
7032 CallArgList args;
7033
John McCall9e8bb002011-05-14 03:10:52 +00007034 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00007035 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00007036 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
7037 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00007038
John McCall9e8bb002011-05-14 03:10:52 +00007039 // Second argument: a pointer to the message ref structure. Leave
7040 // the actual argument value blank for now.
Craig Topper8a13c412014-05-21 05:09:00 +00007041 args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
John McCall234eac82011-05-13 23:16:18 +00007042
7043 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
7044
John McCalla729c622012-02-17 03:33:10 +00007045 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCall234eac82011-05-13 23:16:18 +00007046
John McCall5880fb82011-05-14 21:12:11 +00007047 NullReturnState nullReturn;
7048
John McCall9e8bb002011-05-14 03:10:52 +00007049 // Find the function to call and the mangled name for the message
7050 // ref structure. Using a different mangled name wouldn't actually
7051 // be a problem; it would just be a waste.
7052 //
7053 // The runtime currently never uses vtable dispatch for anything
7054 // except normal, non-super message-sends.
7055 // FIXME: don't use this for that.
Craig Topper8a13c412014-05-21 05:09:00 +00007056 llvm::Constant *fn = nullptr;
John McCall234eac82011-05-13 23:16:18 +00007057 std::string messageRefName("\01l_");
Tim Northovere77cc392014-03-29 13:28:05 +00007058 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
John McCall234eac82011-05-13 23:16:18 +00007059 if (isSuper) {
7060 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
7061 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007062 } else {
John McCall5880fb82011-05-14 21:12:11 +00007063 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00007064 fn = ObjCTypes.getMessageSendStretFixupFn();
7065 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007066 }
John McCall234eac82011-05-13 23:16:18 +00007067 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
7068 fn = ObjCTypes.getMessageSendFpretFixupFn();
7069 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00007070 } else {
John McCall234eac82011-05-13 23:16:18 +00007071 if (isSuper) {
7072 fn = ObjCTypes.getMessageSendSuper2FixupFn();
7073 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007074 } else {
John McCall234eac82011-05-13 23:16:18 +00007075 fn = ObjCTypes.getMessageSendFixupFn();
7076 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007077 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00007078 }
John McCall234eac82011-05-13 23:16:18 +00007079 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
7080 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007081
John McCall234eac82011-05-13 23:16:18 +00007082 // Append the selector name, except use underscores anywhere we
7083 // would have used colons.
7084 appendSelectorForMessageRefTable(messageRefName, selector);
7085
7086 llvm::GlobalVariable *messageRef
7087 = CGM.getModule().getGlobalVariable(messageRefName);
7088 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00007089 // Build the message ref structure.
John McCall176f8922016-11-30 02:39:18 +00007090 ConstantInitBuilder builder(CGM);
7091 auto values = builder.beginStruct();
7092 values.add(fn);
7093 values.add(GetMethodVarName(selector));
7094 messageRef = values.finishAndCreateGlobal(messageRefName,
7095 CharUnits::fromQuantity(16),
7096 /*constant*/ false,
7097 llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007098 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
John McCall234eac82011-05-13 23:16:18 +00007099 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
7100 }
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007101
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00007102 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00007103 if (CGM.getLangOpts().ObjCAutoRefCount && method)
David Majnemer59f77922016-06-24 04:05:48 +00007104 for (const auto *ParamDecl : method->parameters()) {
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00007105 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
7106 if (!nullReturn.NullBB)
7107 nullReturn.init(CGF, arg0);
7108 requiresnullCheck = true;
7109 break;
7110 }
7111 }
7112
John McCall7f416cc2015-09-08 08:05:57 +00007113 Address mref =
7114 Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
7115 CGF.getPointerAlign());
John McCall234eac82011-05-13 23:16:18 +00007116
John McCall9e8bb002011-05-14 03:10:52 +00007117 // Update the message ref argument.
John McCall7f416cc2015-09-08 08:05:57 +00007118 args[1].RV = RValue::get(mref.getPointer());
John McCall234eac82011-05-13 23:16:18 +00007119
7120 // Load the function to call from the message ref table.
John McCall7f416cc2015-09-08 08:05:57 +00007121 Address calleeAddr =
7122 CGF.Builder.CreateStructGEP(mref, 0, CharUnits::Zero());
John McCallb92ab1a2016-10-26 23:46:34 +00007123 llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
John McCall234eac82011-05-13 23:16:18 +00007124
John McCallb92ab1a2016-10-26 23:46:34 +00007125 calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
7126 CGCallee callee(CGCalleeInfo(), calleePtr);
John McCall234eac82011-05-13 23:16:18 +00007127
John McCalla729c622012-02-17 03:33:10 +00007128 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Craig Topper8a13c412014-05-21 05:09:00 +00007129 return nullReturn.complete(CGF, result, resultType, formalArgs,
7130 requiresnullCheck ? method : nullptr);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007131}
7132
7133/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007134CodeGen::RValue
7135CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007136 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007137 QualType ResultType,
7138 Selector Sel,
7139 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007140 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00007141 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007142 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00007143 return isVTableDispatchedSelector(Sel)
7144 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007145 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00007146 false, CallArgs, Method)
7147 : EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00007148 EmitSelector(CGF, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007149 Receiver, CGF.getContext().getObjCIdType(),
John McCall1e3157b2015-09-10 22:27:50 +00007150 false, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007151}
7152
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007153llvm::GlobalVariable *
Benjamin Kramer0772c422016-02-13 13:42:54 +00007154CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name, bool Weak) {
Rafael Espindola554256c2014-02-26 22:25:45 +00007155 llvm::GlobalValue::LinkageTypes L =
7156 Weak ? llvm::GlobalValue::ExternalWeakLinkage
7157 : llvm::GlobalValue::ExternalLinkage;
7158
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007159 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
7160
Rafael Espindola554256c2014-02-26 22:25:45 +00007161 if (!GV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007162 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Craig Topper8a13c412014-05-21 05:09:00 +00007163 false, L, nullptr, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007164
Rafael Espindola554256c2014-02-26 22:25:45 +00007165 assert(GV->getLinkage() == L);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007166 return GV;
7167}
7168
John McCall882987f2013-02-28 19:01:20 +00007169llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
Rafael Espindola554256c2014-02-26 22:25:45 +00007170 IdentifierInfo *II,
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007171 bool Weak,
7172 const ObjCInterfaceDecl *ID) {
John McCall7f416cc2015-09-08 08:05:57 +00007173 CharUnits Align = CGF.getPointerAlign();
John McCall31168b02011-06-15 23:02:42 +00007174 llvm::GlobalVariable *&Entry = ClassReferences[II];
7175
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007176 if (!Entry) {
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00007177 StringRef Name = ID ? ID->getObjCRuntimeNameAsString() : II->getName();
7178 std::string ClassName = (getClassSymbolPrefix() + Name).str();
Rafael Espindola554256c2014-02-26 22:25:45 +00007179 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, Weak);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007180 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
7181 false, llvm::GlobalValue::PrivateLinkage,
7182 ClassGV, "OBJC_CLASSLIST_REFERENCES_$_");
John McCall7f416cc2015-09-08 08:05:57 +00007183 Entry->setAlignment(Align.getQuantity());
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007184 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00007185 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007186 }
John McCall7f416cc2015-09-08 08:05:57 +00007187 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007188}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007189
John McCall882987f2013-02-28 19:01:20 +00007190llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00007191 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00007192 // If the class has the objc_runtime_visible attribute, we need to
7193 // use the Objective-C runtime to get the class.
7194 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
7195 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
7196
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007197 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID->isWeakImported(), ID);
John McCall31168b02011-06-15 23:02:42 +00007198}
7199
7200llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
John McCall882987f2013-02-28 19:01:20 +00007201 CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00007202 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
Hans Wennborgdcfba332015-10-06 23:40:43 +00007203 return EmitClassRefFromId(CGF, II, false, nullptr);
John McCall31168b02011-06-15 23:02:42 +00007204}
7205
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007206llvm::Value *
John McCall882987f2013-02-28 19:01:20 +00007207CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007208 const ObjCInterfaceDecl *ID) {
John McCall7f416cc2015-09-08 08:05:57 +00007209 CharUnits Align = CGF.getPointerAlign();
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007210 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007211
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007212 if (!Entry) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007213 llvm::SmallString<64> ClassName(getClassSymbolPrefix());
7214 ClassName += ID->getObjCRuntimeNameAsString();
7215 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(),
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00007216 ID->isWeakImported());
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007217 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
7218 false, llvm::GlobalValue::PrivateLinkage,
7219 ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
John McCall7f416cc2015-09-08 08:05:57 +00007220 Entry->setAlignment(Align.getQuantity());
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007221 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00007222 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007223 }
John McCall7f416cc2015-09-08 08:05:57 +00007224 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007225}
7226
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007227/// EmitMetaClassRef - Return a Value * of the address of _class_t
7228/// meta-data
7229///
John McCall882987f2013-02-28 19:01:20 +00007230llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00007231 const ObjCInterfaceDecl *ID,
7232 bool Weak) {
John McCall7f416cc2015-09-08 08:05:57 +00007233 CharUnits Align = CGF.getPointerAlign();
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007234 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
Rafael Espindola21039aa2014-02-27 16:26:32 +00007235 if (!Entry) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007236 llvm::SmallString<64> MetaClassName(getMetaclassSymbolPrefix());
7237 MetaClassName += ID->getObjCRuntimeNameAsString();
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00007238 llvm::GlobalVariable *MetaClassGV =
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007239 GetClassGlobal(MetaClassName.str(), Weak);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007240
Rafael Espindola21039aa2014-02-27 16:26:32 +00007241 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Rafael Espindola5179a4e2014-02-27 19:01:11 +00007242 false, llvm::GlobalValue::PrivateLinkage,
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007243 MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
John McCall7f416cc2015-09-08 08:05:57 +00007244 Entry->setAlignment(Align.getQuantity());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007245
Rafael Espindola21039aa2014-02-27 16:26:32 +00007246 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00007247 CGM.addCompilerUsedGlobal(Entry);
Rafael Espindola21039aa2014-02-27 16:26:32 +00007248 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007249
John McCall7f416cc2015-09-08 08:05:57 +00007250 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007251}
7252
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007253/// GetClass - Return a reference to the class for the given interface
7254/// decl.
John McCall882987f2013-02-28 19:01:20 +00007255llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007256 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00007257 if (ID->isWeakImported()) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007258 llvm::SmallString<64> ClassName(getClassSymbolPrefix());
7259 ClassName += ID->getObjCRuntimeNameAsString();
7260 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(), true);
Nick Lewycky9a441642014-02-27 00:36:00 +00007261 (void)ClassGV;
Rafael Espindolab3262952014-05-09 00:43:37 +00007262 assert(ClassGV->hasExternalWeakLinkage());
Fariborz Jahanian95ace552009-11-17 22:42:00 +00007263 }
7264
John McCall882987f2013-02-28 19:01:20 +00007265 return EmitClassRef(CGF, ID);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007266}
7267
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007268/// Generates a message send where the super is the receiver. This is
7269/// a message send to self with special delivery semantics indicating
7270/// which class's method should be called.
7271CodeGen::RValue
7272CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007273 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007274 QualType ResultType,
7275 Selector Sel,
7276 const ObjCInterfaceDecl *Class,
7277 bool isCategoryImpl,
7278 llvm::Value *Receiver,
7279 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007280 const CodeGen::CallArgList &CallArgs,
7281 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007282 // ...
7283 // Create and init a super structure; this is a (receiver, class)
7284 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00007285 Address ObjCSuper =
7286 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
7287 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007288
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007289 llvm::Value *ReceiverAsObject =
7290 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
David Blaikie1ed728c2015-04-05 22:45:47 +00007291 CGF.Builder.CreateStore(
7292 ReceiverAsObject,
John McCall7f416cc2015-09-08 08:05:57 +00007293 CGF.Builder.CreateStructGEP(ObjCSuper, 0, CharUnits::Zero()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007294
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007295 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00007296 llvm::Value *Target;
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007297 if (IsClassMessage)
Fariborz Jahanian85b99da2014-08-28 17:05:17 +00007298 Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007299 else
John McCall882987f2013-02-28 19:01:20 +00007300 Target = EmitSuperClassRef(CGF, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007301
Mike Stump18bb9282009-05-16 07:57:57 +00007302 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
7303 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00007304 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007305 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
7306 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
David Blaikie1ed728c2015-04-05 22:45:47 +00007307 CGF.Builder.CreateStore(
John McCall7f416cc2015-09-08 08:05:57 +00007308 Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1, CGF.getPointerSize()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007309
John McCall9e8bb002011-05-14 03:10:52 +00007310 return (isVTableDispatchedSelector(Sel))
7311 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
John McCall7f416cc2015-09-08 08:05:57 +00007312 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00007313 true, CallArgs, Method)
7314 : EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00007315 EmitSelector(CGF, Sel),
John McCall7f416cc2015-09-08 08:05:57 +00007316 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall1e3157b2015-09-10 22:27:50 +00007317 true, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007318}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007319
John McCall882987f2013-02-28 19:01:20 +00007320llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007321 Selector Sel) {
7322 Address Addr = EmitSelectorAddr(CGF, Sel);
7323
7324 llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
7325 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
7326 llvm::MDNode::get(VMContext, None));
7327 return LI;
7328}
7329
7330Address CGObjCNonFragileABIMac::EmitSelectorAddr(CodeGenFunction &CGF,
7331 Selector Sel) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007332 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007333
John McCall7f416cc2015-09-08 08:05:57 +00007334 CharUnits Align = CGF.getPointerAlign();
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007335 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007336 llvm::Constant *Casted =
7337 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
7338 ObjCTypes.SelectorPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00007339 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy,
7340 false, llvm::GlobalValue::PrivateLinkage,
7341 Casted, "OBJC_SELECTOR_REFERENCES_");
Michael Gottesman5c205962013-02-05 23:08:45 +00007342 Entry->setExternallyInitialized(true);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00007343 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
John McCall7f416cc2015-09-08 08:05:57 +00007344 Entry->setAlignment(Align.getQuantity());
Rafael Espindola060062a2014-03-06 22:15:10 +00007345 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007346 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007347
John McCall7f416cc2015-09-08 08:05:57 +00007348 return Address(Entry, Align);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007349}
John McCall7f416cc2015-09-08 08:05:57 +00007350
Fariborz Jahanian06292952009-02-16 22:52:32 +00007351/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007352/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00007353///
7354void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00007355 llvm::Value *src,
John McCall7f416cc2015-09-08 08:05:57 +00007356 Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007357 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007358 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007359 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007360 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007361 assert(Size <= 8 && "does not support size > 8");
7362 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7363 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007364 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7365 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007366 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7367 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007368 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00007369 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007370}
7371
7372/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
7373/// objc_assign_strongCast (id src, id *dst)
7374///
7375void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007376 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007377 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007378 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007379 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007380 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007381 assert(Size <= 8 && "does not support size > 8");
7382 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007383 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007384 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7385 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007386 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7387 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007388 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007389 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
7390 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007391}
7392
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007393void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007394 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007395 Address DestPtr,
7396 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00007397 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007398 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
7399 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007400 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size };
John McCall882987f2013-02-28 19:01:20 +00007401 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007402}
7403
Fariborz Jahanian06292952009-02-16 22:52:32 +00007404/// EmitObjCWeakRead - Code gen for loading value of a __weak
7405/// object: objc_read_weak (id *src)
7406///
7407llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007408 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007409 Address AddrWeakObj) {
7410 llvm::Type *DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007411 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00007412 llvm::Value *read_weak =
7413 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00007414 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00007415 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007416 return read_weak;
7417}
7418
7419/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
7420/// objc_assign_weak (id src, id *dst)
7421///
7422void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007423 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007424 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007425 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007426 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007427 assert(Size <= 8 && "does not support size > 8");
7428 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7429 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007430 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7431 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007432 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7433 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007434 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007435 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
7436 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007437}
7438
7439/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
7440/// objc_assign_global (id src, id *dst)
7441///
7442void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007443 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00007444 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007445 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007446 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007447 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007448 assert(Size <= 8 && "does not support size > 8");
7449 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7450 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007451 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7452 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007453 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7454 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007455 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00007456 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00007457 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
7458 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00007459 else
John McCall882987f2013-02-28 19:01:20 +00007460 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
7461 args, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007462}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007463
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007464void
John McCallbd309292010-07-06 01:34:17 +00007465CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
7466 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00007467 EmitAtSynchronizedStmt(CGF, S,
7468 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
7469 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00007470}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007471
John McCall2ca705e2010-07-24 00:37:23 +00007472llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00007473CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00007474 // There's a particular fixed type info for 'id'.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007475 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
7476 auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007477 if (!IDEHType) {
John McCall2ca705e2010-07-24 00:37:23 +00007478 IDEHType =
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007479 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
7480 llvm::GlobalValue::ExternalLinkage, nullptr,
7481 "OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007482 if (CGM.getTriple().isOSBinFormatCOFF())
7483 IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id"));
7484 }
John McCall2ca705e2010-07-24 00:37:23 +00007485 return IDEHType;
7486 }
7487
7488 // All other types should be Objective-C interface pointer types.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007489 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
John McCall2ca705e2010-07-24 00:37:23 +00007490 assert(PT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007491
John McCall2ca705e2010-07-24 00:37:23 +00007492 const ObjCInterfaceType *IT = PT->getInterfaceType();
7493 assert(IT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007494
John McCall2ca705e2010-07-24 00:37:23 +00007495 return GetInterfaceEHType(IT->getDecl(), false);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007496}
John McCall2ca705e2010-07-24 00:37:23 +00007497
John McCallbd309292010-07-06 01:34:17 +00007498void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
7499 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00007500 EmitTryCatchStmt(CGF, S,
7501 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
7502 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
7503 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00007504}
7505
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007506/// EmitThrowStmt - Generate code for a throw statement.
7507void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007508 const ObjCAtThrowStmt &S,
7509 bool ClearInsertionPoint) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007510 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00007511 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00007512 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00007513 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall17afe452010-10-16 08:21:07 +00007514 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007515 } else {
John McCall882987f2013-02-28 19:01:20 +00007516 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall17afe452010-10-16 08:21:07 +00007517 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007518 }
7519
John McCall17afe452010-10-16 08:21:07 +00007520 CGF.Builder.CreateUnreachable();
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007521 if (ClearInsertionPoint)
7522 CGF.Builder.ClearInsertionPoint();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007523}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007524
John McCall2ca705e2010-07-24 00:37:23 +00007525llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007526CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007527 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007528 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007529 StringRef ClassName = ID->getObjCRuntimeNameAsString();
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007530
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007531 // If we don't need a definition, return the entry if found or check
7532 // if we use an external reference.
7533 if (!ForDefinition) {
7534 if (Entry)
7535 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00007536
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007537 // If this type (or a super class) has the __objc_exception__
7538 // attribute, emit an external reference.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007539 if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
7540 std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str();
7541 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
7542 false, llvm::GlobalValue::ExternalLinkage,
7543 nullptr, EHTypeName);
7544 if (CGM.getTriple().isOSBinFormatCOFF()) {
7545 if (ID->hasAttr<DLLExportAttr>())
7546 Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
7547 else if (ID->hasAttr<DLLImportAttr>())
7548 Entry->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
7549 }
7550 return Entry;
7551 }
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007552 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007553
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007554 // Otherwise we need to either make a new entry or fill in the initializer.
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007555 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007556
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007557 std::string VTableName = "objc_ehtype_vtable";
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007558 auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007559 if (!VTableGV) {
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007560 VTableGV =
7561 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false,
7562 llvm::GlobalValue::ExternalLinkage, nullptr,
7563 VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007564 if (CGM.getTriple().isOSBinFormatCOFF())
7565 VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
7566 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007567
Chris Lattnerece04092012-02-07 00:39:47 +00007568 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
John McCall176f8922016-11-30 02:39:18 +00007569 ConstantInitBuilder builder(CGM);
7570 auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
7571 values.add(llvm::ConstantExpr::getGetElementPtr(VTableGV->getValueType(),
7572 VTableGV, VTableIdx));
7573 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
7574 values.add(GetClassGlobal((getClassSymbolPrefix() + ClassName).str()));
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007575
Rafael Espindola554256c2014-02-26 22:25:45 +00007576 llvm::GlobalValue::LinkageTypes L = ForDefinition
7577 ? llvm::GlobalValue::ExternalLinkage
7578 : llvm::GlobalValue::WeakAnyLinkage;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007579 if (Entry) {
John McCall176f8922016-11-30 02:39:18 +00007580 values.finishAndSetAsInitializer(Entry);
7581 Entry->setAlignment(CGM.getPointerAlign().getQuantity());
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007582 } else {
John McCall176f8922016-11-30 02:39:18 +00007583 Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName,
7584 CGM.getPointerAlign(),
7585 /*constant*/ false,
7586 L);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007587 if (CGM.getTriple().isOSBinFormatCOFF())
7588 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
7589 if (ID->hasAttr<DLLExportAttr>())
7590 Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007591 }
Rafael Espindola554256c2014-02-26 22:25:45 +00007592 assert(Entry->getLinkage() == L);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007593
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007594 if (!CGM.getTriple().isOSBinFormatCOFF())
7595 if (ID->getVisibility() == HiddenVisibility)
7596 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007597
Rafael Espindola554256c2014-02-26 22:25:45 +00007598 if (ForDefinition)
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00007599 if (CGM.getTriple().isOSBinFormatMachO())
7600 Entry->setSection("__DATA,__objc_const");
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007601
7602 return Entry;
7603}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007604
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00007605/* *** */
7606
Daniel Dunbarb036db82008-08-13 03:21:16 +00007607CodeGen::CGObjCRuntime *
7608CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall5fb5df92012-06-20 06:18:46 +00007609 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7610 case ObjCRuntime::FragileMacOSX:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007611 return new CGObjCMac(CGM);
John McCall5fb5df92012-06-20 06:18:46 +00007612
7613 case ObjCRuntime::MacOSX:
7614 case ObjCRuntime::iOS:
Tim Northover756447a2015-10-30 16:30:36 +00007615 case ObjCRuntime::WatchOS:
John McCall5fb5df92012-06-20 06:18:46 +00007616 return new CGObjCNonFragileABIMac(CGM);
7617
David Chisnallb601c962012-07-03 20:49:52 +00007618 case ObjCRuntime::GNUstep:
7619 case ObjCRuntime::GCC:
John McCall775086e2012-07-12 02:07:58 +00007620 case ObjCRuntime::ObjFW:
John McCall5fb5df92012-06-20 06:18:46 +00007621 llvm_unreachable("these runtimes are not Mac runtimes");
7622 }
7623 llvm_unreachable("bad runtime");
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007624}