blob: 775e3406da7ea4d18f3ecf25211d7024baec4187 [file] [log] [blame]
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Daniel Dunbar303e2c22008-08-11 02:45:11 +00006//
7//===----------------------------------------------------------------------===//
8//
Chris Lattner57540c52011-04-15 05:22:18 +00009// This provides Objective-C code generation targeting the Apple runtime.
Daniel Dunbar303e2c22008-08-11 02:45:11 +000010//
11//===----------------------------------------------------------------------===//
12
John McCallad7c5c12011-02-08 08:22:06 +000013#include "CGBlocks.h"
John McCalled1ae862011-01-28 11:13:47 +000014#include "CGCleanup.h"
Justin Lebar5e83dfe2016-10-21 21:45:01 +000015#include "CGObjCRuntime.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000016#include "CGRecordLayout.h"
17#include "CodeGenFunction.h"
18#include "CodeGenModule.h"
John McCall5ad74072017-03-02 20:04:19 +000019#include "clang/CodeGen/ConstantInitBuilder.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000020#include "clang/AST/ASTContext.h"
Daniel Dunbar221fa942008-08-11 04:54:23 +000021#include "clang/AST/Decl.h"
Daniel Dunbarb036db82008-08-13 03:21:16 +000022#include "clang/AST/DeclObjC.h"
Anders Carlsson15b73de2009-07-18 19:43:29 +000023#include "clang/AST/RecordLayout.h"
Chris Lattnerf0b64d72009-04-26 01:32:48 +000024#include "clang/AST/StmtObjC.h"
Richard Trieu63688182018-12-11 03:18:39 +000025#include "clang/Basic/CodeGenOptions.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"
Justin Lebar5e83dfe2016-10-21 21:45:01 +000028#include "llvm/ADT/CachedHashString.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000029#include "llvm/ADT/DenseSet.h"
30#include "llvm/ADT/SetVector.h"
31#include "llvm/ADT/SmallPtrSet.h"
32#include "llvm/ADT/SmallString.h"
Chandler Carruthffd55512013-01-02 11:45:17 +000033#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/InlineAsm.h"
35#include "llvm/IR/IntrinsicInst.h"
36#include "llvm/IR/LLVMContext.h"
37#include "llvm/IR/Module.h"
Akira Hatanaka2ec36f02018-08-17 15:46:07 +000038#include "llvm/Support/ScopedPrinter.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000039#include "llvm/Support/raw_ostream.h"
Torok Edwindb714922009-08-24 13:25:12 +000040#include <cstdio>
Daniel Dunbar303e2c22008-08-11 02:45:11 +000041
42using namespace clang;
Daniel Dunbar41cf9de2008-09-09 01:06:48 +000043using namespace CodeGen;
Daniel Dunbar303e2c22008-08-11 02:45:11 +000044
45namespace {
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000046
Daniel Dunbar59e476b2009-08-03 17:06:42 +000047// FIXME: We should find a nicer way to make the labels for metadata, string
48// concatenation is lame.
Daniel Dunbarb036db82008-08-13 03:21:16 +000049
Fariborz Jahanian279eda62009-01-21 22:04:16 +000050class ObjCCommonTypesHelper {
Owen Anderson170229f2009-07-14 23:10:40 +000051protected:
52 llvm::LLVMContext &VMContext;
Daniel Dunbar59e476b2009-08-03 17:06:42 +000053
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000054private:
John McCall9dc0db22011-05-15 01:53:33 +000055 // The types of these functions don't really matter because we
56 // should always bitcast before calling them.
57
58 /// id objc_msgSend (id, SEL, ...)
Fangrui Song6907ce22018-07-30 19:24:48 +000059 ///
John McCall9dc0db22011-05-15 01:53:33 +000060 /// The default messenger, used for sends whose ABI is unchanged from
61 /// the all-integer/pointer case.
James Y Knight9871db02019-02-05 16:42:33 +000062 llvm::FunctionCallee getMessageSendFn() const {
John McCall31168b02011-06-15 23:02:42 +000063 // Add the non-lazy-bind attribute, since objc_msgSend is likely to
64 // be called a lot.
Chris Lattnera5f58b02011-07-09 17:41:47 +000065 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Reid Klecknerde864822017-03-21 16:57:30 +000066 return CGM.CreateRuntimeFunction(
67 llvm::FunctionType::get(ObjectPtrTy, params, true), "objc_msgSend",
68 llvm::AttributeList::get(CGM.getLLVMContext(),
69 llvm::AttributeList::FunctionIndex,
70 llvm::Attribute::NonLazyBind));
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000071 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000072
John McCall9dc0db22011-05-15 01:53:33 +000073 /// void objc_msgSend_stret (id, SEL, ...)
74 ///
75 /// The messenger used when the return value is an aggregate returned
76 /// by indirect reference in the first argument, and therefore the
77 /// self and selector parameters are shifted over by one.
James Y Knight9871db02019-02-05 16:42:33 +000078 llvm::FunctionCallee getMessageSendStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000079 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +000080 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
81 params, true),
82 "objc_msgSend_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000083 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000084
John McCall9dc0db22011-05-15 01:53:33 +000085 /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
86 ///
87 /// The messenger used when the return value is returned on the x87
88 /// floating-point stack; without a special entrypoint, the nil case
89 /// would be unbalanced.
James Y Knight9871db02019-02-05 16:42:33 +000090 llvm::FunctionCallee getMessageSendFpretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000091 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Chris Lattnerece04092012-02-07 00:39:47 +000092 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
93 params, true),
John McCall9dc0db22011-05-15 01:53:33 +000094 "objc_msgSend_fpret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000095 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000096
Anders Carlsson2f1a6c32011-10-31 16:27:11 +000097 /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
98 ///
99 /// The messenger used when the return value is returned in two values on the
100 /// x87 floating point stack; without a special entrypoint, the nil case
101 /// would be unbalanced. Only used on 64-bit X86.
James Y Knight9871db02019-02-05 16:42:33 +0000102 llvm::FunctionCallee getMessageSendFp2retFn() const {
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000103 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
104 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
Serge Guelton1d993272017-05-09 19:31:30 +0000105 llvm::Type *resultType =
106 llvm::StructType::get(longDoubleType, longDoubleType);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000107
108 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
109 params, true),
110 "objc_msgSend_fp2ret");
111 }
112
John McCall9dc0db22011-05-15 01:53:33 +0000113 /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
114 ///
115 /// The messenger used for super calls, which have different dispatch
116 /// semantics. The class passed is the superclass of the current
117 /// class.
James Y Knight9871db02019-02-05 16:42:33 +0000118 llvm::FunctionCallee getMessageSendSuperFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000119 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000120 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000121 params, true),
122 "objc_msgSendSuper");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000123 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000124
John McCall9dc0db22011-05-15 01:53:33 +0000125 /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
126 ///
127 /// A slightly different messenger used for super calls. The class
128 /// passed is the current class.
James Y Knight9871db02019-02-05 16:42:33 +0000129 llvm::FunctionCallee getMessageSendSuperFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000130 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000131 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000132 params, true),
133 "objc_msgSendSuper2");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000134 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000135
John McCall9dc0db22011-05-15 01:53:33 +0000136 /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
137 /// SEL op, ...)
138 ///
139 /// The messenger used for super calls which return an aggregate indirectly.
James Y Knight9871db02019-02-05 16:42:33 +0000140 llvm::FunctionCallee getMessageSendSuperStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000141 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000142 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000143 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000144 "objc_msgSendSuper_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000145 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000146
John McCall9dc0db22011-05-15 01:53:33 +0000147 /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
148 /// SEL op, ...)
149 ///
150 /// objc_msgSendSuper_stret with the super2 semantics.
James Y Knight9871db02019-02-05 16:42:33 +0000151 llvm::FunctionCallee getMessageSendSuperStretFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000152 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000153 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000154 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000155 "objc_msgSendSuper2_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000156 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000157
James Y Knight9871db02019-02-05 16:42:33 +0000158 llvm::FunctionCallee getMessageSendSuperFpretFn() const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000159 // There is no objc_msgSendSuper_fpret? How can that work?
160 return getMessageSendSuperFn();
161 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000162
James Y Knight9871db02019-02-05 16:42:33 +0000163 llvm::FunctionCallee getMessageSendSuperFpretFn2() const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000164 // There is no objc_msgSendSuper_fpret? How can that work?
165 return getMessageSendSuperFn2();
166 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000167
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000168protected:
169 CodeGen::CodeGenModule &CGM;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000170
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000171public:
John McCall176f8922016-11-30 02:39:18 +0000172 llvm::IntegerType *ShortTy, *IntTy, *LongTy;
173 llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
Tim Northover238b5082014-03-29 13:42:40 +0000174 llvm::Type *IvarOffsetVarTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000175
Daniel Dunbar5d715592008-08-12 05:28:47 +0000176 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
John McCall176f8922016-11-30 02:39:18 +0000177 llvm::PointerType *ObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000178
Fariborz Jahanian406b1172008-11-18 20:18:11 +0000179 /// PtrObjectPtrTy - LLVM type for id *
John McCall176f8922016-11-30 02:39:18 +0000180 llvm::PointerType *PtrObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000181
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000182 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
John McCall176f8922016-11-30 02:39:18 +0000183 llvm::PointerType *SelectorPtrTy;
Fangrui Song6907ce22018-07-30 19:24:48 +0000184
Douglas Gregor020de322012-01-17 18:36:30 +0000185private:
Daniel Dunbarb036db82008-08-13 03:21:16 +0000186 /// ProtocolPtrTy - LLVM type for external protocol handles
187 /// (typeof(Protocol))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000188 llvm::Type *ExternalProtocolPtrTy;
Fangrui Song6907ce22018-07-30 19:24:48 +0000189
Douglas Gregor020de322012-01-17 18:36:30 +0000190public:
191 llvm::Type *getExternalProtocolPtrTy() {
192 if (!ExternalProtocolPtrTy) {
193 // FIXME: It would be nice to unify this with the opaque type, so that the
194 // IR comes out a bit cleaner.
195 CodeGen::CodeGenTypes &Types = CGM.getTypes();
196 ASTContext &Ctx = CGM.getContext();
197 llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
198 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
199 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000200
Douglas Gregor020de322012-01-17 18:36:30 +0000201 return ExternalProtocolPtrTy;
202 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000203
Daniel Dunbarc722b852008-08-30 03:02:31 +0000204 // SuperCTy - clang type for struct objc_super.
205 QualType SuperCTy;
206 // SuperPtrCTy - clang type for struct objc_super *.
207 QualType SuperPtrCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000208
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000209 /// SuperTy - LLVM type for struct objc_super.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000210 llvm::StructType *SuperTy;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +0000211 /// SuperPtrTy - LLVM type for struct objc_super *.
John McCall176f8922016-11-30 02:39:18 +0000212 llvm::PointerType *SuperPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000213
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000214 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
215 /// in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000216 llvm::StructType *PropertyTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000217
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000218 /// PropertyListTy - LLVM type for struct objc_property_list
219 /// (_prop_list_t in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000220 llvm::StructType *PropertyListTy;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000221 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
John McCall176f8922016-11-30 02:39:18 +0000222 llvm::PointerType *PropertyListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000223
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000224 // MethodTy - LLVM type for struct objc_method.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000225 llvm::StructType *MethodTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000226
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000227 /// CacheTy - LLVM type for struct objc_cache.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000228 llvm::Type *CacheTy;
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000229 /// CachePtrTy - LLVM type for struct objc_cache *.
John McCall176f8922016-11-30 02:39:18 +0000230 llvm::PointerType *CachePtrTy;
Fangrui Song6907ce22018-07-30 19:24:48 +0000231
James Y Knight9871db02019-02-05 16:42:33 +0000232 llvm::FunctionCallee getGetPropertyFn() {
Chris Lattnerce8754e2009-04-22 02:44:54 +0000233 CodeGen::CodeGenTypes &Types = CGM.getTypes();
234 ASTContext &Ctx = CGM.getContext();
235 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
John McCall2da83a32010-02-26 00:48:12 +0000236 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
237 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Benjamin Kramer30934732016-07-02 11:41:41 +0000238 CanQualType Params[] = {
239 IdType, SelType,
240 Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), Ctx.BoolTy};
Chris Lattner2192fe52011-07-18 04:24:23 +0000241 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000242 Types.GetFunctionType(
243 Types.arrangeBuiltinFunctionDeclaration(IdType, Params));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000244 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
245 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000246
James Y Knight9871db02019-02-05 16:42:33 +0000247 llvm::FunctionCallee getSetPropertyFn() {
Chris Lattnerce8754e2009-04-22 02:44:54 +0000248 CodeGen::CodeGenTypes &Types = CGM.getTypes();
249 ASTContext &Ctx = CGM.getContext();
250 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
John McCall2da83a32010-02-26 00:48:12 +0000251 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
252 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Benjamin Kramer30934732016-07-02 11:41:41 +0000253 CanQualType Params[] = {
254 IdType,
255 SelType,
256 Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(),
257 IdType,
258 Ctx.BoolTy,
259 Ctx.BoolTy};
Chris Lattner2192fe52011-07-18 04:24:23 +0000260 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000261 Types.GetFunctionType(
262 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000263 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
264 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000265
James Y Knight9871db02019-02-05 16:42:33 +0000266 llvm::FunctionCallee getOptimizedSetPropertyFn(bool atomic, bool copy) {
Ted Kremeneke65b0862012-03-06 20:05:56 +0000267 CodeGen::CodeGenTypes &Types = CGM.getTypes();
268 ASTContext &Ctx = CGM.getContext();
Fangrui Song6907ce22018-07-30 19:24:48 +0000269 // void objc_setProperty_atomic(id self, SEL _cmd,
Ted Kremeneke65b0862012-03-06 20:05:56 +0000270 // id newValue, ptrdiff_t offset);
Fangrui Song6907ce22018-07-30 19:24:48 +0000271 // void objc_setProperty_nonatomic(id self, SEL _cmd,
Ted Kremeneke65b0862012-03-06 20:05:56 +0000272 // id newValue, ptrdiff_t offset);
Fangrui Song6907ce22018-07-30 19:24:48 +0000273 // void objc_setProperty_atomic_copy(id self, SEL _cmd,
Ted Kremeneke65b0862012-03-06 20:05:56 +0000274 // id newValue, ptrdiff_t offset);
Fangrui Song6907ce22018-07-30 19:24:48 +0000275 // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
Ted Kremeneke65b0862012-03-06 20:05:56 +0000276 // id newValue, ptrdiff_t offset);
Fangrui Song6907ce22018-07-30 19:24:48 +0000277
Ted Kremeneke65b0862012-03-06 20:05:56 +0000278 SmallVector<CanQualType,4> Params;
279 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
280 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
281 Params.push_back(IdType);
282 Params.push_back(SelType);
283 Params.push_back(IdType);
284 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
285 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000286 Types.GetFunctionType(
287 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Ted Kremeneke65b0862012-03-06 20:05:56 +0000288 const char *name;
289 if (atomic && copy)
290 name = "objc_setProperty_atomic_copy";
291 else if (atomic && !copy)
292 name = "objc_setProperty_atomic";
293 else if (!atomic && copy)
294 name = "objc_setProperty_nonatomic_copy";
295 else
296 name = "objc_setProperty_nonatomic";
Fangrui Song6907ce22018-07-30 19:24:48 +0000297
Ted Kremeneke65b0862012-03-06 20:05:56 +0000298 return CGM.CreateRuntimeFunction(FTy, name);
299 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000300
James Y Knight9871db02019-02-05 16:42:33 +0000301 llvm::FunctionCallee getCopyStructFn() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000302 CodeGen::CodeGenTypes &Types = CGM.getTypes();
303 ASTContext &Ctx = CGM.getContext();
304 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000305 SmallVector<CanQualType,5> Params;
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000306 Params.push_back(Ctx.VoidPtrTy);
307 Params.push_back(Ctx.VoidPtrTy);
Saleem Abdulrasool91d9bfc2017-06-17 17:30:31 +0000308 Params.push_back(Ctx.getSizeType());
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000309 Params.push_back(Ctx.BoolTy);
310 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000311 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000312 Types.GetFunctionType(
313 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000314 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
315 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000316
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000317 /// This routine declares and returns address of:
318 /// void objc_copyCppObjectAtomic(
Fangrui Song6907ce22018-07-30 19:24:48 +0000319 /// void *dest, const void *src,
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000320 /// void (*copyHelper) (void *dest, const void *source));
James Y Knight9871db02019-02-05 16:42:33 +0000321 llvm::FunctionCallee getCppAtomicObjectFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000322 CodeGen::CodeGenTypes &Types = CGM.getTypes();
323 ASTContext &Ctx = CGM.getContext();
324 /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
325 SmallVector<CanQualType,3> Params;
326 Params.push_back(Ctx.VoidPtrTy);
327 Params.push_back(Ctx.VoidPtrTy);
328 Params.push_back(Ctx.VoidPtrTy);
329 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000330 Types.GetFunctionType(
331 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000332 return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
333 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000334
James Y Knight9871db02019-02-05 16:42:33 +0000335 llvm::FunctionCallee getEnumerationMutationFn() {
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000336 CodeGen::CodeGenTypes &Types = CGM.getTypes();
337 ASTContext &Ctx = CGM.getContext();
Chris Lattnerce8754e2009-04-22 02:44:54 +0000338 // void objc_enumerationMutation (id)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000339 SmallVector<CanQualType,1> Params;
John McCall2da83a32010-02-26 00:48:12 +0000340 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Chris Lattner2192fe52011-07-18 04:24:23 +0000341 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000342 Types.GetFunctionType(
343 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000344 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
345 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000346
James Y Knight9871db02019-02-05 16:42:33 +0000347 llvm::FunctionCallee getLookUpClassFn() {
Douglas Gregor24ae22c2016-04-01 23:23:52 +0000348 CodeGen::CodeGenTypes &Types = CGM.getTypes();
349 ASTContext &Ctx = CGM.getContext();
350 // Class objc_lookUpClass (const char *)
351 SmallVector<CanQualType,1> Params;
352 Params.push_back(
353 Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst())));
354 llvm::FunctionType *FTy =
355 Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration(
356 Ctx.getCanonicalType(Ctx.getObjCClassType()),
357 Params));
358 return CGM.CreateRuntimeFunction(FTy, "objc_lookUpClass");
359 }
360
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000361 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
James Y Knight9871db02019-02-05 16:42:33 +0000362 llvm::FunctionCallee getGcReadWeakFn() {
Chris Lattnerce8754e2009-04-22 02:44:54 +0000363 // id objc_read_weak (id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000364 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000365 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000366 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000367 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000368 }
369
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000370 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
James Y Knight9871db02019-02-05 16:42:33 +0000371 llvm::FunctionCallee getGcAssignWeakFn() {
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000372 // id objc_assign_weak (id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000373 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000374 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000375 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000376 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
377 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000378
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000379 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
James Y Knight9871db02019-02-05 16:42:33 +0000380 llvm::FunctionCallee getGcAssignGlobalFn() {
Chris Lattner0a696a422009-04-22 02:38:11 +0000381 // id objc_assign_global(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000382 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000383 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000384 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000385 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
386 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000387
Fariborz Jahanian217af242010-07-20 20:30:03 +0000388 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
James Y Knight9871db02019-02-05 16:42:33 +0000389 llvm::FunctionCallee getGcAssignThreadLocalFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000390 // id objc_assign_threadlocal(id src, id * dest)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000391 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian217af242010-07-20 20:30:03 +0000392 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000393 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian217af242010-07-20 20:30:03 +0000394 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
395 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000396
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000397 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
James Y Knight9871db02019-02-05 16:42:33 +0000398 llvm::FunctionCallee getGcAssignIvarFn() {
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000399 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000400 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
401 CGM.PtrDiffTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000402 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000403 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000404 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
405 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000406
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000407 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
James Y Knight9871db02019-02-05 16:42:33 +0000408 llvm::FunctionCallee GcMemmoveCollectableFn() {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000409 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000410 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
John McCall9dc0db22011-05-15 01:53:33 +0000411 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000412 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
413 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000414
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000415 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
James Y Knight9871db02019-02-05 16:42:33 +0000416 llvm::FunctionCallee getGcAssignStrongCastFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000417 // id objc_assign_strongCast(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000418 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000419 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000420 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000421 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
422 }
Anders Carlsson9ab53d12009-02-16 22:59:18 +0000423
424 /// ExceptionThrowFn - LLVM objc_exception_throw function.
James Y Knight9871db02019-02-05 16:42:33 +0000425 llvm::FunctionCallee getExceptionThrowFn() {
Chris Lattner0a696a422009-04-22 02:38:11 +0000426 // void objc_exception_throw(id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000427 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000428 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000429 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000430 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
431 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000432
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000433 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
James Y Knight9871db02019-02-05 16:42:33 +0000434 llvm::FunctionCallee getExceptionRethrowFn() {
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000435 // void objc_exception_rethrow(void)
John McCall9dc0db22011-05-15 01:53:33 +0000436 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000437 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
438 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000439
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000440 /// SyncEnterFn - LLVM object_sync_enter function.
James Y Knight9871db02019-02-05 16:42:33 +0000441 llvm::FunctionCallee getSyncEnterFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000442 // int objc_sync_enter (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000443 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerdcceee72009-04-06 16:53:45 +0000444 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000445 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000446 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
447 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000448
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000449 /// SyncExitFn - LLVM object_sync_exit function.
James Y Knight9871db02019-02-05 16:42:33 +0000450 llvm::FunctionCallee getSyncExitFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000451 // int objc_sync_exit (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000452 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000453 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000454 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000455 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
456 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000457
James Y Knight9871db02019-02-05 16:42:33 +0000458 llvm::FunctionCallee getSendFn(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000459 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
460 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000461
James Y Knight9871db02019-02-05 16:42:33 +0000462 llvm::FunctionCallee getSendFn2(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000463 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
464 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000465
James Y Knight9871db02019-02-05 16:42:33 +0000466 llvm::FunctionCallee getSendStretFn(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000467 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
468 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000469
James Y Knight9871db02019-02-05 16:42:33 +0000470 llvm::FunctionCallee getSendStretFn2(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000471 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
472 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000473
James Y Knight9871db02019-02-05 16:42:33 +0000474 llvm::FunctionCallee getSendFpretFn(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000475 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
476 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000477
James Y Knight9871db02019-02-05 16:42:33 +0000478 llvm::FunctionCallee getSendFpretFn2(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000479 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
480 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000481
James Y Knight9871db02019-02-05 16:42:33 +0000482 llvm::FunctionCallee getSendFp2retFn(bool IsSuper) const {
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000483 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
484 }
485
James Y Knight9871db02019-02-05 16:42:33 +0000486 llvm::FunctionCallee getSendFp2RetFn2(bool IsSuper) const {
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000487 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
488 }
489
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000490 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000491};
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000492
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000493/// ObjCTypesHelper - Helper class that encapsulates lazy
494/// construction of varies types used during ObjC generation.
495class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000496public:
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000497 /// SymtabTy - LLVM type for struct objc_symtab.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000498 llvm::StructType *SymtabTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000499 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
John McCall176f8922016-11-30 02:39:18 +0000500 llvm::PointerType *SymtabPtrTy;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000501 /// ModuleTy - LLVM type for struct objc_module.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000502 llvm::StructType *ModuleTy;
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000503
Daniel Dunbarb036db82008-08-13 03:21:16 +0000504 /// ProtocolTy - LLVM type for struct objc_protocol.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000505 llvm::StructType *ProtocolTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000506 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
John McCall176f8922016-11-30 02:39:18 +0000507 llvm::PointerType *ProtocolPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000508 /// ProtocolExtensionTy - LLVM type for struct
509 /// objc_protocol_extension.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000510 llvm::StructType *ProtocolExtensionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000511 /// ProtocolExtensionTy - LLVM type for struct
512 /// objc_protocol_extension *.
John McCall176f8922016-11-30 02:39:18 +0000513 llvm::PointerType *ProtocolExtensionPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000514 /// MethodDescriptionTy - LLVM type for struct
515 /// objc_method_description.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000516 llvm::StructType *MethodDescriptionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000517 /// MethodDescriptionListTy - LLVM type for struct
518 /// objc_method_description_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000519 llvm::StructType *MethodDescriptionListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000520 /// MethodDescriptionListPtrTy - LLVM type for struct
521 /// objc_method_description_list *.
John McCall176f8922016-11-30 02:39:18 +0000522 llvm::PointerType *MethodDescriptionListPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000523 /// ProtocolListTy - LLVM type for struct objc_property_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000524 llvm::StructType *ProtocolListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000525 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
John McCall176f8922016-11-30 02:39:18 +0000526 llvm::PointerType *ProtocolListPtrTy;
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000527 /// CategoryTy - LLVM type for struct objc_category.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000528 llvm::StructType *CategoryTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000529 /// ClassTy - LLVM type for struct objc_class.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000530 llvm::StructType *ClassTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000531 /// ClassPtrTy - LLVM type for struct objc_class *.
John McCall176f8922016-11-30 02:39:18 +0000532 llvm::PointerType *ClassPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000533 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000534 llvm::StructType *ClassExtensionTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000535 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
John McCall176f8922016-11-30 02:39:18 +0000536 llvm::PointerType *ClassExtensionPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000537 // IvarTy - LLVM type for struct objc_ivar.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000538 llvm::StructType *IvarTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000539 /// IvarListTy - LLVM type for struct objc_ivar_list.
John McCall176f8922016-11-30 02:39:18 +0000540 llvm::StructType *IvarListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000541 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
John McCall176f8922016-11-30 02:39:18 +0000542 llvm::PointerType *IvarListPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000543 /// MethodListTy - LLVM type for struct objc_method_list.
John McCall176f8922016-11-30 02:39:18 +0000544 llvm::StructType *MethodListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000545 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
John McCall176f8922016-11-30 02:39:18 +0000546 llvm::PointerType *MethodListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000547
Anders Carlsson9ff22482008-09-09 10:10:21 +0000548 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
John McCall176f8922016-11-30 02:39:18 +0000549 llvm::StructType *ExceptionDataTy;
Fangrui Song6907ce22018-07-30 19:24:48 +0000550
Anders Carlsson9ff22482008-09-09 10:10:21 +0000551 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
James Y Knight9871db02019-02-05 16:42:33 +0000552 llvm::FunctionCallee getExceptionTryEnterFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000553 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000554 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000555 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000556 "objc_exception_try_enter");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000557 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000558
559 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
James Y Knight9871db02019-02-05 16:42:33 +0000560 llvm::FunctionCallee getExceptionTryExitFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000561 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000562 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000563 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000564 "objc_exception_try_exit");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000565 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000566
567 /// ExceptionExtractFn - LLVM objc_exception_extract function.
James Y Knight9871db02019-02-05 16:42:33 +0000568 llvm::FunctionCallee getExceptionExtractFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000569 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000570 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000571 params, false),
Chris Lattnerc6406db2009-04-22 02:26:14 +0000572 "objc_exception_extract");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000573 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000574
Anders Carlsson9ff22482008-09-09 10:10:21 +0000575 /// ExceptionMatchFn - LLVM objc_exception_match function.
James Y Knight9871db02019-02-05 16:42:33 +0000576 llvm::FunctionCallee getExceptionMatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000577 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000578 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000579 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000580 "objc_exception_match");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000581 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000582
Anders Carlsson9ff22482008-09-09 10:10:21 +0000583 /// SetJmpFn - LLVM _setjmp function.
James Y Knight9871db02019-02-05 16:42:33 +0000584 llvm::FunctionCallee getSetJmpFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000585 // This is specifically the prototype for x86.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000586 llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
Reid Klecknerde864822017-03-21 16:57:30 +0000587 return CGM.CreateRuntimeFunction(
588 llvm::FunctionType::get(CGM.Int32Ty, params, false), "_setjmp",
589 llvm::AttributeList::get(CGM.getLLVMContext(),
590 llvm::AttributeList::FunctionIndex,
591 llvm::Attribute::NonLazyBind));
Chris Lattnerc6406db2009-04-22 02:26:14 +0000592 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000593
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000594public:
595 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000596};
597
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000598/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000599/// modern abi
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000600class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000601public:
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000602 // MethodListnfABITy - LLVM for struct _method_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000603 llvm::StructType *MethodListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000604
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000605 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
John McCall176f8922016-11-30 02:39:18 +0000606 llvm::PointerType *MethodListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000607
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000608 // ProtocolnfABITy = LLVM for struct _protocol_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000609 llvm::StructType *ProtocolnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000610
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000611 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
John McCall176f8922016-11-30 02:39:18 +0000612 llvm::PointerType *ProtocolnfABIPtrTy;
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000613
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000614 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
Chris Lattnera5f58b02011-07-09 17:41:47 +0000615 llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000616
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000617 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
John McCall176f8922016-11-30 02:39:18 +0000618 llvm::PointerType *ProtocolListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000619
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000620 // ClassnfABITy - LLVM for struct _class_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000621 llvm::StructType *ClassnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000622
Fariborz Jahanian71394042009-01-23 23:53:38 +0000623 // ClassnfABIPtrTy - LLVM for struct _class_t*
John McCall176f8922016-11-30 02:39:18 +0000624 llvm::PointerType *ClassnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000625
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000626 // IvarnfABITy - LLVM for struct _ivar_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000627 llvm::StructType *IvarnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000628
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000629 // IvarListnfABITy - LLVM for struct _ivar_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000630 llvm::StructType *IvarListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000631
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000632 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
John McCall176f8922016-11-30 02:39:18 +0000633 llvm::PointerType *IvarListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000634
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000635 // ClassRonfABITy - LLVM for struct _class_ro_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000636 llvm::StructType *ClassRonfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000637
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000638 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
John McCall176f8922016-11-30 02:39:18 +0000639 llvm::PointerType *ImpnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000640
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000641 // CategorynfABITy - LLVM for struct _category_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000642 llvm::StructType *CategorynfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000643
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000644 // New types for nonfragile abi messaging.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000645
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000646 // MessageRefTy - LLVM for:
647 // struct _message_ref_t {
648 // IMP messenger;
649 // SEL name;
650 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000651 llvm::StructType *MessageRefTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000652 // MessageRefCTy - clang type for struct _message_ref_t
653 QualType MessageRefCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000654
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000655 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000656 llvm::Type *MessageRefPtrTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000657 // MessageRefCPtrTy - clang type for struct _message_ref_t*
658 QualType MessageRefCPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000659
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000660 // SuperMessageRefTy - LLVM for:
661 // struct _super_message_ref_t {
662 // SUPER_IMP messenger;
663 // SEL name;
664 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000665 llvm::StructType *SuperMessageRefTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000666
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000667 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
John McCall176f8922016-11-30 02:39:18 +0000668 llvm::PointerType *SuperMessageRefPtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000669
James Y Knight9871db02019-02-05 16:42:33 +0000670 llvm::FunctionCallee getMessageSendFixupFn() {
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000671 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000672 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000673 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000674 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000675 "objc_msgSend_fixup");
676 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000677
James Y Knight9871db02019-02-05 16:42:33 +0000678 llvm::FunctionCallee getMessageSendFpretFixupFn() {
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000679 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000680 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000681 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000682 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000683 "objc_msgSend_fpret_fixup");
684 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000685
James Y Knight9871db02019-02-05 16:42:33 +0000686 llvm::FunctionCallee getMessageSendStretFixupFn() {
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000687 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000688 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000689 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000690 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000691 "objc_msgSend_stret_fixup");
692 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000693
James Y Knight9871db02019-02-05 16:42:33 +0000694 llvm::FunctionCallee getMessageSendSuper2FixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000695 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000696 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000697 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000698 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000699 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000700 "objc_msgSendSuper2_fixup");
701 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000702
James Y Knight9871db02019-02-05 16:42:33 +0000703 llvm::FunctionCallee getMessageSendSuper2StretFixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000704 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000705 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000706 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000707 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000708 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000709 "objc_msgSendSuper2_stret_fixup");
710 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000711
James Y Knight9871db02019-02-05 16:42:33 +0000712 llvm::FunctionCallee getObjCEndCatchFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000713 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000714 "objc_end_catch");
Chris Lattnera7c00b42009-04-22 02:15:23 +0000715 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000716
James Y Knight9871db02019-02-05 16:42:33 +0000717 llvm::FunctionCallee getObjCBeginCatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000718 llvm::Type *params[] = { Int8PtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000719 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000720 params, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000721 "objc_begin_catch");
722 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +0000723
John McCall2c91c3b2019-05-30 04:09:01 +0000724 /// Class objc_loadClassref (void *)
725 ///
726 /// Loads from a classref. For Objective-C stub classes, this invokes the
727 /// initialization callback stored inside the stub. For all other classes
728 /// this simply dereferences the pointer.
729 llvm::FunctionCallee getLoadClassrefFn() const {
730 // Add the non-lazy-bind attribute, since objc_loadClassref is likely to
731 // be called a lot.
732 //
733 // Also it is safe to make it readnone, since we never load or store the
734 // classref except by calling this function.
735 llvm::Type *params[] = { Int8PtrPtrTy };
736 llvm::FunctionCallee F = CGM.CreateRuntimeFunction(
737 llvm::FunctionType::get(ClassnfABIPtrTy, params, false),
738 "objc_loadClassref",
739 llvm::AttributeList::get(CGM.getLLVMContext(),
740 llvm::AttributeList::FunctionIndex,
741 {llvm::Attribute::NonLazyBind,
742 llvm::Attribute::ReadNone,
743 llvm::Attribute::NoUnwind}));
744 if (!CGM.getTriple().isOSBinFormatCOFF())
745 cast<llvm::Function>(F.getCallee())->setLinkage(
746 llvm::Function::ExternalWeakLinkage);
747
748 return F;
749 }
750
Chris Lattnera5f58b02011-07-09 17:41:47 +0000751 llvm::StructType *EHTypeTy;
752 llvm::Type *EHTypePtrTy;
Fangrui Song6907ce22018-07-30 19:24:48 +0000753
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000754 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000755};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000756
Saleem Abdulrasool271106c2016-09-16 23:41:13 +0000757enum class ObjCLabelType {
758 ClassName,
759 MethodVarName,
760 MethodVarType,
761 PropertyName,
762};
763
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000764class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000765public:
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000766 class SKIP_SCAN {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000767 public:
768 unsigned skip;
769 unsigned scan;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000770 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000771 : skip(_skip), scan(_scan) {}
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000772 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000773
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000774 /// opcode for captured block variables layout 'instructions'.
775 /// In the following descriptions, 'I' is the value of the immediate field.
776 /// (field following the opcode).
777 ///
778 enum BLOCK_LAYOUT_OPCODE {
779 /// An operator which affects how the following layout should be
780 /// interpreted.
781 /// I == 0: Halt interpretation and treat everything else as
782 /// a non-pointer. Note that this instruction is equal
783 /// to '\0'.
784 /// I != 0: Currently unused.
785 BLOCK_LAYOUT_OPERATOR = 0,
Fangrui Song6907ce22018-07-30 19:24:48 +0000786
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000787 /// The next I+1 bytes do not contain a value of object pointer type.
788 /// Note that this can leave the stream unaligned, meaning that
789 /// subsequent word-size instructions do not begin at a multiple of
790 /// the pointer size.
791 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
Fangrui Song6907ce22018-07-30 19:24:48 +0000792
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000793 /// The next I+1 words do not contain a value of object pointer type.
794 /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
795 /// when the required skip quantity is a multiple of the pointer size.
796 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
Fangrui Song6907ce22018-07-30 19:24:48 +0000797
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000798 /// The next I+1 words are __strong pointers to Objective-C
799 /// objects or blocks.
800 BLOCK_LAYOUT_STRONG = 3,
Fangrui Song6907ce22018-07-30 19:24:48 +0000801
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000802 /// The next I+1 words are pointers to __block variables.
803 BLOCK_LAYOUT_BYREF = 4,
Fangrui Song6907ce22018-07-30 19:24:48 +0000804
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000805 /// The next I+1 words are __weak pointers to Objective-C
806 /// objects or blocks.
807 BLOCK_LAYOUT_WEAK = 5,
Fangrui Song6907ce22018-07-30 19:24:48 +0000808
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000809 /// The next I+1 words are __unsafe_unretained pointers to
810 /// Objective-C objects or blocks.
811 BLOCK_LAYOUT_UNRETAINED = 6
Fangrui Song6907ce22018-07-30 19:24:48 +0000812
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000813 /// The next I+1 words are block or object pointers with some
814 /// as-yet-unspecified ownership semantics. If we add more
815 /// flavors of ownership semantics, values will be taken from
816 /// this range.
817 ///
818 /// This is included so that older tools can at least continue
819 /// processing the layout past such things.
820 //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
Fangrui Song6907ce22018-07-30 19:24:48 +0000821
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000822 /// All other opcodes are reserved. Halt interpretation and
823 /// treat everything else as opaque.
824 };
Fangrui Song6907ce22018-07-30 19:24:48 +0000825
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000826 class RUN_SKIP {
827 public:
828 enum BLOCK_LAYOUT_OPCODE opcode;
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000829 CharUnits block_var_bytepos;
830 CharUnits block_var_size;
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000831 RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000832 CharUnits BytePos = CharUnits::Zero(),
833 CharUnits Size = CharUnits::Zero())
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +0000834 : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
Fangrui Song6907ce22018-07-30 19:24:48 +0000835
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000836 // Allow sorting based on byte pos.
837 bool operator<(const RUN_SKIP &b) const {
838 return block_var_bytepos < b.block_var_bytepos;
839 }
840 };
Fangrui Song6907ce22018-07-30 19:24:48 +0000841
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000842protected:
Owen Andersonae86c192009-07-13 04:10:07 +0000843 llvm::LLVMContext &VMContext;
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000844 // FIXME! May not be needing this after all.
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000845 unsigned ObjCABI;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000846
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000847 // arc/mrr layout of captured block literal variables.
848 SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000849
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000850 /// LazySymbols - Symbols to generate a lazy reference for. See
851 /// DefinedSymbols and FinishModule().
Daniel Dunbard027a922009-09-07 00:20:42 +0000852 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000853
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000854 /// DefinedSymbols - External symbols which are defined by this
855 /// module. The symbols in this list and LazySymbols are used to add
856 /// special linker symbols which ensure that Objective-C modules are
857 /// linked properly.
Daniel Dunbard027a922009-09-07 00:20:42 +0000858 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000859
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000860 /// ClassNames - uniqued class names.
Fariborz Jahanian451b92a2014-07-16 16:16:04 +0000861 llvm::StringMap<llvm::GlobalVariable*> ClassNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000862
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000863 /// MethodVarNames - uniqued method variable names.
864 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000865
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000866 /// DefinedCategoryNames - list of category names in form Class_Category.
Justin Lebar5e83dfe2016-10-21 21:45:01 +0000867 llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames;
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000868
Daniel Dunbarb036db82008-08-13 03:21:16 +0000869 /// MethodVarTypes - uniqued method type signatures. We have to use
870 /// a StringMap here because have no other unique reference.
871 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000872
Daniel Dunbar3c76cb52008-08-26 21:51:14 +0000873 /// MethodDefinitions - map of methods which have been defined in
874 /// this translation unit.
875 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000876
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -0800877 /// DirectMethodDefinitions - map of direct methods which have been defined in
878 /// this translation unit.
879 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> DirectMethodDefinitions;
880
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000881 /// PropertyNames - uniqued method variable names.
882 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000883
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000884 /// ClassReferences - uniqued class references.
885 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000886
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000887 /// SelectorReferences - uniqued selector references.
888 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000889
Daniel Dunbarb036db82008-08-13 03:21:16 +0000890 /// Protocols - Protocols for which an objc_protocol structure has
891 /// been emitted. Forward declarations are handled by creating an
892 /// empty structure whose initializer is filled in when/if defined.
893 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000894
Daniel Dunbarc475d422008-10-29 22:36:39 +0000895 /// DefinedProtocols - Protocols which have actually been
896 /// defined. We should not need this, see FIXME in GenerateProtocol.
897 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000898
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000899 /// DefinedClasses - List of defined classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000900 SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
Fangrui Song6907ce22018-07-30 19:24:48 +0000901
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +0000902 /// ImplementedClasses - List of @implemented classes.
903 SmallVector<const ObjCInterfaceDecl*, 16> ImplementedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000904
905 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000906 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000907
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000908 /// DefinedCategories - List of defined categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000909 SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000910
John McCall2c91c3b2019-05-30 04:09:01 +0000911 /// DefinedStubCategories - List of defined categories on class stubs.
912 SmallVector<llvm::GlobalValue*, 16> DefinedStubCategories;
913
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000914 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000915 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000916
John McCallcd21d542016-11-30 23:15:55 +0000917 /// Cached reference to the class for constant strings. This value has type
918 /// int * but is actually an Obj-C class pointer.
Sanjoy Dase369bd92017-05-01 17:08:00 +0000919 llvm::WeakTrackingVH ConstantStringClassRef;
John McCallcd21d542016-11-30 23:15:55 +0000920
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000921 /// The LLVM type corresponding to NSConstantString.
John McCallcd21d542016-11-30 23:15:55 +0000922 llvm::StructType *NSConstantStringType = nullptr;
923
924 llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
925
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000926 /// GetNameForMethod - Return a name for the given method.
927 /// \param[out] NameOut - The return value.
928 void GetNameForMethod(const ObjCMethodDecl *OMD,
929 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000930 SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000931
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000932 /// GetMethodVarName - Return a unique constant for the given
933 /// selector's name. The return value has type char *.
934 llvm::Constant *GetMethodVarName(Selector Sel);
935 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000936
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000937 /// GetMethodVarType - Return a unique constant for the given
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000938 /// method's type encoding string. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000939
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000940 // FIXME: This is a horrible name.
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000941 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
942 bool Extended = false);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000943 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000944
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000945 /// GetPropertyName - Return a unique constant for the given
946 /// name. The return value has type char *.
947 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000948
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000949 // FIXME: This can be dropped once string functions are unified.
950 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
951 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000952
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000953 /// GetClassName - Return a unique constant for the given selector's
Fariborz Jahanian451b92a2014-07-16 16:16:04 +0000954 /// runtime name (which may change via use of objc_runtime_name attribute on
955 /// class or protocol definition. The return value has type char *.
956 llvm::Constant *GetClassName(StringRef RuntimeName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000957
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000958 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
959
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000960 /// BuildIvarLayout - Builds ivar layout bitmap for the class
961 /// implementation for the __strong or __weak case.
962 ///
John McCall460ce582015-10-22 18:38:17 +0000963 /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there
964 /// are any weak ivars defined directly in the class. Meaningless unless
965 /// building a weak layout. Does not guarantee that the layout will
966 /// actually have any entries, because the ivar might be under-aligned.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000967 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
John McCall3fd13f062015-10-21 18:06:47 +0000968 CharUnits beginOffset,
969 CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +0000970 bool forStrongLayout,
971 bool hasMRCWeakIvars);
972
973 llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI,
974 CharUnits beginOffset,
975 CharUnits endOffset) {
976 return BuildIvarLayout(OI, beginOffset, endOffset, true, false);
977 }
978
979 llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI,
980 CharUnits beginOffset,
981 CharUnits endOffset,
982 bool hasMRCWeakIvars) {
983 return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
984 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000985
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000986 Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
Fangrui Song6907ce22018-07-30 19:24:48 +0000987
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000988 void UpdateRunSkipBlockVars(bool IsByref,
989 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000990 CharUnits FieldOffset,
991 CharUnits FieldSize);
Fangrui Song6907ce22018-07-30 19:24:48 +0000992
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000993 void BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000994 CharUnits BytePos, bool &HasUnion,
995 bool ByrefLayout=false);
Fangrui Song6907ce22018-07-30 19:24:48 +0000996
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000997 void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
998 const RecordDecl *RD,
999 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00001000 CharUnits BytePos, bool &HasUnion,
1001 bool ByrefLayout);
Fangrui Song6907ce22018-07-30 19:24:48 +00001002
Fariborz Jahanian23290b02012-11-01 18:32:55 +00001003 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
Fangrui Song6907ce22018-07-30 19:24:48 +00001004
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00001005 llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
Fangrui Song6907ce22018-07-30 19:24:48 +00001006
Fariborz Jahanian01dff422009-03-05 19:17:31 +00001007 /// GetIvarLayoutName - Returns a unique constant for the given
1008 /// ivar layout bitmap.
1009 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
1010 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001011
Fariborz Jahanian066347e2009-01-28 22:18:42 +00001012 /// EmitPropertyList - Emit the given property list. The return
1013 /// value has type PropertyListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001014 llvm::Constant *EmitPropertyList(Twine Name,
1015 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +00001016 const ObjCContainerDecl *OCD,
Manman Renad0e7912016-01-29 19:22:54 +00001017 const ObjCCommonTypesHelper &ObjCTypes,
1018 bool IsClassProperty);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001019
Fangrui Song6907ce22018-07-30 19:24:48 +00001020 /// EmitProtocolMethodTypes - Generate the array of extended method type
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001021 /// strings. The return value has type Int8PtrPtrTy.
Fangrui Song6907ce22018-07-30 19:24:48 +00001022 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
Zachary Turner41a9ee92017-10-11 23:54:34 +00001023 ArrayRef<llvm::Constant*> MethodTypes,
1024 const ObjCCommonTypesHelper &ObjCTypes);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001025
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001026 /// GetProtocolRef - Return a reference to the internal protocol
1027 /// description, creating an empty one if it has not been
1028 /// defined. The return value has type ProtocolPtrTy.
1029 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +00001030
Douglas Gregor24ae22c2016-04-01 23:23:52 +00001031 /// Return a reference to the given Class using runtime calls rather than
1032 /// by a symbol reference.
1033 llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
1034 const ObjCInterfaceDecl *ID,
1035 ObjCCommonTypesHelper &ObjCTypes);
1036
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00001037 std::string GetSectionName(StringRef Section, StringRef MachOAttributes);
1038
John McCall3fd13f062015-10-21 18:06:47 +00001039public:
Daniel Dunbar30c65362009-03-09 20:09:19 +00001040 /// CreateMetadataVar - Create a global variable with internal
1041 /// linkage for use by the Objective-C runtime.
1042 ///
1043 /// This is a convenience wrapper which not only creates the
1044 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +00001045 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001046 ///
1047 /// \param Name - The variable name.
1048 /// \param Init - The variable initializer; this is also used to
John McCall176f8922016-11-30 02:39:18 +00001049 /// define the type of the variable.
Alp Toker541d5072014-06-07 23:30:53 +00001050 /// \param Section - The section the variable should go into, or empty.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001051 /// \param Align - The alignment for the variable, or 0.
1052 /// \param AddToUsed - Whether the variable should be added to
John McCall176f8922016-11-30 02:39:18 +00001053 /// "llvm.used".
Zachary Turner41a9ee92017-10-11 23:54:34 +00001054 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
John McCall176f8922016-11-30 02:39:18 +00001055 ConstantStructBuilder &Init,
1056 StringRef Section, CharUnits Align,
1057 bool AddToUsed);
Zachary Turner41a9ee92017-10-11 23:54:34 +00001058 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
John McCall176f8922016-11-30 02:39:18 +00001059 llvm::Constant *Init,
John McCall7f416cc2015-09-08 08:05:57 +00001060 StringRef Section, CharUnits Align,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001061 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +00001062
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001063 llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00001064 ObjCLabelType LabelType,
1065 bool ForceNonFragileABI = false,
1066 bool NullTerminate = true);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001067
John McCall3fd13f062015-10-21 18:06:47 +00001068protected:
John McCall9e8bb002011-05-14 03:10:52 +00001069 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1070 ReturnValueSlot Return,
1071 QualType ResultType,
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08001072 Selector Sel,
John McCall9e8bb002011-05-14 03:10:52 +00001073 llvm::Value *Arg0,
1074 QualType Arg0Ty,
1075 bool IsSuper,
1076 const CallArgList &CallArgs,
1077 const ObjCMethodDecl *OMD,
John McCall1e3157b2015-09-10 22:27:50 +00001078 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00001079 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +00001080
Daniel Dunbar5e639272010-04-25 20:39:01 +00001081 /// EmitImageInfo - Emit the image info marker used to encode some module
1082 /// level information.
1083 void EmitImageInfo();
1084
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001085public:
Owen Andersonae86c192009-07-13 04:10:07 +00001086 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
John McCalla729c622012-02-17 03:33:10 +00001087 CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001088
John McCall3fd13f062015-10-21 18:06:47 +00001089 bool isNonFragileABI() const {
1090 return ObjCABI == 2;
1091 }
1092
John McCall7f416cc2015-09-08 08:05:57 +00001093 ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
John McCallcd21d542016-11-30 23:15:55 +00001094 ConstantAddress GenerateConstantNSString(const StringLiteral *SL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001095
Craig Topper4f12f102014-03-12 06:41:41 +00001096 llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
Craig Topper8a13c412014-05-21 05:09:00 +00001097 const ObjCContainerDecl *CD=nullptr) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001098
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08001099 llvm::Function *GenerateDirectMethod(const ObjCMethodDecl *OMD,
1100 const ObjCContainerDecl *CD);
1101
1102 void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
1103 const ObjCMethodDecl *OMD,
1104 const ObjCContainerDecl *CD) override;
1105
Craig Topper4f12f102014-03-12 06:41:41 +00001106 void GenerateProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001107
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001108 /// GetOrEmitProtocol - Get the protocol object for the given
1109 /// declaration, emitting it if necessary. The return value has type
1110 /// ProtocolPtrTy.
1111 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001112
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001113 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1114 /// object for the given declaration, emitting it if needed. These
1115 /// forward references will be filled in with empty bodies if no
1116 /// definition is seen. The return value has type ProtocolPtrTy.
1117 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCallcd21d542016-11-30 23:15:55 +00001118
1119 virtual llvm::Constant *getNSConstantStringClassRef() = 0;
1120
Craig Topper4f12f102014-03-12 06:41:41 +00001121 llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1122 const CGBlockInfo &blockInfo) override;
1123 llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1124 const CGBlockInfo &blockInfo) override;
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00001125 std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM,
1126 const CGBlockInfo &blockInfo) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001127
1128 llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1129 QualType T) override;
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00001130
1131private:
1132 void fillRunSkipBlockVars(CodeGenModule &CGM, const CGBlockInfo &blockInfo);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001133};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001134
John McCall176f8922016-11-30 02:39:18 +00001135namespace {
1136
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001137enum class MethodListType {
1138 CategoryInstanceMethods,
1139 CategoryClassMethods,
1140 InstanceMethods,
1141 ClassMethods,
1142 ProtocolInstanceMethods,
1143 ProtocolClassMethods,
1144 OptionalProtocolInstanceMethods,
1145 OptionalProtocolClassMethods,
1146};
1147
John McCall176f8922016-11-30 02:39:18 +00001148/// A convenience class for splitting the methods of a protocol into
1149/// the four interesting groups.
1150class ProtocolMethodLists {
1151public:
1152 enum Kind {
1153 RequiredInstanceMethods,
1154 RequiredClassMethods,
1155 OptionalInstanceMethods,
1156 OptionalClassMethods
1157 };
1158 enum {
1159 NumProtocolMethodLists = 4
1160 };
1161
1162 static MethodListType getMethodListKind(Kind kind) {
1163 switch (kind) {
1164 case RequiredInstanceMethods:
1165 return MethodListType::ProtocolInstanceMethods;
1166 case RequiredClassMethods:
1167 return MethodListType::ProtocolClassMethods;
1168 case OptionalInstanceMethods:
1169 return MethodListType::OptionalProtocolInstanceMethods;
1170 case OptionalClassMethods:
1171 return MethodListType::OptionalProtocolClassMethods;
1172 }
1173 llvm_unreachable("bad kind");
1174 }
1175
1176 SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];
1177
1178 static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
1179 ProtocolMethodLists result;
1180
1181 for (auto MD : PD->methods()) {
1182 size_t index = (2 * size_t(MD->isOptional()))
1183 + (size_t(MD->isClassMethod()));
1184 result.Methods[index].push_back(MD);
1185 }
1186
1187 return result;
1188 }
1189
1190 template <class Self>
1191 SmallVector<llvm::Constant*, 8> emitExtendedTypesArray(Self *self) const {
1192 // In both ABIs, the method types list is parallel with the
1193 // concatenation of the methods arrays in the following order:
1194 // instance methods
1195 // class methods
1196 // optional instance methods
1197 // optional class methods
1198 SmallVector<llvm::Constant*, 8> result;
1199
1200 // Methods is already in the correct order for both ABIs.
1201 for (auto &list : Methods) {
1202 for (auto MD : list) {
1203 result.push_back(self->GetMethodVarType(MD, true));
1204 }
1205 }
1206
1207 return result;
1208 }
1209
1210 template <class Self>
1211 llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD,
1212 Kind kind) const {
1213 return self->emitMethodList(PD->getObjCRuntimeNameAsString(),
1214 getMethodListKind(kind), Methods[kind]);
1215 }
1216};
1217
1218} // end anonymous namespace
1219
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001220class CGObjCMac : public CGObjCCommonMac {
1221private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001222 friend ProtocolMethodLists;
John McCall176f8922016-11-30 02:39:18 +00001223
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001224 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001225
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001226 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001227 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001228 void EmitModuleInfo();
1229
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001230 /// EmitModuleSymols - Emit module symbols, the list of defined
1231 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001232 llvm::Constant *EmitModuleSymbols();
1233
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001234 /// FinishModule - Write out global data structures at the end of
1235 /// processing a translation unit.
1236 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +00001237
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001238 /// EmitClassExtension - Generate the class extension structure used
1239 /// to store the weak ivar layout and properties. The return value
1240 /// has type ClassExtensionPtrTy.
John McCall3fd13f062015-10-21 18:06:47 +00001241 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
John McCall460ce582015-10-22 18:38:17 +00001242 CharUnits instanceSize,
Manman Renad0e7912016-01-29 19:22:54 +00001243 bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00001244 bool isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001245
1246 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1247 /// for the given class.
John McCall882987f2013-02-28 19:01:20 +00001248 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001249 const ObjCInterfaceDecl *ID);
Fangrui Song6907ce22018-07-30 19:24:48 +00001250
John McCall882987f2013-02-28 19:01:20 +00001251 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00001252 IdentifierInfo *II);
Craig Topper4f12f102014-03-12 06:41:41 +00001253
1254 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
1255
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001256 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1257 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001258
1259 /// EmitIvarList - Emit the ivar list for the given
1260 /// implementation. If ForClass is true the list of class ivars
1261 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1262 /// interface ivars will be emitted. The return value has type
1263 /// IvarListPtrTy.
1264 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00001265 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001266
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001267 /// EmitMetaClass - Emit a forward reference to the class structure
1268 /// for the metaclass of the given interface. The return value has
1269 /// type ClassPtrTy.
1270 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1271
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001272 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001273 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001274 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1275 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00001276 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001277
John McCall176f8922016-11-30 02:39:18 +00001278 void emitMethodConstant(ConstantArrayBuilder &builder,
1279 const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001280
John McCall176f8922016-11-30 02:39:18 +00001281 void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
1282 const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001283
1284 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +00001285 /// implementation. The return value has type MethodListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001286 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
John McCall176f8922016-11-30 02:39:18 +00001287 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001288
Daniel Dunbarc475d422008-10-29 22:36:39 +00001289 /// GetOrEmitProtocol - Get the protocol object for the given
1290 /// declaration, emitting it if necessary. The return value has type
1291 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001292 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001293
1294 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1295 /// object for the given declaration, emitting it if needed. These
1296 /// forward references will be filled in with empty bodies if no
1297 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001298 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001299
Daniel Dunbarb036db82008-08-13 03:21:16 +00001300 /// EmitProtocolExtension - Generate the protocol extension
1301 /// structure used to store optional instance and class methods, and
1302 /// protocol properties. The return value has type
1303 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001304 llvm::Constant *
1305 EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00001306 const ProtocolMethodLists &methodLists);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001307
1308 /// EmitProtocolList - Generate the list of referenced
1309 /// protocols. The return value has type ProtocolListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001310 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001311 ObjCProtocolDecl::protocol_iterator begin,
1312 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001313
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001314 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1315 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001316 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1317 Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001318
1319public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001320 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001321
John McCallcd21d542016-11-30 23:15:55 +00001322 llvm::Constant *getNSConstantStringClassRef() override;
1323
Craig Topper4f12f102014-03-12 06:41:41 +00001324 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001325
Craig Topper4f12f102014-03-12 06:41:41 +00001326 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1327 ReturnValueSlot Return,
1328 QualType ResultType,
1329 Selector Sel, llvm::Value *Receiver,
1330 const CallArgList &CallArgs,
1331 const ObjCInterfaceDecl *Class,
1332 const ObjCMethodDecl *Method) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001333
Craig Topper4f12f102014-03-12 06:41:41 +00001334 CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001335 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001336 ReturnValueSlot Return, QualType ResultType,
1337 Selector Sel, const ObjCInterfaceDecl *Class,
1338 bool isCategoryImpl, llvm::Value *Receiver,
1339 bool IsClassMessage, const CallArgList &CallArgs,
1340 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001341
Craig Topper4f12f102014-03-12 06:41:41 +00001342 llvm::Value *GetClass(CodeGenFunction &CGF,
1343 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001344
John McCall7f416cc2015-09-08 08:05:57 +00001345 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
1346 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001347
1348 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1349 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001350 llvm::Value *GetSelector(CodeGenFunction &CGF,
1351 const ObjCMethodDecl *Method) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001352
Craig Topper4f12f102014-03-12 06:41:41 +00001353 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001354
Craig Topper4f12f102014-03-12 06:41:41 +00001355 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001356
Craig Topper4f12f102014-03-12 06:41:41 +00001357 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001358
Craig Topper4f12f102014-03-12 06:41:41 +00001359 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001360
Craig Topper4f12f102014-03-12 06:41:41 +00001361 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1362 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001363
James Y Knight9871db02019-02-05 16:42:33 +00001364 llvm::FunctionCallee GetPropertyGetFunction() override;
1365 llvm::FunctionCallee GetPropertySetFunction() override;
1366 llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
1367 bool copy) override;
1368 llvm::FunctionCallee GetGetStructFunction() override;
1369 llvm::FunctionCallee GetSetStructFunction() override;
1370 llvm::FunctionCallee GetCppAtomicObjectGetFunction() override;
1371 llvm::FunctionCallee GetCppAtomicObjectSetFunction() override;
1372 llvm::FunctionCallee EnumerationMutationFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001373
Craig Topper4f12f102014-03-12 06:41:41 +00001374 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1375 const ObjCAtTryStmt &S) override;
1376 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1377 const ObjCAtSynchronizedStmt &S) override;
John McCallbd309292010-07-06 01:34:17 +00001378 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Craig Topper4f12f102014-03-12 06:41:41 +00001379 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1380 bool ClearInsertionPoint=true) override;
1381 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001382 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001383 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001384 llvm::Value *src, Address dst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001385 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001386 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001387 bool threadlocal = false) override;
1388 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001389 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001390 llvm::Value *ivarOffset) override;
1391 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001392 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001393 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001394 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001395 llvm::Value *size) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001396
Craig Topper4f12f102014-03-12 06:41:41 +00001397 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1398 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1399 unsigned CVRQualifiers) override;
1400 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1401 const ObjCInterfaceDecl *Interface,
1402 const ObjCIvarDecl *Ivar) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001403};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001404
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001405class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001406private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001407 friend ProtocolMethodLists;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001408 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001409 llvm::GlobalVariable* ObjCEmptyCacheVar;
John McCall176f8922016-11-30 02:39:18 +00001410 llvm::Constant* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001411
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001412 /// SuperClassReferences - uniqued super class references.
1413 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001414
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001415 /// MetaClassReferences - uniqued meta class references.
1416 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001417
1418 /// EHTypeReferences - uniqued class ehtype references.
1419 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001420
John McCall9e8bb002011-05-14 03:10:52 +00001421 /// VTableDispatchMethods - List of methods for which we generate
1422 /// vtable-based message dispatch.
1423 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001424
Fariborz Jahanian67260552009-11-17 21:37:35 +00001425 /// DefinedMetaClasses - List of defined meta-classes.
1426 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
Fangrui Song6907ce22018-07-30 19:24:48 +00001427
John McCall9e8bb002011-05-14 03:10:52 +00001428 /// isVTableDispatchedSelector - Returns true if SEL is a
1429 /// vtable-based selector.
1430 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001431
Fariborz Jahanian71394042009-01-23 23:53:38 +00001432 /// FinishNonFragileABIModule - Write out global data structures at the end of
1433 /// processing a translation unit.
1434 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001435
Daniel Dunbar19573e72009-05-15 21:48:48 +00001436 /// AddModuleClassList - Add the given list of class pointers to the
1437 /// module with the provided symbol and section names.
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001438 void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container,
1439 StringRef SymbolName, StringRef SectionName);
Daniel Dunbar19573e72009-05-15 21:48:48 +00001440
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001441 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1442 unsigned InstanceStart,
1443 unsigned InstanceSize,
1444 const ObjCImplementationDecl *ID);
John McCalldba63a72016-11-30 23:54:50 +00001445 llvm::GlobalVariable *BuildClassObject(const ObjCInterfaceDecl *CI,
1446 bool isMetaclass,
1447 llvm::Constant *IsAGV,
1448 llvm::Constant *SuperClassGV,
1449 llvm::Constant *ClassRoGV,
1450 bool HiddenVisibility);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001451
John McCall176f8922016-11-30 02:39:18 +00001452 void emitMethodConstant(ConstantArrayBuilder &builder,
1453 const ObjCMethodDecl *MD,
1454 bool forProtocol);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001455
John McCall176f8922016-11-30 02:39:18 +00001456 /// Emit the method list for the given implementation. The return value
1457 /// has type MethodListnfABITy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001458 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
John McCall176f8922016-11-30 02:39:18 +00001459 ArrayRef<const ObjCMethodDecl *> Methods);
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001460
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001461 /// EmitIvarList - Emit the ivar list for the given
1462 /// implementation. If ForClass is true the list of class ivars
1463 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1464 /// interface ivars will be emitted. The return value has type
1465 /// IvarListnfABIPtrTy.
1466 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001467
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001468 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001469 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00001470 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001471
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001472 /// GetOrEmitProtocol - Get the protocol object for the given
1473 /// declaration, emitting it if necessary. The return value has type
1474 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001475 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001476
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001477 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1478 /// object for the given declaration, emitting it if needed. These
1479 /// forward references will be filled in with empty bodies if no
1480 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001481 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001482
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001483 /// EmitProtocolList - Generate the list of referenced
1484 /// protocols. The return value has type ProtocolListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001485 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001486 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001487 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001488
John McCall9e8bb002011-05-14 03:10:52 +00001489 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1490 ReturnValueSlot Return,
1491 QualType ResultType,
1492 Selector Sel,
1493 llvm::Value *Receiver,
1494 QualType Arg0Ty,
1495 bool IsSuper,
1496 const CallArgList &CallArgs,
1497 const ObjCMethodDecl *Method);
Fangrui Song6907ce22018-07-30 19:24:48 +00001498
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001499 /// GetClassGlobal - Return the global variable for the Objective-C
1500 /// class of the given name.
John McCalldba63a72016-11-30 23:54:50 +00001501 llvm::Constant *GetClassGlobal(StringRef Name,
1502 ForDefinition_t IsForDefinition,
1503 bool Weak = false, bool DLLImport = false);
1504 llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID,
1505 bool isMetaclass,
1506 ForDefinition_t isForDefinition);
Rafael Espindola554256c2014-02-26 22:25:45 +00001507
John McCall2c91c3b2019-05-30 04:09:01 +00001508 llvm::Constant *GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID);
1509
1510 llvm::Value *EmitLoadOfClassRef(CodeGenFunction &CGF,
1511 const ObjCInterfaceDecl *ID,
1512 llvm::GlobalVariable *Entry);
1513
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001514 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001515 /// for the given class reference.
John McCall882987f2013-02-28 19:01:20 +00001516 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001517 const ObjCInterfaceDecl *ID);
Fangrui Song6907ce22018-07-30 19:24:48 +00001518
John McCall882987f2013-02-28 19:01:20 +00001519 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
John McCalldba63a72016-11-30 23:54:50 +00001520 IdentifierInfo *II,
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00001521 const ObjCInterfaceDecl *ID);
Craig Topper4f12f102014-03-12 06:41:41 +00001522
1523 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001524
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001525 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1526 /// for the given super class reference.
John McCall882987f2013-02-28 19:01:20 +00001527 llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001528 const ObjCInterfaceDecl *ID);
1529
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001530 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1531 /// meta-data
John McCall882987f2013-02-28 19:01:20 +00001532 llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00001533 const ObjCInterfaceDecl *ID, bool Weak);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001534
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001535 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1536 /// the given ivar.
1537 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001538 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001539 const ObjCInterfaceDecl *ID,
1540 const ObjCIvarDecl *Ivar);
1541
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001542 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1543 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001544 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1545 Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001546
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001547 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001548 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001549 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
John McCalldba63a72016-11-30 23:54:50 +00001550 ForDefinition_t IsForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001551
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001552 StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001553
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001554 StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; }
Daniel Dunbar15894b72009-04-07 05:48:37 +00001555
Daniel Dunbar961202372009-05-03 12:57:56 +00001556 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001557 uint32_t &InstanceStart,
1558 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001559
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001560 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001561 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001562 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1563 return CGM.getContext().Selectors.getSelector(0, &II);
1564 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001565
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001566 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001567 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1568 return CGM.getContext().Selectors.getSelector(1, &II);
1569 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001570
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001571 /// ImplementationIsNonLazy - Check whether the given category or
1572 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001573 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001574
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001575 bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001576 const ObjCIvarDecl *IV) {
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001577 // Annotate the load as an invariant load iff inside an instance method
1578 // and ivar belongs to instance method's class and one of its super class.
1579 // This check is needed because the ivar offset is a lazily
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001580 // initialised value that may depend on objc_msgSend to perform a fixup on
1581 // the first message dispatch.
1582 //
1583 // An additional opportunity to mark the load as invariant arises when the
1584 // base of the ivar access is a parameter to an Objective C method.
1585 // However, because the parameters are not available in the current
1586 // interface, we cannot perform this check.
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08001587 //
1588 // Note that for direct methods, because objc_msgSend is skipped,
1589 // and that the method may be inlined, this optimization actually
1590 // can't be performed.
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001591 if (const ObjCMethodDecl *MD =
1592 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08001593 if (MD->isInstanceMethod() && !MD->isDirectMethod())
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001594 if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
1595 return IV->getContainingInterface()->isSuperClassOf(ID);
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001596 return false;
1597 }
1598
Erik Pilkington2ff012d2019-01-17 18:18:53 +00001599 bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) {
1600 // NSObject is a fixed size. If we can see the @implementation of a class
1601 // which inherits from NSObject then we know that all it's offsets also must
1602 // be fixed. FIXME: Can we do this if see a chain of super classes with
1603 // implementations leading to NSObject?
1604 return ID->getImplementation() && ID->getSuperClass() &&
1605 ID->getSuperClass()->getName() == "NSObject";
1606 }
1607
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001608public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001609 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
John McCallcd21d542016-11-30 23:15:55 +00001610
1611 llvm::Constant *getNSConstantStringClassRef() override;
1612
Craig Topper4f12f102014-03-12 06:41:41 +00001613 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001614
Craig Topper4f12f102014-03-12 06:41:41 +00001615 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1616 ReturnValueSlot Return,
1617 QualType ResultType, Selector Sel,
1618 llvm::Value *Receiver,
1619 const CallArgList &CallArgs,
1620 const ObjCInterfaceDecl *Class,
1621 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001622
Craig Topper4f12f102014-03-12 06:41:41 +00001623 CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001624 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001625 ReturnValueSlot Return, QualType ResultType,
1626 Selector Sel, const ObjCInterfaceDecl *Class,
1627 bool isCategoryImpl, llvm::Value *Receiver,
1628 bool IsClassMessage, const CallArgList &CallArgs,
1629 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001630
Craig Topper4f12f102014-03-12 06:41:41 +00001631 llvm::Value *GetClass(CodeGenFunction &CGF,
1632 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001633
John McCall7f416cc2015-09-08 08:05:57 +00001634 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override
1635 { return EmitSelector(CGF, Sel); }
1636 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override
1637 { return EmitSelectorAddr(CGF, Sel); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001638
1639 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1640 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001641 llvm::Value *GetSelector(CodeGenFunction &CGF,
1642 const ObjCMethodDecl *Method) override
John McCall882987f2013-02-28 19:01:20 +00001643 { return EmitSelector(CGF, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001644
Craig Topper4f12f102014-03-12 06:41:41 +00001645 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001646
Craig Topper4f12f102014-03-12 06:41:41 +00001647 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
David Chisnall92d436b2012-01-31 18:59:20 +00001648
Craig Topper4f12f102014-03-12 06:41:41 +00001649 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001650
Craig Topper4f12f102014-03-12 06:41:41 +00001651 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1652 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001653
Craig Topper4f12f102014-03-12 06:41:41 +00001654 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001655
James Y Knight9871db02019-02-05 16:42:33 +00001656 llvm::FunctionCallee GetPropertyGetFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001657 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001658 }
James Y Knight9871db02019-02-05 16:42:33 +00001659 llvm::FunctionCallee GetPropertySetFunction() override {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001660 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001661 }
Craig Topper4f12f102014-03-12 06:41:41 +00001662
James Y Knight9871db02019-02-05 16:42:33 +00001663 llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
1664 bool copy) override {
Ted Kremeneke65b0862012-03-06 20:05:56 +00001665 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1666 }
Craig Topper4f12f102014-03-12 06:41:41 +00001667
James Y Knight9871db02019-02-05 16:42:33 +00001668 llvm::FunctionCallee GetSetStructFunction() override {
David Chisnall168b80f2010-12-26 22:13:16 +00001669 return ObjCTypes.getCopyStructFn();
1670 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001671
James Y Knight9871db02019-02-05 16:42:33 +00001672 llvm::FunctionCallee GetGetStructFunction() override {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001673 return ObjCTypes.getCopyStructFn();
1674 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001675
James Y Knight9871db02019-02-05 16:42:33 +00001676 llvm::FunctionCallee GetCppAtomicObjectSetFunction() override {
David Chisnall0d75e062012-12-17 18:54:24 +00001677 return ObjCTypes.getCppAtomicObjectFunction();
1678 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001679
James Y Knight9871db02019-02-05 16:42:33 +00001680 llvm::FunctionCallee GetCppAtomicObjectGetFunction() override {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001681 return ObjCTypes.getCppAtomicObjectFunction();
1682 }
Craig Topper4f12f102014-03-12 06:41:41 +00001683
James Y Knight9871db02019-02-05 16:42:33 +00001684 llvm::FunctionCallee EnumerationMutationFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001685 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001686 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001687
Craig Topper4f12f102014-03-12 06:41:41 +00001688 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1689 const ObjCAtTryStmt &S) override;
1690 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1691 const ObjCAtSynchronizedStmt &S) override;
1692 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1693 bool ClearInsertionPoint=true) override;
1694 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001695 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001696 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001697 llvm::Value *src, Address edst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001698 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001699 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001700 bool threadlocal = false) override;
1701 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001702 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001703 llvm::Value *ivarOffset) override;
1704 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001705 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001706 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001707 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001708 llvm::Value *size) override;
1709 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1710 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1711 unsigned CVRQualifiers) override;
1712 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1713 const ObjCInterfaceDecl *Interface,
1714 const ObjCIvarDecl *Ivar) override;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001715};
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001716
1717/// A helper class for performing the null-initialization of a return
1718/// value.
1719struct NullReturnState {
1720 llvm::BasicBlock *NullBB;
Craig Topper8a13c412014-05-21 05:09:00 +00001721 NullReturnState() : NullBB(nullptr) {}
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001722
John McCall3d1e2c92013-02-12 05:53:35 +00001723 /// Perform a null-check of the given receiver.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001724 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
John McCall3d1e2c92013-02-12 05:53:35 +00001725 // Make blocks for the null-receiver and call edges.
1726 NullBB = CGF.createBasicBlock("msgSend.null-receiver");
1727 llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001728
1729 // Check for a null receiver and, if there is one, jump to the
John McCall3d1e2c92013-02-12 05:53:35 +00001730 // null-receiver block. There's no point in trying to avoid it:
1731 // we're always going to put *something* there, because otherwise
1732 // we shouldn't have done this null-check in the first place.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001733 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1734 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1735
1736 // Otherwise, start performing the call.
1737 CGF.EmitBlock(callBB);
1738 }
1739
John McCall3d1e2c92013-02-12 05:53:35 +00001740 /// Complete the null-return operation. It is valid to call this
1741 /// regardless of whether 'init' has been called.
Kuba Mracekbce5cea2017-06-30 16:28:15 +00001742 RValue complete(CodeGenFunction &CGF,
1743 ReturnValueSlot returnSlot,
1744 RValue result,
1745 QualType resultType,
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001746 const CallArgList &CallArgs,
1747 const ObjCMethodDecl *Method) {
John McCall3d1e2c92013-02-12 05:53:35 +00001748 // If we never had to do a null-check, just use the raw result.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001749 if (!NullBB) return result;
John McCall3d1e2c92013-02-12 05:53:35 +00001750
1751 // The continuation block. This will be left null if we don't have an
1752 // IP, which can happen if the method we're calling is marked noreturn.
Craig Topper8a13c412014-05-21 05:09:00 +00001753 llvm::BasicBlock *contBB = nullptr;
1754
John McCall3d1e2c92013-02-12 05:53:35 +00001755 // Finish the call path.
1756 llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
1757 if (callBB) {
1758 contBB = CGF.createBasicBlock("msgSend.cont");
1759 CGF.Builder.CreateBr(contBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001760 }
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001761
John McCall3d1e2c92013-02-12 05:53:35 +00001762 // Okay, start emitting the null-receiver block.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001763 CGF.EmitBlock(NullBB);
Fangrui Song6907ce22018-07-30 19:24:48 +00001764
John McCall3d1e2c92013-02-12 05:53:35 +00001765 // Release any consumed arguments we've got.
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001766 if (Method) {
1767 CallArgList::const_iterator I = CallArgs.begin();
1768 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1769 e = Method->param_end(); i != e; ++i, ++I) {
1770 const ParmVarDecl *ParamDecl = (*i);
1771 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
Yaxun Liu5b330e82018-03-15 15:25:19 +00001772 RValue RV = I->getRValue(CGF);
Fangrui Song6907ce22018-07-30 19:24:48 +00001773 assert(RV.isScalar() &&
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001774 "NullReturnState::complete - arg not on object");
John McCallcdda29c2013-03-13 03:10:54 +00001775 CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001776 }
1777 }
1778 }
John McCall3d1e2c92013-02-12 05:53:35 +00001779
1780 // The phi code below assumes that we haven't needed any control flow yet.
1781 assert(CGF.Builder.GetInsertBlock() == NullBB);
1782
1783 // If we've got a void return, just jump to the continuation block.
1784 if (result.isScalar() && resultType->isVoidType()) {
1785 // No jumps required if the message-send was noreturn.
1786 if (contBB) CGF.EmitBlock(contBB);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001787 return result;
1788 }
1789
John McCall3d1e2c92013-02-12 05:53:35 +00001790 // If we've got a scalar return, build a phi.
1791 if (result.isScalar()) {
1792 // Derive the null-initialization value.
1793 llvm::Constant *null = CGF.CGM.EmitNullConstant(resultType);
1794
1795 // If no join is necessary, just flow out.
1796 if (!contBB) return RValue::get(null);
1797
1798 // Otherwise, build a phi.
1799 CGF.EmitBlock(contBB);
1800 llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2);
1801 phi->addIncoming(result.getScalarVal(), callBB);
1802 phi->addIncoming(null, NullBB);
1803 return RValue::get(phi);
1804 }
1805
1806 // If we've got an aggregate return, null the buffer out.
1807 // FIXME: maybe we should be doing things differently for all the
1808 // cases where the ABI has us returning (1) non-agg values in
1809 // memory or (2) agg values in registers.
1810 if (result.isAggregate()) {
1811 assert(result.isAggregate() && "null init of non-aggregate result?");
Kuba Mracekbce5cea2017-06-30 16:28:15 +00001812 if (!returnSlot.isUnused())
1813 CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
John McCall3d1e2c92013-02-12 05:53:35 +00001814 if (contBB) CGF.EmitBlock(contBB);
1815 return result;
1816 }
1817
1818 // Complex types.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001819 CGF.EmitBlock(contBB);
John McCall3d1e2c92013-02-12 05:53:35 +00001820 CodeGenFunction::ComplexPairTy callResult = result.getComplexVal();
1821
1822 // Find the scalar type and its zero value.
1823 llvm::Type *scalarTy = callResult.first->getType();
1824 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1825
1826 // Build phis for both coordinates.
1827 llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2);
1828 real->addIncoming(callResult.first, callBB);
1829 real->addIncoming(scalarZero, NullBB);
1830 llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2);
1831 imag->addIncoming(callResult.second, callBB);
1832 imag->addIncoming(scalarZero, NullBB);
1833 return RValue::getComplex(real, imag);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001834 }
1835};
1836
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001837} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001838
1839/* *** Helper Functions *** */
1840
1841/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001842static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
David Blaikiee3b172a2015-04-02 18:55:21 +00001843 llvm::GlobalVariable *C, unsigned idx0,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001844 unsigned idx1) {
1845 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001846 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1847 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001848 };
David Blaikiee3b172a2015-04-02 18:55:21 +00001849 return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001850}
1851
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001852/// hasObjCExceptionAttribute - Return true if this class or any super
1853/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001854static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001855 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001856 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001857 return true;
1858 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001859 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001860 return false;
1861}
1862
Akira Hatanaka187770d2019-05-09 17:43:52 +00001863static llvm::GlobalValue::LinkageTypes
1864getLinkageTypeForObjCMetadata(CodeGenModule &CGM, StringRef Section) {
1865 if (CGM.getTriple().isOSBinFormatMachO() &&
1866 (Section.empty() || Section.startswith("__DATA")))
1867 return llvm::GlobalValue::InternalLinkage;
1868 return llvm::GlobalValue::PrivateLinkage;
1869}
1870
1871/// A helper function to create an internal or private global variable.
1872static llvm::GlobalVariable *
1873finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder,
1874 const llvm::Twine &Name, CodeGenModule &CGM) {
1875 std::string SectionName;
1876 if (CGM.getTriple().isOSBinFormatMachO())
1877 SectionName = "__DATA, __objc_const";
1878 auto *GV = Builder.finishAndCreateGlobal(
1879 Name, CGM.getPointerAlign(), /*constant*/ false,
1880 getLinkageTypeForObjCMetadata(CGM, SectionName));
1881 GV->setSection(SectionName);
1882 return GV;
1883}
1884
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001885/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001886
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001887CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001888 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001889 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001890 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001891}
1892
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001893/// GetClass - Return a reference to the class for the given interface
1894/// decl.
John McCall882987f2013-02-28 19:01:20 +00001895llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001896 const ObjCInterfaceDecl *ID) {
John McCall882987f2013-02-28 19:01:20 +00001897 return EmitClassRef(CGF, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001898}
1899
1900/// GetSelector - Return the pointer to the unique'd string for this selector.
John McCall7f416cc2015-09-08 08:05:57 +00001901llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
1902 return EmitSelector(CGF, Sel);
1903}
1904Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
1905 return EmitSelectorAddr(CGF, Sel);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001906}
John McCall882987f2013-02-28 19:01:20 +00001907llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001908 *Method) {
John McCall882987f2013-02-28 19:01:20 +00001909 return EmitSelector(CGF, Method->getSelector());
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001910}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001911
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001912llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001913 if (T->isObjCIdType() ||
1914 T->isObjCQualifiedIdType()) {
1915 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001916 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001917 }
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001918 if (T->isObjCClassType() ||
1919 T->isObjCQualifiedClassType()) {
1920 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001921 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001922 }
1923 if (T->isObjCObjectPointerType())
1924 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
Fangrui Song6907ce22018-07-30 19:24:48 +00001925
John McCall2ca705e2010-07-24 00:37:23 +00001926 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall2ca705e2010-07-24 00:37:23 +00001927}
1928
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001929/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001930/*
1931 struct __builtin_CFString {
1932 const int *isa; // point to __CFConstantStringClassReference
1933 int flags;
1934 const char *str;
1935 long length;
1936 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001937*/
1938
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001939/// or Generate a constant NSString object.
1940/*
1941 struct __builtin_NSString {
1942 const int *isa; // point to __NSConstantStringClassReference
1943 const char *str;
1944 unsigned int length;
1945 };
1946*/
1947
John McCallcd21d542016-11-30 23:15:55 +00001948ConstantAddress
1949CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) {
1950 return (!CGM.getLangOpts().NoConstantCFStrings
1951 ? CGM.GetAddrOfConstantCFString(SL)
1952 : GenerateConstantNSString(SL));
1953}
1954
1955static llvm::StringMapEntry<llvm::GlobalVariable *> &
1956GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
1957 const StringLiteral *Literal, unsigned &StringLength) {
1958 StringRef String = Literal->getString();
1959 StringLength = String.size();
1960 return *Map.insert(std::make_pair(String, nullptr)).first;
1961}
1962
1963llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1964 if (llvm::Value *V = ConstantStringClassRef)
1965 return cast<llvm::Constant>(V);
1966
1967 auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
1968 std::string str =
1969 StringClass.empty() ? "_NSConstantStringClassReference"
1970 : "_" + StringClass + "ClassReference";
1971
1972 llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0);
1973 auto GV = CGM.CreateRuntimeVariable(PTy, str);
1974 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1975 ConstantStringClassRef = V;
1976 return V;
1977}
1978
1979llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1980 if (llvm::Value *V = ConstantStringClassRef)
1981 return cast<llvm::Constant>(V);
1982
1983 auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
Fangrui Song6907ce22018-07-30 19:24:48 +00001984 std::string str =
1985 StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
John McCallcd21d542016-11-30 23:15:55 +00001986 : "OBJC_CLASS_$_" + StringClass;
John McCall2c91c3b2019-05-30 04:09:01 +00001987 llvm::Constant *GV = GetClassGlobal(str, NotForDefinition);
John McCallcd21d542016-11-30 23:15:55 +00001988
1989 // Make sure the result is of the correct type.
1990 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1991
1992 ConstantStringClassRef = V;
1993 return V;
1994}
1995
1996ConstantAddress
1997CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) {
1998 unsigned StringLength = 0;
1999 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
2000 GetConstantStringEntry(NSConstantStringMap, Literal, StringLength);
2001
2002 if (auto *C = Entry.second)
2003 return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
2004
2005 // If we don't already have it, get _NSConstantStringClassReference.
2006 llvm::Constant *Class = getNSConstantStringClassRef();
2007
2008 // If we don't already have it, construct the type for a constant NSString.
2009 if (!NSConstantStringType) {
2010 NSConstantStringType =
2011 llvm::StructType::create({
2012 CGM.Int32Ty->getPointerTo(),
2013 CGM.Int8PtrTy,
2014 CGM.IntTy
2015 }, "struct.__builtin_NSString");
2016 }
2017
2018 ConstantInitBuilder Builder(CGM);
2019 auto Fields = Builder.beginStruct(NSConstantStringType);
2020
2021 // Class pointer.
2022 Fields.add(Class);
2023
2024 // String pointer.
2025 llvm::Constant *C =
2026 llvm::ConstantDataArray::getString(VMContext, Entry.first());
2027
2028 llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
2029 bool isConstant = !CGM.getLangOpts().WritableStrings;
2030
2031 auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant,
2032 Linkage, C, ".str");
2033 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2034 // Don't enforce the target's minimum global alignment, since the only use
2035 // of the string is via this class initializer.
Guillaume Chateletc79099e2019-10-03 13:00:29 +00002036 GV->setAlignment(llvm::Align::None());
John McCallcd21d542016-11-30 23:15:55 +00002037 Fields.addBitCast(GV, CGM.Int8PtrTy);
2038
2039 // String length.
2040 Fields.addInt(CGM.IntTy, StringLength);
2041
2042 // The struct.
2043 CharUnits Alignment = CGM.getPointerAlign();
2044 GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
2045 /*constant*/ true,
2046 llvm::GlobalVariable::PrivateLinkage);
2047 const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
2048 const char *NSStringNonFragileABISection =
2049 "__DATA,__objc_stringobj,regular,no_dead_strip";
2050 // FIXME. Fix section.
2051 GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile()
2052 ? NSStringNonFragileABISection
2053 : NSStringSection);
2054 Entry.second = GV;
2055
2056 return ConstantAddress(GV, Alignment);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002057}
2058
Ted Kremeneke65b0862012-03-06 20:05:56 +00002059enum {
2060 kCFTaggedObjectID_Integer = (1 << 1) + 1
2061};
2062
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002063/// Generates a message send where the super is the receiver. This is
2064/// a message send to self with special delivery semantics indicating
2065/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00002066CodeGen::RValue
2067CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00002068 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00002069 QualType ResultType,
2070 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002071 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002072 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002073 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00002074 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00002075 const CodeGen::CallArgList &CallArgs,
2076 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002077 // Create and init a super structure; this is a (receiver, class)
2078 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00002079 Address ObjCSuper =
2080 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
2081 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002082 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002083 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
James Y Knight751fe282019-02-09 22:22:28 +00002084 CGF.Builder.CreateStore(ReceiverAsObject,
2085 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002086
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002087 // If this is a class message the metaclass is passed as the target.
2088 llvm::Value *Target;
2089 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002090 if (isCategoryImpl) {
2091 // Message sent to 'super' in a class method defined in a category
2092 // implementation requires an odd treatment.
2093 // If we are in a class method, we must retrieve the
2094 // _metaclass_ for the current class, pointed at by
2095 // the class's "isa" pointer. The following assumes that
2096 // isa" is the first ivar in a class (which it must be).
John McCall882987f2013-02-28 19:01:20 +00002097 Target = EmitClassRef(CGF, Class->getSuperClass());
David Blaikie1ed728c2015-04-05 22:45:47 +00002098 Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
John McCall7f416cc2015-09-08 08:05:57 +00002099 Target = CGF.Builder.CreateAlignedLoad(Target, CGF.getPointerAlign());
Mike Stump658fe022009-07-30 22:28:39 +00002100 } else {
David Blaikie1ed728c2015-04-05 22:45:47 +00002101 llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
2102 llvm::Value *SuperPtr =
2103 CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00002104 llvm::Value *Super =
2105 CGF.Builder.CreateAlignedLoad(SuperPtr, CGF.getPointerAlign());
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002106 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002107 }
David Blaikie1ed728c2015-04-05 22:45:47 +00002108 } else if (isCategoryImpl)
John McCall882987f2013-02-28 19:01:20 +00002109 Target = EmitClassRef(CGF, Class->getSuperClass());
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00002110 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002111 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
David Blaikie1ed728c2015-04-05 22:45:47 +00002112 ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00002113 Target = CGF.Builder.CreateAlignedLoad(ClassPtr, CGF.getPointerAlign());
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002114 }
Mike Stump18bb9282009-05-16 07:57:57 +00002115 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
2116 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00002117 llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00002118 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00002119 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
James Y Knight751fe282019-02-09 22:22:28 +00002120 CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002121 return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.getPointer(),
2122 ObjCTypes.SuperPtrCTy, true, CallArgs, Method, Class,
2123 ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002124}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002125
2126/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00002127CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00002128 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00002129 QualType ResultType,
2130 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002131 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00002132 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00002133 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00002134 const ObjCMethodDecl *Method) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002135 return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2136 CGF.getContext().getObjCIdType(), false, CallArgs,
2137 Method, Class, ObjCTypes);
John McCall1e3157b2015-09-10 22:27:50 +00002138}
2139
2140static bool isWeakLinkedClass(const ObjCInterfaceDecl *ID) {
2141 do {
2142 if (ID->isWeakImported())
2143 return true;
2144 } while ((ID = ID->getSuperClass()));
2145
2146 return false;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00002147}
2148
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00002149CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00002150CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
2151 ReturnValueSlot Return,
2152 QualType ResultType,
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002153 Selector Sel,
John McCall9e8bb002011-05-14 03:10:52 +00002154 llvm::Value *Arg0,
2155 QualType Arg0Ty,
2156 bool IsSuper,
2157 const CallArgList &CallArgs,
2158 const ObjCMethodDecl *Method,
John McCall1e3157b2015-09-10 22:27:50 +00002159 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00002160 const ObjCCommonTypesHelper &ObjCTypes) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002161 CodeGenTypes &Types = CGM.getTypes();
2162 auto selTy = CGF.getContext().getObjCSelType();
2163 llvm::Value *SelValue;
2164
2165 if (Method && Method->isDirectMethod()) {
2166 // Direct methods will synthesize the proper `_cmd` internally,
2167 // so just don't bother with setting the `_cmd` argument.
2168 assert(!IsSuper);
2169 SelValue = llvm::UndefValue::get(Types.ConvertType(selTy));
2170 } else {
2171 SelValue = GetSelector(CGF, Sel);
2172 }
2173
Daniel Dunbarc722b852008-08-30 03:02:31 +00002174 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00002175 if (!IsSuper)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00002176 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman43dca6a2011-05-02 17:57:46 +00002177 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002178 ActualArgs.add(RValue::get(SelValue), selTy);
John McCall31168b02011-06-15 23:02:42 +00002179 ActualArgs.addFrom(CallArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002180
John McCalla729c622012-02-17 03:33:10 +00002181 // If we're calling a method, use the formal signature.
2182 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002183
Anders Carlsson280e61f12010-06-21 20:59:55 +00002184 if (Method)
Alp Toker314cc812014-01-25 16:55:45 +00002185 assert(CGM.getContext().getCanonicalType(Method->getReturnType()) ==
2186 CGM.getContext().getCanonicalType(ResultType) &&
Anders Carlsson280e61f12010-06-21 20:59:55 +00002187 "Result type mismatch!");
2188
John McCall1e3157b2015-09-10 22:27:50 +00002189 bool ReceiverCanBeNull = true;
2190
2191 // Super dispatch assumes that self is non-null; even the messenger
2192 // doesn't have a null check internally.
2193 if (IsSuper) {
2194 ReceiverCanBeNull = false;
2195
2196 // If this is a direct dispatch of a class method, check whether the class,
2197 // or anything in its hierarchy, was weak-linked.
2198 } else if (ClassReceiver && Method && Method->isClassMethod()) {
2199 ReceiverCanBeNull = isWeakLinkedClass(ClassReceiver);
2200
2201 // If we're emitting a method, and self is const (meaning just ARC, for now),
2202 // and the receiver is a load of self, then self is a valid object.
2203 } else if (auto CurMethod =
2204 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) {
2205 auto Self = CurMethod->getSelfDecl();
2206 if (Self->getType().isConstQualified()) {
2207 if (auto LI = dyn_cast<llvm::LoadInst>(Arg0->stripPointerCasts())) {
2208 llvm::Value *SelfAddr = CGF.GetAddrOfLocalVar(Self).getPointer();
2209 if (SelfAddr == LI->getPointerOperand()) {
2210 ReceiverCanBeNull = false;
2211 }
2212 }
2213 }
2214 }
2215
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002216 bool RequiresNullCheck = false;
John McCall5880fb82011-05-14 21:12:11 +00002217
James Y Knight9871db02019-02-05 16:42:33 +00002218 llvm::FunctionCallee Fn = nullptr;
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002219 if (Method && Method->isDirectMethod()) {
2220 Fn = GenerateDirectMethod(Method, Method->getClassInterface());
2221 } else if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002222 if (ReceiverCanBeNull) RequiresNullCheck = true;
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002223 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002224 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00002225 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
2226 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2227 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +00002228 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
2229 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2230 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002231 } else {
Tim Northovere77cc392014-03-29 13:28:05 +00002232 // arm64 uses objc_msgSend for stret methods and yet null receiver check
2233 // must be made for it.
Ahmed Bougachaa3df87b2015-10-02 22:41:59 +00002234 if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002235 RequiresNullCheck = true;
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002236 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002237 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002238 }
John McCall1e3157b2015-09-10 22:27:50 +00002239
James Y Knight9871db02019-02-05 16:42:33 +00002240 // Cast function to proper signature
2241 llvm::Constant *BitcastFn = cast<llvm::Constant>(
2242 CGF.Builder.CreateBitCast(Fn.getCallee(), MSI.MessengerType));
2243
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002244 // We don't need to emit a null check to zero out an indirect result if the
2245 // result is ignored.
2246 if (Return.isUnused())
2247 RequiresNullCheck = false;
2248
John McCall1e3157b2015-09-10 22:27:50 +00002249 // Emit a null-check if there's a consumed argument other than the receiver.
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002250 if (!RequiresNullCheck && CGM.getLangOpts().ObjCAutoRefCount && Method) {
David Majnemer59f77922016-06-24 04:05:48 +00002251 for (const auto *ParamDecl : Method->parameters()) {
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002252 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
John McCall1e3157b2015-09-10 22:27:50 +00002253 RequiresNullCheck = true;
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002254 break;
2255 }
2256 }
John McCall1e3157b2015-09-10 22:27:50 +00002257 }
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002258
2259 NullReturnState nullReturn;
2260 if (RequiresNullCheck) {
2261 nullReturn.init(CGF, Arg0);
2262 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002263
James Y Knight3933add2019-01-30 02:54:28 +00002264 llvm::CallBase *CallSite;
James Y Knight9871db02019-02-05 16:42:33 +00002265 CGCallee Callee = CGCallee::forDirect(BitcastFn);
John McCallb92ab1a2016-10-26 23:46:34 +00002266 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2267 &CallSite);
John McCall1e3157b2015-09-10 22:27:50 +00002268
2269 // Mark the call as noreturn if the method is marked noreturn and the
2270 // receiver cannot be null.
2271 if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
James Y Knight3933add2019-01-30 02:54:28 +00002272 CallSite->setDoesNotReturn();
John McCall1e3157b2015-09-10 22:27:50 +00002273 }
2274
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002275 return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
John McCall1e3157b2015-09-10 22:27:50 +00002276 RequiresNullCheck ? Method : nullptr);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002277}
2278
John McCall3fd13f062015-10-21 18:06:47 +00002279static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT,
2280 bool pointee = false) {
2281 // Note that GC qualification applies recursively to C pointer types
2282 // that aren't otherwise decorated. This is weird, but it's probably
2283 // an intentional workaround to the unreliable placement of GC qualifiers.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002284 if (FQT.isObjCGCStrong())
2285 return Qualifiers::Strong;
John McCall3fd13f062015-10-21 18:06:47 +00002286
2287 if (FQT.isObjCGCWeak())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002288 return Qualifiers::Weak;
John McCall3fd13f062015-10-21 18:06:47 +00002289
2290 if (auto ownership = FQT.getObjCLifetime()) {
2291 // Ownership does not apply recursively to C pointer types.
2292 if (pointee) return Qualifiers::GCNone;
2293 switch (ownership) {
2294 case Qualifiers::OCL_Weak: return Qualifiers::Weak;
2295 case Qualifiers::OCL_Strong: return Qualifiers::Strong;
2296 case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone;
2297 case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?");
2298 case Qualifiers::OCL_None: llvm_unreachable("known nonzero");
2299 }
2300 llvm_unreachable("bad objc ownership");
2301 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002302
John McCall3fd13f062015-10-21 18:06:47 +00002303 // Treat unqualified retainable pointers as strong.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002304 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
2305 return Qualifiers::Strong;
Fangrui Song6907ce22018-07-30 19:24:48 +00002306
John McCall3fd13f062015-10-21 18:06:47 +00002307 // Walk into C pointer types, but only in GC.
2308 if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) {
2309 if (const PointerType *PT = FQT->getAs<PointerType>())
2310 return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true);
2311 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002312
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002313 return Qualifiers::GCNone;
2314}
2315
John McCall3fd13f062015-10-21 18:06:47 +00002316namespace {
2317 struct IvarInfo {
2318 CharUnits Offset;
2319 uint64_t SizeInWords;
2320 IvarInfo(CharUnits offset, uint64_t sizeInWords)
2321 : Offset(offset), SizeInWords(sizeInWords) {}
2322
2323 // Allow sorting based on byte pos.
2324 bool operator<(const IvarInfo &other) const {
2325 return Offset < other.Offset;
2326 }
2327 };
2328
2329 /// A helper class for building GC layout strings.
2330 class IvarLayoutBuilder {
2331 CodeGenModule &CGM;
2332
2333 /// The start of the layout. Offsets will be relative to this value,
2334 /// and entries less than this value will be silently discarded.
2335 CharUnits InstanceBegin;
2336
2337 /// The end of the layout. Offsets will never exceed this value.
2338 CharUnits InstanceEnd;
2339
2340 /// Whether we're generating the strong layout or the weak layout.
2341 bool ForStrongLayout;
2342
2343 /// Whether the offsets in IvarsInfo might be out-of-order.
2344 bool IsDisordered = false;
2345
2346 llvm::SmallVector<IvarInfo, 8> IvarsInfo;
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002347
John McCall3fd13f062015-10-21 18:06:47 +00002348 public:
2349 IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
2350 CharUnits instanceEnd, bool forStrongLayout)
2351 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2352 ForStrongLayout(forStrongLayout) {
2353 }
2354
2355 void visitRecord(const RecordType *RT, CharUnits offset);
2356
2357 template <class Iterator, class GetOffsetFn>
Fangrui Song6907ce22018-07-30 19:24:48 +00002358 void visitAggregate(Iterator begin, Iterator end,
John McCall3fd13f062015-10-21 18:06:47 +00002359 CharUnits aggrOffset,
2360 const GetOffsetFn &getOffset);
2361
2362 void visitField(const FieldDecl *field, CharUnits offset);
2363
2364 /// Add the layout of a block implementation.
2365 void visitBlock(const CGBlockInfo &blockInfo);
2366
2367 /// Is there any information for an interesting bitmap?
2368 bool hasBitmapData() const { return !IvarsInfo.empty(); }
2369
2370 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2371 llvm::SmallVectorImpl<unsigned char> &buffer);
2372
2373 static void dump(ArrayRef<unsigned char> buffer) {
2374 const unsigned char *s = buffer.data();
2375 for (unsigned i = 0, e = buffer.size(); i < e; i++)
2376 if (!(s[i] & 0xf0))
2377 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
2378 else
2379 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
2380 printf("\n");
2381 }
2382 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002383} // end anonymous namespace
John McCall3fd13f062015-10-21 18:06:47 +00002384
John McCall351762c2011-02-07 10:33:21 +00002385llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
2386 const CGBlockInfo &blockInfo) {
Fangrui Song6907ce22018-07-30 19:24:48 +00002387
Chris Lattnerece04092012-02-07 00:39:47 +00002388 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
John McCall460ce582015-10-22 18:38:17 +00002389 if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
John McCall351762c2011-02-07 10:33:21 +00002390 return nullPtr;
2391
John McCall3fd13f062015-10-21 18:06:47 +00002392 IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize,
2393 /*for strong layout*/ true);
2394
2395 builder.visitBlock(blockInfo);
2396
2397 if (!builder.hasBitmapData())
2398 return nullPtr;
2399
2400 llvm::SmallVector<unsigned char, 32> buffer;
2401 llvm::Constant *C = builder.buildBitmap(*this, buffer);
John McCallf5ea0722015-10-29 23:36:14 +00002402 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
John McCall3fd13f062015-10-21 18:06:47 +00002403 printf("\n block variable layout for block: ");
2404 builder.dump(buffer);
2405 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002406
John McCall3fd13f062015-10-21 18:06:47 +00002407 return C;
2408}
2409
2410void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00002411 // __isa is the first field in block descriptor and must assume by runtime's
2412 // convention that it is GC'able.
John McCall3fd13f062015-10-21 18:06:47 +00002413 IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1));
John McCall351762c2011-02-07 10:33:21 +00002414
2415 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2416
John McCall351762c2011-02-07 10:33:21 +00002417 // Ignore the optional 'this' capture: C++ objects are not assumed
2418 // to be GC'ed.
2419
John McCall3fd13f062015-10-21 18:06:47 +00002420 CharUnits lastFieldOffset;
2421
John McCall351762c2011-02-07 10:33:21 +00002422 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002423 for (const auto &CI : blockDecl->captures()) {
2424 const VarDecl *variable = CI.getVariable();
John McCall351762c2011-02-07 10:33:21 +00002425 QualType type = variable->getType();
2426
2427 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2428
2429 // Ignore constant captures.
2430 if (capture.isConstant()) continue;
2431
John McCall3fd13f062015-10-21 18:06:47 +00002432 CharUnits fieldOffset = capture.getOffset();
2433
2434 // Block fields are not necessarily ordered; if we detect that we're
2435 // adding them out-of-order, make sure we sort later.
2436 if (fieldOffset < lastFieldOffset)
2437 IsDisordered = true;
2438 lastFieldOffset = fieldOffset;
John McCall351762c2011-02-07 10:33:21 +00002439
2440 // __block variables are passed by their descriptor address.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002441 if (CI.isByRef()) {
John McCall3fd13f062015-10-21 18:06:47 +00002442 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00002443 continue;
John McCall351762c2011-02-07 10:33:21 +00002444 }
2445
2446 assert(!type->isArrayType() && "array variable should not be caught");
2447 if (const RecordType *record = type->getAs<RecordType>()) {
John McCall3fd13f062015-10-21 18:06:47 +00002448 visitRecord(record, fieldOffset);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00002449 continue;
2450 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002451
John McCall351762c2011-02-07 10:33:21 +00002452 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
John McCall351762c2011-02-07 10:33:21 +00002453
John McCall3fd13f062015-10-21 18:06:47 +00002454 if (GCAttr == Qualifiers::Strong) {
2455 assert(CGM.getContext().getTypeSize(type)
2456 == CGM.getTarget().getPointerWidth(0));
2457 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
2458 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002459 }
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00002460}
2461
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00002462/// getBlockCaptureLifetime - This routine returns life time of the captured
2463/// block variable for the purpose of block layout meta-data generation. FQT is
2464/// the type of the variable captured in the block.
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002465Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
2466 bool ByrefLayout) {
John McCall460ce582015-10-22 18:38:17 +00002467 // If it has an ownership qualifier, we're done.
2468 if (auto lifetime = FQT.getObjCLifetime())
2469 return lifetime;
2470
2471 // If it doesn't, and this is ARC, it has no ownership.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002472 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCall460ce582015-10-22 18:38:17 +00002473 return Qualifiers::OCL_None;
Fangrui Song6907ce22018-07-30 19:24:48 +00002474
John McCall460ce582015-10-22 18:38:17 +00002475 // In MRC, retainable pointers are owned by non-__block variables.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002476 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002477 return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
Fangrui Song6907ce22018-07-30 19:24:48 +00002478
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002479 return Qualifiers::OCL_None;
2480}
2481
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002482void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
2483 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002484 CharUnits FieldOffset,
2485 CharUnits FieldSize) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002486 // __block variables are passed by their descriptor address.
2487 if (IsByref)
2488 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002489 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002490 else if (LifeTime == Qualifiers::OCL_Strong)
2491 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002492 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002493 else if (LifeTime == Qualifiers::OCL_Weak)
2494 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002495 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002496 else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2497 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002498 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002499 else
2500 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2501 FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002502 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002503}
2504
2505void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2506 const RecordDecl *RD,
2507 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002508 CharUnits BytePos, bool &HasUnion,
2509 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002510 bool IsUnion = (RD && RD->isUnion());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002511 CharUnits MaxUnionSize = CharUnits::Zero();
Craig Topper8a13c412014-05-21 05:09:00 +00002512 const FieldDecl *MaxField = nullptr;
2513 const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002514 CharUnits MaxFieldOffset = CharUnits::Zero();
2515 CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
Fangrui Song6907ce22018-07-30 19:24:48 +00002516
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002517 if (RecFields.empty())
2518 return;
John McCallc8e01702013-04-16 22:48:15 +00002519 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fangrui Song6907ce22018-07-30 19:24:48 +00002520
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002521 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2522 const FieldDecl *Field = RecFields[i];
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002523 // Note that 'i' here is actually the field index inside RD of Field,
2524 // although this dependency is hidden.
2525 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002526 CharUnits FieldOffset =
2527 CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
Fangrui Song6907ce22018-07-30 19:24:48 +00002528
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002529 // Skip over unnamed or bitfields
2530 if (!Field->getIdentifier() || Field->isBitField()) {
2531 LastFieldBitfieldOrUnnamed = Field;
2532 LastBitfieldOrUnnamedOffset = FieldOffset;
2533 continue;
2534 }
Craig Topper8a13c412014-05-21 05:09:00 +00002535
2536 LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002537 QualType FQT = Field->getType();
2538 if (FQT->isRecordType() || FQT->isUnionType()) {
2539 if (FQT->isUnionType())
2540 HasUnion = true;
Fangrui Song6907ce22018-07-30 19:24:48 +00002541
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002542 BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
2543 BytePos + FieldOffset, HasUnion);
2544 continue;
2545 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002546
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002547 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00002548 auto *CArray = cast<ConstantArrayType>(Array);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002549 uint64_t ElCount = CArray->getSize().getZExtValue();
2550 assert(CArray && "only array with known element size is supported");
2551 FQT = CArray->getElementType();
2552 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00002553 auto *CArray = cast<ConstantArrayType>(Array);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002554 ElCount *= CArray->getSize().getZExtValue();
2555 FQT = CArray->getElementType();
2556 }
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002557 if (FQT->isRecordType() && ElCount) {
2558 int OldIndex = RunSkipBlockVars.size() - 1;
2559 const RecordType *RT = FQT->getAs<RecordType>();
2560 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
2561 HasUnion);
Fangrui Song6907ce22018-07-30 19:24:48 +00002562
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002563 // Replicate layout information for each array element. Note that
2564 // one element is already done.
2565 uint64_t ElIx = 1;
2566 for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002567 CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002568 for (int i = OldIndex+1; i <= FirstIndex; ++i)
2569 RunSkipBlockVars.push_back(
2570 RUN_SKIP(RunSkipBlockVars[i].opcode,
2571 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2572 RunSkipBlockVars[i].block_var_size));
2573 }
2574 continue;
2575 }
2576 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002577 CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002578 if (IsUnion) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002579 CharUnits UnionIvarSize = FieldSize;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002580 if (UnionIvarSize > MaxUnionSize) {
2581 MaxUnionSize = UnionIvarSize;
2582 MaxField = Field;
2583 MaxFieldOffset = FieldOffset;
2584 }
2585 } else {
2586 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002587 getBlockCaptureLifetime(FQT, ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002588 BytePos + FieldOffset,
2589 FieldSize);
2590 }
2591 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002592
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002593 if (LastFieldBitfieldOrUnnamed) {
2594 if (LastFieldBitfieldOrUnnamed->isBitField()) {
2595 // Last field was a bitfield. Must update the info.
2596 uint64_t BitFieldSize
2597 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002598 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
Eli Friedman8cbca202012-11-06 22:15:52 +00002599 ((BitFieldSize % ByteSizeInBits) != 0);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002600 CharUnits Size = CharUnits::fromQuantity(UnsSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002601 Size += LastBitfieldOrUnnamedOffset;
2602 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002603 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2604 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002605 BytePos + LastBitfieldOrUnnamedOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002606 Size);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002607 } else {
2608 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2609 // Last field was unnamed. Must update skip info.
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002610 CharUnits FieldSize
2611 = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002612 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002613 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2614 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002615 BytePos + LastBitfieldOrUnnamedOffset,
2616 FieldSize);
2617 }
2618 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002619
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002620 if (MaxField)
2621 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002622 getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002623 BytePos + MaxFieldOffset,
2624 MaxUnionSize);
2625}
2626
2627void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002628 CharUnits BytePos,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002629 bool &HasUnion,
2630 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002631 const RecordDecl *RD = RT->getDecl();
Aaron Ballman62e47c42014-03-10 13:43:55 +00002632 SmallVector<const FieldDecl*, 16> Fields(RD->fields());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002633 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
2634 const llvm::StructLayout *RecLayout =
2635 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
Fangrui Song6907ce22018-07-30 19:24:48 +00002636
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002637 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002638}
2639
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002640/// InlineLayoutInstruction - This routine produce an inline instruction for the
2641/// block variable layout if it can. If not, it returns 0. Rules are as follow:
2642/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
2643/// an inline layout of value 0x0000000000000xyz is interpreted as follows:
2644/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
2645/// y captured object of BLOCK_LAYOUT_BYREF. Followed by
2646/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
2647/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
2648/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
2649uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2650 SmallVectorImpl<unsigned char> &Layout) {
2651 uint64_t Result = 0;
2652 if (Layout.size() <= 3) {
2653 unsigned size = Layout.size();
2654 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2655 unsigned char inst;
2656 enum BLOCK_LAYOUT_OPCODE opcode ;
2657 switch (size) {
2658 case 3:
2659 inst = Layout[0];
2660 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2661 if (opcode == BLOCK_LAYOUT_STRONG)
2662 strong_word_count = (inst & 0xF)+1;
2663 else
2664 return 0;
2665 inst = Layout[1];
2666 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2667 if (opcode == BLOCK_LAYOUT_BYREF)
2668 byref_word_count = (inst & 0xF)+1;
2669 else
2670 return 0;
2671 inst = Layout[2];
2672 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2673 if (opcode == BLOCK_LAYOUT_WEAK)
2674 weak_word_count = (inst & 0xF)+1;
2675 else
2676 return 0;
2677 break;
Fangrui Song6907ce22018-07-30 19:24:48 +00002678
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002679 case 2:
2680 inst = Layout[0];
2681 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2682 if (opcode == BLOCK_LAYOUT_STRONG) {
2683 strong_word_count = (inst & 0xF)+1;
2684 inst = Layout[1];
2685 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2686 if (opcode == BLOCK_LAYOUT_BYREF)
2687 byref_word_count = (inst & 0xF)+1;
2688 else if (opcode == BLOCK_LAYOUT_WEAK)
2689 weak_word_count = (inst & 0xF)+1;
2690 else
2691 return 0;
2692 }
2693 else if (opcode == BLOCK_LAYOUT_BYREF) {
2694 byref_word_count = (inst & 0xF)+1;
2695 inst = Layout[1];
2696 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2697 if (opcode == BLOCK_LAYOUT_WEAK)
2698 weak_word_count = (inst & 0xF)+1;
2699 else
2700 return 0;
2701 }
2702 else
2703 return 0;
2704 break;
Fangrui Song6907ce22018-07-30 19:24:48 +00002705
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002706 case 1:
2707 inst = Layout[0];
2708 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2709 if (opcode == BLOCK_LAYOUT_STRONG)
2710 strong_word_count = (inst & 0xF)+1;
2711 else if (opcode == BLOCK_LAYOUT_BYREF)
2712 byref_word_count = (inst & 0xF)+1;
2713 else if (opcode == BLOCK_LAYOUT_WEAK)
2714 weak_word_count = (inst & 0xF)+1;
2715 else
2716 return 0;
2717 break;
Fangrui Song6907ce22018-07-30 19:24:48 +00002718
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002719 default:
2720 return 0;
2721 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002722
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002723 // Cannot inline when any of the word counts is 15. Because this is one less
2724 // than the actual work count (so 15 means 16 actual word counts),
2725 // and we can only display 0 thru 15 word counts.
2726 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2727 return 0;
Fangrui Song6907ce22018-07-30 19:24:48 +00002728
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002729 unsigned count =
2730 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
Fangrui Song6907ce22018-07-30 19:24:48 +00002731
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002732 if (size == count) {
2733 if (strong_word_count)
2734 Result = strong_word_count;
2735 Result <<= 4;
2736 if (byref_word_count)
2737 Result += byref_word_count;
2738 Result <<= 4;
2739 if (weak_word_count)
2740 Result += weak_word_count;
2741 }
2742 }
2743 return Result;
2744}
2745
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002746llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
2747 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2748 if (RunSkipBlockVars.empty())
2749 return nullPtr;
John McCallc8e01702013-04-16 22:48:15 +00002750 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2751 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002752 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
Fangrui Song6907ce22018-07-30 19:24:48 +00002753
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002754 // Sort on byte position; captures might not be allocated in order,
2755 // and unions can do funny things.
2756 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2757 SmallVector<unsigned char, 16> Layout;
Fangrui Song6907ce22018-07-30 19:24:48 +00002758
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002759 unsigned size = RunSkipBlockVars.size();
2760 for (unsigned i = 0; i < size; i++) {
2761 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2762 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2763 CharUnits end_byte_pos = start_byte_pos;
2764 unsigned j = i+1;
2765 while (j < size) {
2766 if (opcode == RunSkipBlockVars[j].opcode) {
2767 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2768 i++;
2769 }
2770 else
2771 break;
2772 }
2773 CharUnits size_in_bytes =
2774 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2775 if (j < size) {
2776 CharUnits gap =
2777 RunSkipBlockVars[j].block_var_bytepos -
2778 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2779 size_in_bytes += gap;
2780 }
2781 CharUnits residue_in_bytes = CharUnits::Zero();
2782 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2783 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2784 size_in_bytes -= residue_in_bytes;
2785 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2786 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002787
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002788 unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
2789 while (size_in_words >= 16) {
2790 // Note that value in imm. is one less that the actual
2791 // value. So, 0xf means 16 words follow!
2792 unsigned char inst = (opcode << 4) | 0xf;
2793 Layout.push_back(inst);
2794 size_in_words -= 16;
2795 }
2796 if (size_in_words > 0) {
2797 // Note that value in imm. is one less that the actual
2798 // value. So, we subtract 1 away!
2799 unsigned char inst = (opcode << 4) | (size_in_words-1);
2800 Layout.push_back(inst);
2801 }
2802 if (residue_in_bytes > CharUnits::Zero()) {
2803 unsigned char inst =
2804 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
2805 Layout.push_back(inst);
2806 }
2807 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002808
John McCall7f416cc2015-09-08 08:05:57 +00002809 while (!Layout.empty()) {
2810 unsigned char inst = Layout.back();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002811 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2812 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2813 Layout.pop_back();
2814 else
2815 break;
2816 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002817
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002818 uint64_t Result = InlineLayoutInstruction(Layout);
2819 if (Result != 0) {
2820 // Block variable layout instruction has been inlined.
2821 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2822 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002823 printf("\n Inline BYREF variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002824 else
John McCall7f416cc2015-09-08 08:05:57 +00002825 printf("\n Inline block variable layout: ");
2826 printf("0x0%" PRIx64 "", Result);
2827 if (auto numStrong = (Result & 0xF00) >> 8)
2828 printf(", BL_STRONG:%d", (int) numStrong);
2829 if (auto numByref = (Result & 0x0F0) >> 4)
2830 printf(", BL_BYREF:%d", (int) numByref);
2831 if (auto numWeak = (Result & 0x00F) >> 0)
2832 printf(", BL_WEAK:%d", (int) numWeak);
2833 printf(", BL_OPERATOR:0\n");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002834 }
Vedant Kumar3ed0df02015-12-21 19:43:25 +00002835 return llvm::ConstantInt::get(CGM.IntPtrTy, Result);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002836 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002837
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002838 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2839 Layout.push_back(inst);
2840 std::string BitMap;
2841 for (unsigned i = 0, e = Layout.size(); i != e; i++)
2842 BitMap += Layout[i];
Fangrui Song6907ce22018-07-30 19:24:48 +00002843
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002844 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2845 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002846 printf("\n Byref variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002847 else
John McCall7f416cc2015-09-08 08:05:57 +00002848 printf("\n Block variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002849 for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
2850 unsigned char inst = BitMap[i];
2851 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2852 unsigned delta = 1;
2853 switch (opcode) {
2854 case BLOCK_LAYOUT_OPERATOR:
2855 printf("BL_OPERATOR:");
2856 delta = 0;
2857 break;
2858 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2859 printf("BL_NON_OBJECT_BYTES:");
2860 break;
2861 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2862 printf("BL_NON_OBJECT_WORD:");
2863 break;
2864 case BLOCK_LAYOUT_STRONG:
2865 printf("BL_STRONG:");
2866 break;
2867 case BLOCK_LAYOUT_BYREF:
2868 printf("BL_BYREF:");
2869 break;
2870 case BLOCK_LAYOUT_WEAK:
2871 printf("BL_WEAK:");
2872 break;
2873 case BLOCK_LAYOUT_UNRETAINED:
2874 printf("BL_UNRETAINED:");
2875 break;
2876 }
2877 // Actual value of word count is one more that what is in the imm.
2878 // field of the instruction
2879 printf("%d", (inst & 0xf) + delta);
2880 if (i < e-1)
2881 printf(", ");
2882 else
2883 printf("\n");
2884 }
2885 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00002886
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00002887 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2888 /*ForceNonFragileABI=*/true,
2889 /*NullTerminate=*/false);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002890 return getConstantGEP(VMContext, Entry, 0, 0);
2891}
2892
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00002893static std::string getBlockLayoutInfoString(
2894 const SmallVectorImpl<CGObjCCommonMac::RUN_SKIP> &RunSkipBlockVars,
2895 bool HasCopyDisposeHelpers) {
2896 std::string Str;
2897 for (const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
2898 if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
2899 // Copy/dispose helpers don't have any information about
2900 // __unsafe_unretained captures, so unconditionally concatenate a string.
2901 Str += "u";
2902 } else if (HasCopyDisposeHelpers) {
2903 // Information about __strong, __weak, or byref captures has already been
2904 // encoded into the names of the copy/dispose helpers. We have to add a
2905 // string here only when the copy/dispose helpers aren't generated (which
2906 // happens when the block is non-escaping).
2907 continue;
2908 } else {
2909 switch (R.opcode) {
2910 case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
2911 Str += "s";
2912 break;
2913 case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
2914 Str += "r";
2915 break;
2916 case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
2917 Str += "w";
2918 break;
2919 default:
2920 continue;
2921 }
2922 }
2923 Str += llvm::to_string(R.block_var_bytepos.getQuantity());
2924 Str += "l" + llvm::to_string(R.block_var_size.getQuantity());
2925 }
2926 return Str;
2927}
2928
2929void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM,
2930 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002931 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
Fangrui Song6907ce22018-07-30 19:24:48 +00002932
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002933 RunSkipBlockVars.clear();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002934 bool hasUnion = false;
Fangrui Song6907ce22018-07-30 19:24:48 +00002935
John McCallc8e01702013-04-16 22:48:15 +00002936 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2937 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002938 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
Fangrui Song6907ce22018-07-30 19:24:48 +00002939
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002940 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
Fangrui Song6907ce22018-07-30 19:24:48 +00002941
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002942 // Calculate the basic layout of the block structure.
2943 const llvm::StructLayout *layout =
2944 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
Fangrui Song6907ce22018-07-30 19:24:48 +00002945
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002946 // Ignore the optional 'this' capture: C++ objects are not assumed
2947 // to be GC'ed.
Fariborz Jahanian4cf177e2012-12-04 17:20:57 +00002948 if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
2949 UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
2950 blockInfo.BlockHeaderForcedGapOffset,
2951 blockInfo.BlockHeaderForcedGapSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002952 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002953 for (const auto &CI : blockDecl->captures()) {
2954 const VarDecl *variable = CI.getVariable();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002955 QualType type = variable->getType();
Fangrui Song6907ce22018-07-30 19:24:48 +00002956
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002957 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
Fangrui Song6907ce22018-07-30 19:24:48 +00002958
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002959 // Ignore constant captures.
2960 if (capture.isConstant()) continue;
Fangrui Song6907ce22018-07-30 19:24:48 +00002961
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002962 CharUnits fieldOffset =
2963 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fangrui Song6907ce22018-07-30 19:24:48 +00002964
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002965 assert(!type->isArrayType() && "array variable should not be caught");
Aaron Ballman9371dd22014-03-14 18:34:04 +00002966 if (!CI.isByRef())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002967 if (const RecordType *record = type->getAs<RecordType>()) {
2968 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2969 continue;
2970 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002971 CharUnits fieldSize;
Aaron Ballman9371dd22014-03-14 18:34:04 +00002972 if (CI.isByRef())
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002973 fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2974 else
2975 fieldSize = CGM.getContext().getTypeSizeInChars(type);
Aaron Ballman9371dd22014-03-14 18:34:04 +00002976 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002977 fieldOffset, fieldSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002978 }
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00002979}
2980
2981llvm::Constant *
2982CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2983 const CGBlockInfo &blockInfo) {
2984 fillRunSkipBlockVars(CGM, blockInfo);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002985 return getBitmapBlockLayout(false);
2986}
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002987
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00002988std::string CGObjCCommonMac::getRCBlockLayoutStr(CodeGenModule &CGM,
2989 const CGBlockInfo &blockInfo) {
2990 fillRunSkipBlockVars(CGM, blockInfo);
2991 return getBlockLayoutInfoString(RunSkipBlockVars,
2992 blockInfo.needsCopyDisposeHelpers());
2993}
2994
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002995llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2996 QualType T) {
2997 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2998 assert(!T->isArrayType() && "__block array variable should not be caught");
2999 CharUnits fieldOffset;
3000 RunSkipBlockVars.clear();
3001 bool hasUnion = false;
3002 if (const RecordType *record = T->getAs<RecordType>()) {
3003 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
3004 llvm::Constant *Result = getBitmapBlockLayout(true);
Vedant Kumar2f5bb1152015-12-21 20:21:15 +00003005 if (isa<llvm::ConstantInt>(Result))
3006 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00003007 return Result;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00003008 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00003009 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
3010 return nullPtr;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00003011}
3012
John McCall882987f2013-02-28 19:01:20 +00003013llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00003014 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00003015 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00003016 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00003017 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
3018
Owen Andersonade90fd2009-07-29 18:54:39 +00003019 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00003020 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003021}
3022
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00003023void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00003024 // FIXME: We shouldn't need this, the protocol decl should contain enough
3025 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00003026 DefinedProtocols.insert(PD->getIdentifier());
3027
3028 // If we have generated a forward reference to this protocol, emit
3029 // it now. Otherwise do nothing, the protocol objects are lazily
3030 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003031 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00003032 GetOrEmitProtocol(PD);
3033}
3034
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00003035llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00003036 if (DefinedProtocols.count(PD->getIdentifier()))
3037 return GetOrEmitProtocol(PD);
Fangrui Song6907ce22018-07-30 19:24:48 +00003038
Daniel Dunbarc475d422008-10-29 22:36:39 +00003039 return GetOrEmitProtocolRef(PD);
3040}
3041
Douglas Gregor24ae22c2016-04-01 23:23:52 +00003042llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
3043 CodeGenFunction &CGF,
3044 const ObjCInterfaceDecl *ID,
3045 ObjCCommonTypesHelper &ObjCTypes) {
James Y Knight9871db02019-02-05 16:42:33 +00003046 llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
Douglas Gregor24ae22c2016-04-01 23:23:52 +00003047
3048 llvm::Value *className =
3049 CGF.CGM.GetAddrOfConstantCString(ID->getObjCRuntimeNameAsString())
3050 .getPointer();
3051 ASTContext &ctx = CGF.CGM.getContext();
3052 className =
3053 CGF.Builder.CreateBitCast(className,
3054 CGF.ConvertType(
3055 ctx.getPointerType(ctx.CharTy.withConst())));
3056 llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className);
3057 call->setDoesNotThrow();
3058 return call;
3059}
3060
Daniel Dunbarb036db82008-08-13 03:21:16 +00003061/*
Rafael Espindolaf9e1e5e2014-02-20 14:09:04 +00003062// Objective-C 1.0 extensions
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003063struct _objc_protocol {
3064struct _objc_protocol_extension *isa;
3065char *protocol_name;
3066struct _objc_protocol_list *protocol_list;
3067struct _objc__method_prototype_list *instance_methods;
3068struct _objc__method_prototype_list *class_methods
3069};
Daniel Dunbarb036db82008-08-13 03:21:16 +00003070
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003071See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00003072*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00003073llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00003074 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbarc475d422008-10-29 22:36:39 +00003075
3076 // Early exit if a defining object has already been generated.
3077 if (Entry && Entry->hasInitializer())
3078 return Entry;
3079
Douglas Gregora715bff2012-01-01 19:51:50 +00003080 // Use the protocol definition, if there is one.
3081 if (const ObjCProtocolDecl *Def = PD->getDefinition())
3082 PD = Def;
3083
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003084 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00003085 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003086 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
3087
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003088 // Construct method lists.
John McCall176f8922016-11-30 02:39:18 +00003089 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003090
John McCall176f8922016-11-30 02:39:18 +00003091 ConstantInitBuilder builder(CGM);
3092 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
3093 values.add(EmitProtocolExtension(PD, methodLists));
3094 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
3095 values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
3096 PD->protocol_begin(), PD->protocol_end()));
3097 values.add(methodLists.emitMethodList(this, PD,
3098 ProtocolMethodLists::RequiredInstanceMethods));
3099 values.add(methodLists.emitMethodList(this, PD,
3100 ProtocolMethodLists::RequiredClassMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003101
Daniel Dunbarb036db82008-08-13 03:21:16 +00003102 if (Entry) {
Rafael Espindola5d117f32014-03-06 01:10:46 +00003103 // Already created, update the initializer.
Rafael Espindolab3262952014-05-09 00:43:37 +00003104 assert(Entry->hasPrivateLinkage());
John McCall176f8922016-11-30 02:39:18 +00003105 values.finishAndSetAsInitializer(Entry);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003106 } else {
John McCall176f8922016-11-30 02:39:18 +00003107 Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(),
3108 CGM.getPointerAlign(),
3109 /*constant*/ false,
3110 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003111 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
John McCallf9582a72012-03-30 21:29:05 +00003112
3113 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00003114 }
Rafael Espindola060062a2014-03-06 22:15:10 +00003115 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00003116
3117 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00003118}
3119
Daniel Dunbarc475d422008-10-29 22:36:39 +00003120llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003121 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
3122
3123 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00003124 // We use the initializer as a marker of whether this is a forward
3125 // reference or not. At module finalization we add the empty
3126 // contents for protocols which were referenced but never defined.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003127 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
3128 false, llvm::GlobalValue::PrivateLinkage,
3129 nullptr, "OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00003130 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00003131 // FIXME: Is this necessary? Why only for protocol?
Guillaume Chateletc79099e2019-10-03 13:00:29 +00003132 Entry->setAlignment(llvm::Align(4));
Daniel Dunbarb036db82008-08-13 03:21:16 +00003133 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003134
Daniel Dunbarb036db82008-08-13 03:21:16 +00003135 return Entry;
3136}
3137
3138/*
3139 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003140 uint32_t size;
3141 struct objc_method_description_list *optional_instance_methods;
3142 struct objc_method_description_list *optional_class_methods;
3143 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003144 const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00003145 struct objc_property_list *class_properties;
Daniel Dunbarb036db82008-08-13 03:21:16 +00003146 };
3147*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003148llvm::Constant *
3149CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00003150 const ProtocolMethodLists &methodLists) {
3151 auto optInstanceMethods =
3152 methodLists.emitMethodList(this, PD,
3153 ProtocolMethodLists::OptionalInstanceMethods);
3154 auto optClassMethods =
3155 methodLists.emitMethodList(this, PD,
3156 ProtocolMethodLists::OptionalClassMethods);
3157
3158 auto extendedMethodTypes =
3159 EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
3160 methodLists.emitExtendedTypesArray(this),
3161 ObjCTypes);
3162
3163 auto instanceProperties =
3164 EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD,
3165 ObjCTypes, false);
3166 auto classProperties =
3167 EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr,
3168 PD, ObjCTypes, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003169
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003170 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00003171 if (optInstanceMethods->isNullValue() &&
3172 optClassMethods->isNullValue() &&
3173 extendedMethodTypes->isNullValue() &&
3174 instanceProperties->isNullValue() &&
3175 classProperties->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003176 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003177 }
Daniel Dunbarb036db82008-08-13 03:21:16 +00003178
John McCall176f8922016-11-30 02:39:18 +00003179 uint64_t size =
3180 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3181
3182 ConstantInitBuilder builder(CGM);
3183 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3184 values.addInt(ObjCTypes.IntTy, size);
3185 values.add(optInstanceMethods);
3186 values.add(optClassMethods);
3187 values.add(instanceProperties);
3188 values.add(extendedMethodTypes);
3189 values.add(classProperties);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003190
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003191 // No special section, but goes in llvm.used
Akira Hatanaka187770d2019-05-09 17:43:52 +00003192 return CreateMetadataVar("_OBJC_PROTOCOLEXT_" + PD->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00003193 StringRef(), CGM.getPointerAlign(), true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003194}
3195
3196/*
3197 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00003198 struct objc_protocol_list *next;
3199 long count;
3200 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00003201 };
3202*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00003203llvm::Constant *
Zachary Turner41a9ee92017-10-11 23:54:34 +00003204CGObjCMac::EmitProtocolList(Twine name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00003205 ObjCProtocolDecl::protocol_iterator begin,
3206 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003207 // Just return null for empty protocol lists
John McCall176f8922016-11-30 02:39:18 +00003208 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00003209 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003210
John McCall176f8922016-11-30 02:39:18 +00003211 ConstantInitBuilder builder(CGM);
3212 auto values = builder.beginStruct();
Daniel Dunbarb036db82008-08-13 03:21:16 +00003213
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003214 // This field is only used by the runtime.
John McCall176f8922016-11-30 02:39:18 +00003215 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003216
John McCall176f8922016-11-30 02:39:18 +00003217 // Reserve a slot for the count.
3218 auto countSlot = values.addPlaceholder();
3219
3220 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3221 for (; begin != end; ++begin) {
3222 refsArray.add(GetProtocolRef(*begin));
3223 }
3224 auto count = refsArray.size();
3225
3226 // This list is null terminated.
3227 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3228
3229 refsArray.finishAndAddTo(values);
3230 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3231
3232 StringRef section;
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003233 if (CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00003234 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003235
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003236 llvm::GlobalVariable *GV =
Zachary Turner41a9ee92017-10-11 23:54:34 +00003237 CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false);
Owen Andersonade90fd2009-07-29 18:54:39 +00003238 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003239}
3240
Fangrui Song6907ce22018-07-30 19:24:48 +00003241static void
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003242PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
John McCall176f8922016-11-30 02:39:18 +00003243 SmallVectorImpl<const ObjCPropertyDecl *> &Properties,
Aaron Ballmandc4bea42014-03-13 18:47:37 +00003244 const ObjCProtocolDecl *Proto,
Manman Renad0e7912016-01-29 19:22:54 +00003245 bool IsClassProperty) {
Fangrui Song6907ce22018-07-30 19:24:48 +00003246 for (const auto *P : Proto->protocols())
John McCall176f8922016-11-30 02:39:18 +00003247 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Manman Renad0e7912016-01-29 19:22:54 +00003248
3249 for (const auto *PD : Proto->properties()) {
3250 if (IsClassProperty != PD->isClassProperty())
3251 continue;
David Blaikie82e95a32014-11-19 07:49:47 +00003252 if (!PropertySet.insert(PD->getIdentifier()).second)
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003253 continue;
John McCall176f8922016-11-30 02:39:18 +00003254 Properties.push_back(PD);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003255 }
3256}
3257
Daniel Dunbarb036db82008-08-13 03:21:16 +00003258/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003259 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00003260 const char * const name;
3261 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003262 };
3263
3264 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00003265 uint32_t entsize; // sizeof (struct _objc_property)
3266 uint32_t prop_count;
3267 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003268 };
3269*/
Zachary Turner41a9ee92017-10-11 23:54:34 +00003270llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
3271 const Decl *Container,
3272 const ObjCContainerDecl *OCD,
3273 const ObjCCommonTypesHelper &ObjCTypes,
3274 bool IsClassProperty) {
Manman Ren01b705e2016-04-19 19:05:03 +00003275 if (IsClassProperty) {
3276 // Make this entry NULL for OS X with deployment target < 10.11, for iOS
3277 // with deployment target < 9.0.
3278 const llvm::Triple &Triple = CGM.getTarget().getTriple();
3279 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3280 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3281 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3282 }
3283
John McCall176f8922016-11-30 02:39:18 +00003284 SmallVector<const ObjCPropertyDecl *, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003285 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Nico Weber08c93332015-12-03 17:44:51 +00003286
Nico Weber08c93332015-12-03 17:44:51 +00003287 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3288 for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
Manman Renad0e7912016-01-29 19:22:54 +00003289 for (auto *PD : ClassExt->properties()) {
3290 if (IsClassProperty != PD->isClassProperty())
3291 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003292 PropertySet.insert(PD->getIdentifier());
John McCall176f8922016-11-30 02:39:18 +00003293 Properties.push_back(PD);
Nico Weber08c93332015-12-03 17:44:51 +00003294 }
Manman Renad0e7912016-01-29 19:22:54 +00003295
3296 for (const auto *PD : OCD->properties()) {
3297 if (IsClassProperty != PD->isClassProperty())
3298 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003299 // Don't emit duplicate metadata for properties that were already in a
3300 // class extension.
3301 if (!PropertySet.insert(PD->getIdentifier()).second)
3302 continue;
John McCall176f8922016-11-30 02:39:18 +00003303 Properties.push_back(PD);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003304 }
Nico Weber08c93332015-12-03 17:44:51 +00003305
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003306 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003307 for (const auto *P : OID->all_referenced_protocols())
John McCall176f8922016-11-30 02:39:18 +00003308 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003309 }
3310 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
Aaron Ballman19a41762014-03-14 12:55:57 +00003311 for (const auto *P : CD->protocols())
John McCall176f8922016-11-30 02:39:18 +00003312 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003313 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003314
3315 // Return null for empty list.
3316 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003317 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003318
John McCall176f8922016-11-30 02:39:18 +00003319 unsigned propertySize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00003320 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
John McCall176f8922016-11-30 02:39:18 +00003321
3322 ConstantInitBuilder builder(CGM);
3323 auto values = builder.beginStruct();
3324 values.addInt(ObjCTypes.IntTy, propertySize);
3325 values.addInt(ObjCTypes.IntTy, Properties.size());
3326 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3327 for (auto PD : Properties) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08003328 if (PD->isDirectProperty())
3329 continue;
John McCall176f8922016-11-30 02:39:18 +00003330 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3331 property.add(GetPropertyName(PD->getIdentifier()));
3332 property.add(GetPropertyTypeString(PD, Container));
3333 property.finishAndAddTo(propertiesArray);
3334 }
3335 propertiesArray.finishAndAddTo(values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003336
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003337 StringRef Section;
3338 if (CGM.getTriple().isOSBinFormatMachO())
3339 Section = (ObjCABI == 2) ? "__DATA, __objc_const"
3340 : "__OBJC,__property,regular,no_dead_strip";
3341
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003342 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003343 CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003344 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003345}
3346
Zachary Turner41a9ee92017-10-11 23:54:34 +00003347llvm::Constant *
3348CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
3349 ArrayRef<llvm::Constant*> MethodTypes,
3350 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003351 // Return null for empty list.
3352 if (MethodTypes.empty())
3353 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3354
3355 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3356 MethodTypes.size());
3357 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
3358
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003359 StringRef Section;
3360 if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3361 Section = "__DATA, __objc_const";
3362
3363 llvm::GlobalVariable *GV =
3364 CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003365 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
3366}
3367
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003368/*
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003369 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003370 char *category_name;
3371 char *class_name;
3372 struct _objc_method_list *instance_methods;
3373 struct _objc_method_list *class_methods;
3374 struct _objc_protocol_list *protocols;
3375 uint32_t size; // <rdar://4585769>
3376 struct _objc_property_list *instance_properties;
Manman Ren96df0b32016-01-29 23:45:01 +00003377 struct _objc_property_list *class_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003378 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003379*/
Daniel Dunbar92992502008-08-15 22:20:32 +00003380void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00003381 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003382
Mike Stump18bb9282009-05-16 07:57:57 +00003383 // FIXME: This is poor design, the OCD should have a pointer to the category
3384 // decl. Additionally, note that Category can be null for the @implementation
3385 // w/o an @interface case. Sema should just create one for us as it does for
3386 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003387 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003388 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003389 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003390
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003391 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003392 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
3393 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003394
John McCall176f8922016-11-30 02:39:18 +00003395 ConstantInitBuilder Builder(CGM);
3396 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
Aaron Ballmanf26acce2014-03-13 19:50:17 +00003397
John McCall176f8922016-11-30 02:39:18 +00003398 enum {
3399 InstanceMethods,
3400 ClassMethods,
3401 NumMethodLists
3402 };
3403 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3404 for (const auto *MD : OCD->methods()) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08003405 if (!MD->isDirectMethod())
3406 Methods[unsigned(MD->isClassMethod())].push_back(MD);
John McCall176f8922016-11-30 02:39:18 +00003407 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003408
John McCall176f8922016-11-30 02:39:18 +00003409 Values.add(GetClassName(OCD->getName()));
3410 Values.add(GetClassName(Interface->getObjCRuntimeNameAsString()));
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00003411 LazySymbols.insert(Interface->getIdentifier());
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003412
John McCall176f8922016-11-30 02:39:18 +00003413 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3414 Methods[InstanceMethods]));
3415 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3416 Methods[ClassMethods]));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003417 if (Category) {
John McCall176f8922016-11-30 02:39:18 +00003418 Values.add(
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003419 EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003420 Category->protocol_begin(), Category->protocol_end()));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003421 } else {
John McCall176f8922016-11-30 02:39:18 +00003422 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003423 }
John McCall176f8922016-11-30 02:39:18 +00003424 Values.addInt(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003425
3426 // If there is no category @interface then there can be no properties.
3427 if (Category) {
Akira Hatanaka187770d2019-05-09 17:43:52 +00003428 Values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003429 OCD, Category, ObjCTypes, false));
Akira Hatanaka187770d2019-05-09 17:43:52 +00003430 Values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003431 OCD, Category, ObjCTypes, true));
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003432 } else {
John McCall176f8922016-11-30 02:39:18 +00003433 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3434 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003435 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003436
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003437 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003438 CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values,
John McCall7f416cc2015-09-08 08:05:57 +00003439 "__OBJC,__category,regular,no_dead_strip",
3440 CGM.getPointerAlign(), true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003441 DefinedCategories.push_back(GV);
Justin Lebar5e83dfe2016-10-21 21:45:01 +00003442 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003443 // method definition entries must be clear for next implementation.
3444 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003445}
3446
John McCallef19dbb2012-10-17 04:53:23 +00003447enum FragileClassFlags {
John McCall460ce582015-10-22 18:38:17 +00003448 /// Apparently: is not a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003449 FragileABI_Class_Factory = 0x00001,
John McCall460ce582015-10-22 18:38:17 +00003450
3451 /// Is a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003452 FragileABI_Class_Meta = 0x00002,
John McCall460ce582015-10-22 18:38:17 +00003453
3454 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003455 FragileABI_Class_HasCXXStructors = 0x02000,
John McCall460ce582015-10-22 18:38:17 +00003456
3457 /// Has hidden visibility.
John McCall09ec1ec2015-10-21 22:06:03 +00003458 FragileABI_Class_Hidden = 0x20000,
John McCall460ce582015-10-22 18:38:17 +00003459
3460 /// Class implementation was compiled under ARC.
3461 FragileABI_Class_CompiledByARC = 0x04000000,
3462
3463 /// Class implementation was compiled under MRC and has MRC weak ivars.
3464 /// Exclusive with CompiledByARC.
3465 FragileABI_Class_HasMRCWeakIvars = 0x08000000,
John McCallef19dbb2012-10-17 04:53:23 +00003466};
3467
3468enum NonFragileClassFlags {
3469 /// Is a meta-class.
3470 NonFragileABI_Class_Meta = 0x00001,
3471
3472 /// Is a root class.
3473 NonFragileABI_Class_Root = 0x00002,
3474
John McCall460ce582015-10-22 18:38:17 +00003475 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003476 NonFragileABI_Class_HasCXXStructors = 0x00004,
3477
3478 /// Has hidden visibility.
3479 NonFragileABI_Class_Hidden = 0x00010,
3480
3481 /// Has the exception attribute.
3482 NonFragileABI_Class_Exception = 0x00020,
3483
3484 /// (Obsolete) ARC-specific: this class has a .release_ivars method
3485 NonFragileABI_Class_HasIvarReleaser = 0x00040,
3486
3487 /// Class implementation was compiled under ARC.
John McCall0d54a172012-10-17 04:53:31 +00003488 NonFragileABI_Class_CompiledByARC = 0x00080,
3489
3490 /// Class has non-trivial destructors, but zero-initialization is okay.
John McCall460ce582015-10-22 18:38:17 +00003491 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100,
3492
3493 /// Class implementation was compiled under MRC and has MRC weak ivars.
3494 /// Exclusive with CompiledByARC.
3495 NonFragileABI_Class_HasMRCWeakIvars = 0x00200,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003496};
3497
John McCall460ce582015-10-22 18:38:17 +00003498static bool hasWeakMember(QualType type) {
3499 if (type.getObjCLifetime() == Qualifiers::OCL_Weak) {
3500 return true;
3501 }
3502
3503 if (auto recType = type->getAs<RecordType>()) {
3504 for (auto field : recType->getDecl()->fields()) {
3505 if (hasWeakMember(field->getType()))
3506 return true;
3507 }
3508 }
3509
3510 return false;
3511}
3512
3513/// For compatibility, we only want to set the "HasMRCWeakIvars" flag
3514/// (and actually fill in a layout string) if we really do have any
3515/// __weak ivars.
3516static bool hasMRCWeakIvars(CodeGenModule &CGM,
3517 const ObjCImplementationDecl *ID) {
3518 if (!CGM.getLangOpts().ObjCWeak) return false;
3519 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
3520
3521 for (const ObjCIvarDecl *ivar =
3522 ID->getClassInterface()->all_declared_ivar_begin();
3523 ivar; ivar = ivar->getNextIvar()) {
3524 if (hasWeakMember(ivar->getType()))
3525 return true;
3526 }
3527
3528 return false;
3529}
3530
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003531/*
3532 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003533 Class isa;
3534 Class super_class;
3535 const char *name;
3536 long version;
3537 long info;
3538 long instance_size;
3539 struct _objc_ivar_list *ivars;
3540 struct _objc_method_list *methods;
3541 struct _objc_cache *cache;
3542 struct _objc_protocol_list *protocols;
3543 // Objective-C 1.0 extensions (<rdr://4585769>)
3544 const char *ivar_layout;
3545 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003546 };
3547
3548 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003549*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003550void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Akira Hatanaka0c194462018-04-03 22:50:16 +00003551 IdentifierInfo *RuntimeName =
3552 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
3553 DefinedSymbols.insert(RuntimeName);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003554
Chris Lattner86d7d912008-11-24 03:54:41 +00003555 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003556 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003557 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003558 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003559 llvm::Constant *Protocols =
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003560 EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(),
3561 Interface->all_referenced_protocol_begin(),
3562 Interface->all_referenced_protocol_end());
John McCallef19dbb2012-10-17 04:53:23 +00003563 unsigned Flags = FragileABI_Class_Factory;
John McCall0d54a172012-10-17 04:53:31 +00003564 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCallef19dbb2012-10-17 04:53:23 +00003565 Flags |= FragileABI_Class_HasCXXStructors;
John McCall09ec1ec2015-10-21 22:06:03 +00003566
John McCall460ce582015-10-22 18:38:17 +00003567 bool hasMRCWeak = false;
3568
John McCall09ec1ec2015-10-21 22:06:03 +00003569 if (CGM.getLangOpts().ObjCAutoRefCount)
3570 Flags |= FragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00003571 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
3572 Flags |= FragileABI_Class_HasMRCWeakIvars;
John McCall09ec1ec2015-10-21 22:06:03 +00003573
John McCall3fd13f062015-10-21 18:06:47 +00003574 CharUnits Size =
3575 CGM.getContext().getASTObjCImplementationLayout(ID).getSize();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003576
3577 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00003578 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003579 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003580
John McCall176f8922016-11-30 02:39:18 +00003581 enum {
3582 InstanceMethods,
3583 ClassMethods,
3584 NumMethodLists
3585 };
3586 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3587 for (const auto *MD : ID->methods()) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08003588 if (!MD->isDirectMethod())
3589 Methods[unsigned(MD->isClassMethod())].push_back(MD);
John McCall176f8922016-11-30 02:39:18 +00003590 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003591
Aaron Ballmand85eff42014-03-14 15:02:45 +00003592 for (const auto *PID : ID->property_impls()) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003593 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08003594 if (PID->getPropertyDecl()->isDirectProperty())
3595 continue;
Adrian Prantl2073dd22019-11-04 14:28:14 -08003596 if (ObjCMethodDecl *MD = PID->getGetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003597 if (GetMethodDefinition(MD))
3598 Methods[InstanceMethods].push_back(MD);
Adrian Prantl2073dd22019-11-04 14:28:14 -08003599 if (ObjCMethodDecl *MD = PID->getSetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003600 if (GetMethodDefinition(MD))
3601 Methods[InstanceMethods].push_back(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003602 }
3603 }
3604
John McCall176f8922016-11-30 02:39:18 +00003605 ConstantInitBuilder builder(CGM);
3606 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3607 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003608 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003609 // Record a reference to the super class.
3610 LazySymbols.insert(Super->getIdentifier());
3611
John McCall176f8922016-11-30 02:39:18 +00003612 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3613 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003614 } else {
John McCall176f8922016-11-30 02:39:18 +00003615 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003616 }
John McCall176f8922016-11-30 02:39:18 +00003617 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003618 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003619 values.addInt(ObjCTypes.LongTy, 0);
3620 values.addInt(ObjCTypes.LongTy, Flags);
3621 values.addInt(ObjCTypes.LongTy, Size.getQuantity());
3622 values.add(EmitIvarList(ID, false));
3623 values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods,
3624 Methods[InstanceMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003625 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003626 values.addNullPointer(ObjCTypes.CachePtrTy);
3627 values.add(Protocols);
3628 values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size));
3629 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3630 /*isMetaclass*/ false));
3631
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003632 std::string Name("OBJC_CLASS_");
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003633 Name += ClassName;
3634 const char *Section = "__OBJC,__class,regular,no_dead_strip";
3635 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003636 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003637 if (GV) {
3638 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3639 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003640 values.finishAndSetAsInitializer(GV);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003641 GV->setSection(Section);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00003642 GV->setAlignment(CGM.getPointerAlign().getAsAlign());
Rafael Espindola060062a2014-03-06 22:15:10 +00003643 CGM.addCompilerUsedGlobal(GV);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003644 } else
John McCall176f8922016-11-30 02:39:18 +00003645 GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003646 DefinedClasses.push_back(GV);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00003647 ImplementedClasses.push_back(Interface);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003648 // method definition entries must be clear for next implementation.
3649 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003650}
3651
3652llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3653 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00003654 ArrayRef<const ObjCMethodDecl*> Methods) {
John McCallef19dbb2012-10-17 04:53:23 +00003655 unsigned Flags = FragileABI_Class_Meta;
Micah Villmowdd31ca12012-10-08 16:25:52 +00003656 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003657
John McCall457a04e2010-10-22 21:05:15 +00003658 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003659 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003660
John McCall176f8922016-11-30 02:39:18 +00003661 ConstantInitBuilder builder(CGM);
3662 auto values = builder.beginStruct(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003663 // The isa for the metaclass is the root of the hierarchy.
3664 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3665 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3666 Root = Super;
John McCall176f8922016-11-30 02:39:18 +00003667 values.addBitCast(GetClassName(Root->getObjCRuntimeNameAsString()),
3668 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003669 // The super class for the metaclass is emitted as the name of the
3670 // super class. The runtime fixes this up to point to the
3671 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003672 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
John McCall176f8922016-11-30 02:39:18 +00003673 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3674 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003675 } else {
John McCall176f8922016-11-30 02:39:18 +00003676 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003677 }
John McCall176f8922016-11-30 02:39:18 +00003678 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003679 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003680 values.addInt(ObjCTypes.LongTy, 0);
3681 values.addInt(ObjCTypes.LongTy, Flags);
3682 values.addInt(ObjCTypes.LongTy, Size);
3683 values.add(EmitIvarList(ID, true));
3684 values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods,
3685 Methods));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003686 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003687 values.addNullPointer(ObjCTypes.CachePtrTy);
3688 values.add(Protocols);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003689 // ivar_layout for metaclass is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003690 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Renad0e7912016-01-29 19:22:54 +00003691 // The class extension is used to store class properties for metaclasses.
John McCall176f8922016-11-30 02:39:18 +00003692 values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/,
3693 /*isMetaclass*/true));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003694
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003695 std::string Name("OBJC_METACLASS_");
Benjamin Kramer1bbcbd02012-07-31 11:45:39 +00003696 Name += ID->getName();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003697
3698 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003699 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003700 if (GV) {
3701 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3702 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003703 values.finishAndSetAsInitializer(GV);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003704 } else {
John McCall176f8922016-11-30 02:39:18 +00003705 GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
3706 /*constant*/ false,
3707 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003708 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003709 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00003710 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003711
3712 return GV;
3713}
3714
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003715llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003716 std::string Name = "OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003717
Mike Stump18bb9282009-05-16 07:57:57 +00003718 // FIXME: Should we look these up somewhere other than the module. Its a bit
3719 // silly since we only generate these while processing an implementation, so
3720 // exactly one pointer would work if know when we entered/exitted an
3721 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003722
3723 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00003724 // Previously, metaclass with internal linkage may have been defined.
3725 // pass 'true' as 2nd argument so it is returned.
Rafael Espindola21039aa2014-02-27 16:26:32 +00003726 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3727 if (!GV)
3728 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003729 llvm::GlobalValue::PrivateLinkage, nullptr,
3730 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003731
3732 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3733 "Forward metaclass reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003734 return GV;
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003735}
3736
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003737llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003738 std::string Name = "OBJC_CLASS_" + ID->getNameAsString();
Rafael Espindola21039aa2014-02-27 16:26:32 +00003739 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3740
3741 if (!GV)
3742 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003743 llvm::GlobalValue::PrivateLinkage, nullptr,
3744 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003745
3746 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3747 "Forward class metadata reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003748 return GV;
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003749}
3750
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003751/*
John McCall3fd13f062015-10-21 18:06:47 +00003752 Emit a "class extension", which in this specific context means extra
3753 data that doesn't fit in the normal fragile-ABI class structure, and
3754 has nothing to do with the language concept of a class extension.
3755
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003756 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003757 uint32_t size;
3758 const char *weak_ivar_layout;
3759 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003760 };
3761*/
3762llvm::Constant *
John McCall3fd13f062015-10-21 18:06:47 +00003763CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
Manman Renad0e7912016-01-29 19:22:54 +00003764 CharUnits InstanceSize, bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00003765 bool isMetaclass) {
3766 // Weak ivar layout.
3767 llvm::Constant *layout;
3768 if (isMetaclass) {
3769 layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
3770 } else {
3771 layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
3772 hasMRCWeakIvars);
3773 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003774
John McCall176f8922016-11-30 02:39:18 +00003775 // Properties.
3776 llvm::Constant *propertyList =
Akira Hatanaka187770d2019-05-09 17:43:52 +00003777 EmitPropertyList((isMetaclass ? Twine("_OBJC_$_CLASS_PROP_LIST_")
3778 : Twine("_OBJC_$_PROP_LIST_"))
John McCall176f8922016-11-30 02:39:18 +00003779 + ID->getName(),
3780 ID, ID->getClassInterface(), ObjCTypes, isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003781
3782 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00003783 if (layout->isNullValue() && propertyList->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003784 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003785 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003786
John McCall176f8922016-11-30 02:39:18 +00003787 uint64_t size =
3788 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3789
3790 ConstantInitBuilder builder(CGM);
3791 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3792 values.addInt(ObjCTypes.IntTy, size);
3793 values.add(layout);
3794 values.add(propertyList);
3795
3796 return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00003797 "__OBJC,__class_ext,regular,no_dead_strip",
3798 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003799}
3800
3801/*
3802 struct objc_ivar {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003803 char *ivar_name;
3804 char *ivar_type;
3805 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003806 };
3807
3808 struct objc_ivar_list {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003809 int ivar_count;
3810 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003811 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003812*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003813llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003814 bool ForClass) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003815 // When emitting the root class GCC emits ivar entries for the
3816 // actual class structure. It is not clear if we need to follow this
3817 // behavior; for now lets try and get away with not doing it. If so,
3818 // the cleanest solution would be to make up an ObjCInterfaceDecl
3819 // for the class.
3820 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00003821 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003822
Jordy Rosea91768e2011-07-22 02:08:32 +00003823 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003824
John McCall176f8922016-11-30 02:39:18 +00003825 ConstantInitBuilder builder(CGM);
3826 auto ivarList = builder.beginStruct();
3827 auto countSlot = ivarList.addPlaceholder();
3828 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3829
Fangrui Song6907ce22018-07-30 19:24:48 +00003830 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00003831 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00003832 // Ignore unnamed bit-fields.
3833 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003834 continue;
John McCall176f8922016-11-30 02:39:18 +00003835
3836 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3837 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3838 ivar.add(GetMethodVarType(IVD));
3839 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3840 ivar.finishAndAddTo(ivars);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003841 }
3842
3843 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00003844 auto count = ivars.size();
3845 if (count == 0) {
3846 ivars.abandon();
3847 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00003848 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003849 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003850
John McCall176f8922016-11-30 02:39:18 +00003851 ivars.finishAndAddTo(ivarList);
3852 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003853
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003854 llvm::GlobalVariable *GV;
3855 if (ForClass)
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003856 GV =
John McCall176f8922016-11-30 02:39:18 +00003857 CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003858 "__OBJC,__class_vars,regular,no_dead_strip",
3859 CGM.getPointerAlign(), true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003860 else
John McCall176f8922016-11-30 02:39:18 +00003861 GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003862 "__OBJC,__instance_vars,regular,no_dead_strip",
3863 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003864 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003865}
3866
John McCall176f8922016-11-30 02:39:18 +00003867/// Build a struct objc_method_description constant for the given method.
3868///
3869/// struct objc_method_description {
3870/// SEL method_name;
3871/// char *method_types;
3872/// };
3873void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
3874 const ObjCMethodDecl *MD) {
3875 auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy);
3876 description.addBitCast(GetMethodVarName(MD->getSelector()),
3877 ObjCTypes.SelectorPtrTy);
3878 description.add(GetMethodVarType(MD));
3879 description.finishAndAddTo(builder);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003880}
3881
John McCall176f8922016-11-30 02:39:18 +00003882/// Build a struct objc_method constant for the given method.
3883///
3884/// struct objc_method {
3885/// SEL method_name;
3886/// char *method_types;
3887/// void *method;
3888/// };
3889void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
3890 const ObjCMethodDecl *MD) {
3891 llvm::Function *fn = GetMethodDefinition(MD);
3892 assert(fn && "no definition registered for method");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003893
John McCall176f8922016-11-30 02:39:18 +00003894 auto method = builder.beginStruct(ObjCTypes.MethodTy);
3895 method.addBitCast(GetMethodVarName(MD->getSelector()),
3896 ObjCTypes.SelectorPtrTy);
3897 method.add(GetMethodVarType(MD));
3898 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
3899 method.finishAndAddTo(builder);
3900}
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003901
John McCall176f8922016-11-30 02:39:18 +00003902/// Build a struct objc_method_list or struct objc_method_description_list,
3903/// as appropriate.
3904///
3905/// struct objc_method_list {
3906/// struct objc_method_list *obsolete;
3907/// int count;
3908/// struct objc_method methods_list[count];
3909/// };
3910///
3911/// struct objc_method_description_list {
3912/// int count;
3913/// struct objc_method_description list[count];
3914/// };
Zachary Turner41a9ee92017-10-11 23:54:34 +00003915llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3916 ArrayRef<const ObjCMethodDecl *> methods) {
John McCall176f8922016-11-30 02:39:18 +00003917 StringRef prefix;
3918 StringRef section;
3919 bool forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003920 switch (MLT) {
3921 case MethodListType::CategoryInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003922 prefix = "OBJC_CATEGORY_INSTANCE_METHODS_";
3923 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3924 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003925 break;
3926 case MethodListType::CategoryClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003927 prefix = "OBJC_CATEGORY_CLASS_METHODS_";
3928 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3929 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003930 break;
3931 case MethodListType::InstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003932 prefix = "OBJC_INSTANCE_METHODS_";
3933 section = "__OBJC,__inst_meth,regular,no_dead_strip";
3934 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003935 break;
3936 case MethodListType::ClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003937 prefix = "OBJC_CLASS_METHODS_";
3938 section = "__OBJC,__cls_meth,regular,no_dead_strip";
3939 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003940 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003941 case MethodListType::ProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003942 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_";
3943 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3944 forProtocol = true;
3945 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003946 case MethodListType::ProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003947 prefix = "OBJC_PROTOCOL_CLASS_METHODS_";
3948 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3949 forProtocol = true;
3950 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003951 case MethodListType::OptionalProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003952 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3953 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3954 forProtocol = true;
3955 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003956 case MethodListType::OptionalProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003957 prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3958 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3959 forProtocol = true;
3960 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003961 }
3962
John McCall176f8922016-11-30 02:39:18 +00003963 // Return null for empty list.
3964 if (methods.empty())
3965 return llvm::Constant::getNullValue(forProtocol
3966 ? ObjCTypes.MethodDescriptionListPtrTy
3967 : ObjCTypes.MethodListPtrTy);
3968
3969 // For protocols, this is an objc_method_description_list, which has
3970 // a slightly different structure.
3971 if (forProtocol) {
3972 ConstantInitBuilder builder(CGM);
3973 auto values = builder.beginStruct();
3974 values.addInt(ObjCTypes.IntTy, methods.size());
3975 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3976 for (auto MD : methods) {
3977 emitMethodDescriptionConstant(methodArray, MD);
3978 }
3979 methodArray.finishAndAddTo(values);
3980
Zachary Turner41a9ee92017-10-11 23:54:34 +00003981 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
John McCall176f8922016-11-30 02:39:18 +00003982 CGM.getPointerAlign(), true);
3983 return llvm::ConstantExpr::getBitCast(GV,
3984 ObjCTypes.MethodDescriptionListPtrTy);
3985 }
3986
3987 // Otherwise, it's an objc_method_list.
3988 ConstantInitBuilder builder(CGM);
3989 auto values = builder.beginStruct();
3990 values.addNullPointer(ObjCTypes.Int8PtrTy);
3991 values.addInt(ObjCTypes.IntTy, methods.size());
3992 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3993 for (auto MD : methods) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08003994 if (!MD->isDirectMethod())
3995 emitMethodConstant(methodArray, MD);
John McCall176f8922016-11-30 02:39:18 +00003996 }
3997 methodArray.finishAndAddTo(values);
3998
Zachary Turner41a9ee92017-10-11 23:54:34 +00003999 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00004000 CGM.getPointerAlign(), true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00004001 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004002}
4003
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004004llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004005 const ObjCContainerDecl *CD) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08004006 llvm::Function *Method;
4007
4008 if (OMD->isDirectMethod()) {
4009 Method = GenerateDirectMethod(OMD, CD);
4010 } else {
4011 SmallString<256> Name;
4012 GetNameForMethod(OMD, CD, Name);
4013
4014 CodeGenTypes &Types = CGM.getTypes();
4015 llvm::FunctionType *MethodTy =
4016 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
4017 Method =
4018 llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage,
4019 Name.str(), &CGM.getModule());
4020 }
4021
4022 MethodDefinitions.insert(std::make_pair(OMD, Method));
4023
4024 return Method;
4025}
4026
4027llvm::Function *
4028CGObjCCommonMac::GenerateDirectMethod(const ObjCMethodDecl *OMD,
4029 const ObjCContainerDecl *CD) {
4030 auto I = DirectMethodDefinitions.find(OMD);
4031 if (I != DirectMethodDefinitions.end())
4032 return I->second;
4033
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00004034 SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00004035 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004036
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00004037 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00004038 llvm::FunctionType *MethodTy =
John McCalla729c622012-02-17 03:33:10 +00004039 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004040 llvm::Function *Method =
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08004041 llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4042 Name.str(), &CGM.getModule());
4043 DirectMethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004044
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004045 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00004046}
4047
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08004048void CGObjCCommonMac::GenerateDirectMethodPrologue(
4049 CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD,
4050 const ObjCContainerDecl *CD) {
4051 auto &Builder = CGF.Builder;
4052 bool ReceiverCanBeNull = true;
4053 auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl());
4054 auto selfValue = Builder.CreateLoad(selfAddr);
4055
4056 // Generate:
4057 //
4058 // /* for class methods only to force class lazy initialization */
4059 // self = [self self];
4060 //
4061 // /* unless the receiver is never NULL */
4062 // if (self == nil) {
4063 // return (ReturnType){ };
4064 // }
4065 //
4066 // _cmd = @selector(...)
4067 // ...
4068
4069 if (OMD->isClassMethod()) {
4070 const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);
4071 assert(OID &&
4072 "GenerateDirectMethod() should be called with the Class Interface");
4073 Selector SelfSel = GetNullarySelector("self", CGM.getContext());
4074 auto ResultType = CGF.getContext().getObjCIdType();
4075 RValue result;
4076 CallArgList Args;
4077
4078 // TODO: If this method is inlined, the caller might know that `self` is
4079 // already initialized; for example, it might be an ordinary Objective-C
4080 // method which always receives an initialized `self`, or it might have just
4081 // forced initialization on its own.
4082 //
4083 // We should find a way to eliminate this unnecessary initialization in such
4084 // cases in LLVM.
4085 result = GeneratePossiblySpecializedMessageSend(
4086 CGF, ReturnValueSlot(), ResultType, SelfSel, selfValue, Args, OID,
4087 nullptr, true);
4088 Builder.CreateStore(result.getScalarVal(), selfAddr);
4089
4090 // Nullable `Class` expressions cannot be messaged with a direct method
4091 // so the only reason why the receive can be null would be because
4092 // of weak linking.
4093 ReceiverCanBeNull = isWeakLinkedClass(OID);
4094 }
4095
4096 if (ReceiverCanBeNull) {
4097 llvm::BasicBlock *SelfIsNilBlock =
4098 CGF.createBasicBlock("objc_direct_method.self_is_nil");
4099 llvm::BasicBlock *ContBlock =
4100 CGF.createBasicBlock("objc_direct_method.cont");
4101
4102 // if (self == nil) {
4103 auto selfTy = cast<llvm::PointerType>(selfValue->getType());
4104 auto Zero = llvm::ConstantPointerNull::get(selfTy);
4105
4106 llvm::MDBuilder MDHelper(CGM.getLLVMContext());
4107 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock,
4108 ContBlock, MDHelper.createBranchWeights(1, 1 << 20));
4109
4110 CGF.EmitBlock(SelfIsNilBlock);
4111
4112 // return (ReturnType){ };
4113 auto retTy = OMD->getReturnType();
4114 Builder.SetInsertPoint(SelfIsNilBlock);
4115 if (!retTy->isVoidType()) {
4116 CGF.EmitNullInitialization(CGF.ReturnValue, retTy);
4117 }
4118 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
4119 // }
4120
4121 // rest of the body
4122 CGF.EmitBlock(ContBlock);
4123 Builder.SetInsertPoint(ContBlock);
4124 }
4125
4126 // only synthesize _cmd if it's referenced
4127 if (OMD->getCmdDecl()->isUsed()) {
4128 Builder.CreateStore(GetSelector(CGF, OMD),
4129 CGF.GetAddrOfLocalVar(OMD->getCmdDecl()));
4130 }
4131}
4132
Zachary Turner41a9ee92017-10-11 23:54:34 +00004133llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4134 ConstantStructBuilder &Init,
4135 StringRef Section,
4136 CharUnits Align,
4137 bool AddToUsed) {
Akira Hatanaka187770d2019-05-09 17:43:52 +00004138 llvm::GlobalValue::LinkageTypes LT =
4139 getLinkageTypeForObjCMetadata(CGM, Section);
John McCall176f8922016-11-30 02:39:18 +00004140 llvm::GlobalVariable *GV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00004141 Init.finishAndCreateGlobal(Name, Align, /*constant*/ false, LT);
John McCall176f8922016-11-30 02:39:18 +00004142 if (!Section.empty())
4143 GV->setSection(Section);
4144 if (AddToUsed)
4145 CGM.addCompilerUsedGlobal(GV);
4146 return GV;
4147}
4148
Zachary Turner41a9ee92017-10-11 23:54:34 +00004149llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
Alp Toker541d5072014-06-07 23:30:53 +00004150 llvm::Constant *Init,
4151 StringRef Section,
John McCall7f416cc2015-09-08 08:05:57 +00004152 CharUnits Align,
Alp Toker541d5072014-06-07 23:30:53 +00004153 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004154 llvm::Type *Ty = Init->getType();
Akira Hatanaka187770d2019-05-09 17:43:52 +00004155 llvm::GlobalValue::LinkageTypes LT =
4156 getLinkageTypeForObjCMetadata(CGM, Section);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004157 llvm::GlobalVariable *GV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00004158 new llvm::GlobalVariable(CGM.getModule(), Ty, false, LT, Init, Name);
Alp Toker541d5072014-06-07 23:30:53 +00004159 if (!Section.empty())
Daniel Dunbar30c65362009-03-09 20:09:19 +00004160 GV->setSection(Section);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00004161 GV->setAlignment(Align.getAsAlign());
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00004162 if (AddToUsed)
Rafael Espindola060062a2014-03-06 22:15:10 +00004163 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00004164 return GV;
4165}
4166
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004167llvm::GlobalVariable *
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004168CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type,
4169 bool ForceNonFragileABI,
4170 bool NullTerminate) {
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004171 StringRef Label;
4172 switch (Type) {
4173 case ObjCLabelType::ClassName: Label = "OBJC_CLASS_NAME_"; break;
4174 case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break;
4175 case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break;
4176 case ObjCLabelType::PropertyName: Label = "OBJC_PROP_NAME_ATTR_"; break;
4177 }
4178
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004179 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
4180
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004181 StringRef Section;
4182 switch (Type) {
4183 case ObjCLabelType::ClassName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004184 Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals"
4185 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004186 break;
4187 case ObjCLabelType::MethodVarName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004188 Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
4189 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004190 break;
4191 case ObjCLabelType::MethodVarType:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004192 Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals"
4193 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004194 break;
4195 case ObjCLabelType::PropertyName:
4196 Section = "__TEXT,__cstring,cstring_literals";
4197 break;
4198 }
4199
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004200 llvm::Constant *Value =
4201 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004202 llvm::GlobalVariable *GV =
Saleem Abdulrasool0c54dc82016-09-18 16:12:04 +00004203 new llvm::GlobalVariable(CGM.getModule(), Value->getType(),
4204 /*isConstant=*/true,
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004205 llvm::GlobalValue::PrivateLinkage, Value, Label);
Saleem Abdulrasool3f307512016-09-18 16:12:14 +00004206 if (CGM.getTriple().isOSBinFormatMachO())
4207 GV->setSection(Section);
4208 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00004209 GV->setAlignment(CharUnits::One().getAsAlign());
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004210 CGM.addCompilerUsedGlobal(GV);
4211
4212 return GV;
4213}
4214
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004215llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004216 // Abuse this interface function as a place to finalize.
4217 FinishModule();
Craig Topper8a13c412014-05-21 05:09:00 +00004218 return nullptr;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00004219}
4220
James Y Knight9871db02019-02-05 16:42:33 +00004221llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00004222 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00004223}
4224
James Y Knight9871db02019-02-05 16:42:33 +00004225llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00004226 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00004227}
4228
James Y Knight9871db02019-02-05 16:42:33 +00004229llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
4230 bool copy) {
Ted Kremeneke65b0862012-03-06 20:05:56 +00004231 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
4232}
4233
James Y Knight9871db02019-02-05 16:42:33 +00004234llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
David Chisnall168b80f2010-12-26 22:13:16 +00004235 return ObjCTypes.getCopyStructFn();
4236}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004237
James Y Knight9871db02019-02-05 16:42:33 +00004238llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00004239 return ObjCTypes.getCopyStructFn();
4240}
4241
James Y Knight9871db02019-02-05 16:42:33 +00004242llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
David Chisnall0d75e062012-12-17 18:54:24 +00004243 return ObjCTypes.getCppAtomicObjectFunction();
4244}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004245
James Y Knight9871db02019-02-05 16:42:33 +00004246llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00004247 return ObjCTypes.getCppAtomicObjectFunction();
4248}
4249
James Y Knight9871db02019-02-05 16:42:33 +00004250llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00004251 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00004252}
4253
John McCallbd309292010-07-06 01:34:17 +00004254void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
4255 return EmitTryOrSynchronizedStmt(CGF, S);
4256}
4257
4258void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
4259 const ObjCAtSynchronizedStmt &S) {
4260 return EmitTryOrSynchronizedStmt(CGF, S);
4261}
4262
John McCall65bea082010-07-21 06:59:36 +00004263namespace {
David Blaikie7e70d682015-08-18 22:40:54 +00004264 struct PerformFragileFinally final : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00004265 const Stmt &S;
John McCall7f416cc2015-09-08 08:05:57 +00004266 Address SyncArgSlot;
4267 Address CallTryExitVar;
4268 Address ExceptionData;
John McCall65bea082010-07-21 06:59:36 +00004269 ObjCTypesHelper &ObjCTypes;
4270 PerformFragileFinally(const Stmt *S,
John McCall7f416cc2015-09-08 08:05:57 +00004271 Address SyncArgSlot,
4272 Address CallTryExitVar,
4273 Address ExceptionData,
John McCall65bea082010-07-21 06:59:36 +00004274 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00004275 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00004276 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4277
Craig Topper4f12f102014-03-12 06:41:41 +00004278 void Emit(CodeGenFunction &CGF, Flags flags) override {
John McCall65bea082010-07-21 06:59:36 +00004279 // Check whether we need to call objc_exception_try_exit.
4280 // In optimized code, this branch will always be folded.
4281 llvm::BasicBlock *FinallyCallExit =
4282 CGF.createBasicBlock("finally.call_exit");
4283 llvm::BasicBlock *FinallyNoCallExit =
4284 CGF.createBasicBlock("finally.no_call_exit");
4285 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
4286 FinallyCallExit, FinallyNoCallExit);
4287
4288 CGF.EmitBlock(FinallyCallExit);
John McCall882987f2013-02-28 19:01:20 +00004289 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004290 ExceptionData.getPointer());
John McCall65bea082010-07-21 06:59:36 +00004291
4292 CGF.EmitBlock(FinallyNoCallExit);
4293
4294 if (isa<ObjCAtTryStmt>(S)) {
4295 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00004296 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
John McCall638d4f52013-04-03 00:56:07 +00004297 // Don't try to do the @finally if this is an EH cleanup.
4298 if (flags.isForEHCleanup()) return;
4299
John McCallcebe0ca2010-08-11 00:16:14 +00004300 // Save the current cleanup destination in case there's
4301 // control flow inside the finally statement.
4302 llvm::Value *CurCleanupDest =
4303 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
4304
John McCall65bea082010-07-21 06:59:36 +00004305 CGF.EmitStmt(FinallyStmt->getFinallyBody());
4306
John McCallcebe0ca2010-08-11 00:16:14 +00004307 if (CGF.HaveInsertPoint()) {
4308 CGF.Builder.CreateStore(CurCleanupDest,
4309 CGF.getNormalCleanupDestSlot());
4310 } else {
4311 // Currently, the end of the cleanup must always exist.
4312 CGF.EnsureInsertPoint();
4313 }
4314 }
John McCall65bea082010-07-21 06:59:36 +00004315 } else {
4316 // Emit objc_sync_exit(expr); as finally's sole statement for
4317 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00004318 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall882987f2013-02-28 19:01:20 +00004319 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg);
John McCall65bea082010-07-21 06:59:36 +00004320 }
4321 }
4322 };
John McCall42227ed2010-07-31 23:20:56 +00004323
4324 class FragileHazards {
4325 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004326 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00004327 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
4328
4329 llvm::InlineAsm *ReadHazard;
4330 llvm::InlineAsm *WriteHazard;
4331
4332 llvm::FunctionType *GetAsmFnType();
4333
4334 void collectLocals();
4335 void emitReadHazard(CGBuilderTy &Builder);
4336
4337 public:
4338 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00004339
John McCall42227ed2010-07-31 23:20:56 +00004340 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00004341 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004342 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004343} // end anonymous namespace
John McCall42227ed2010-07-31 23:20:56 +00004344
4345/// Create the fragile-ABI read and write hazards based on the current
4346/// state of the function, which is presumed to be immediately prior
4347/// to a @try block. These hazards are used to maintain correct
4348/// semantics in the face of optimization and the fragile ABI's
4349/// cavalier use of setjmp/longjmp.
4350FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
4351 collectLocals();
4352
4353 if (Locals.empty()) return;
4354
4355 // Collect all the blocks in the function.
4356 for (llvm::Function::iterator
4357 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
4358 BlocksBeforeTry.insert(&*I);
4359
4360 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4361
4362 // Create a read hazard for the allocas. This inhibits dead-store
4363 // optimizations and forces the values to memory. This hazard is
4364 // inserted before any 'throwing' calls in the protected scope to
4365 // reflect the possibility that the variables might be read from the
4366 // catch block if the call throws.
4367 {
4368 std::string Constraint;
4369 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
4370 if (I) Constraint += ',';
4371 Constraint += "*m";
4372 }
4373
4374 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
4375 }
4376
4377 // Create a write hazard for the allocas. This inhibits folding
4378 // loads across the hazard. This hazard is inserted at the
4379 // beginning of the catch path to reflect the possibility that the
4380 // variables might have been written within the protected scope.
4381 {
4382 std::string Constraint;
4383 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
4384 if (I) Constraint += ',';
4385 Constraint += "=*m";
4386 }
4387
4388 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
4389 }
4390}
4391
4392/// Emit a write hazard at the current location.
4393void FragileHazards::emitWriteHazard() {
4394 if (Locals.empty()) return;
4395
John McCall882987f2013-02-28 19:01:20 +00004396 CGF.EmitNounwindRuntimeCall(WriteHazard, Locals);
John McCall42227ed2010-07-31 23:20:56 +00004397}
4398
John McCall42227ed2010-07-31 23:20:56 +00004399void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
4400 assert(!Locals.empty());
John McCall882987f2013-02-28 19:01:20 +00004401 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4402 call->setDoesNotThrow();
4403 call->setCallingConv(CGF.getRuntimeCC());
John McCall42227ed2010-07-31 23:20:56 +00004404}
4405
4406/// Emit read hazards in all the protected blocks, i.e. all the blocks
4407/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00004408void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00004409 if (Locals.empty()) return;
4410
John McCall7f416cc2015-09-08 08:05:57 +00004411 CGBuilderTy Builder(CGF, CGF.getLLVMContext());
John McCall42227ed2010-07-31 23:20:56 +00004412
4413 // Iterate through all blocks, skipping those prior to the try.
4414 for (llvm::Function::iterator
4415 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
4416 llvm::BasicBlock &BB = *FI;
4417 if (BlocksBeforeTry.count(&BB)) continue;
4418
4419 // Walk through all the calls in the block.
4420 for (llvm::BasicBlock::iterator
4421 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
4422 llvm::Instruction &I = *BI;
4423
4424 // Ignore instructions that aren't non-intrinsic calls.
4425 // These are the only calls that can possibly call longjmp.
James Y Knight3933add2019-01-30 02:54:28 +00004426 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
4427 continue;
John McCall42227ed2010-07-31 23:20:56 +00004428 if (isa<llvm::IntrinsicInst>(I))
4429 continue;
4430
4431 // Ignore call sites marked nounwind. This may be questionable,
4432 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
James Y Knight3933add2019-01-30 02:54:28 +00004433 if (cast<llvm::CallBase>(I).doesNotThrow())
4434 continue;
John McCall42227ed2010-07-31 23:20:56 +00004435
John McCall2dd7d442010-08-04 05:59:32 +00004436 // Insert a read hazard before the call. This will ensure that
4437 // any writes to the locals are performed before making the
4438 // call. If the call throws, then this is sufficient to
4439 // guarantee correctness as long as it doesn't also write to any
4440 // locals.
John McCall42227ed2010-07-31 23:20:56 +00004441 Builder.SetInsertPoint(&BB, BI);
4442 emitReadHazard(Builder);
4443 }
4444 }
4445}
4446
John McCall7f416cc2015-09-08 08:05:57 +00004447static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) {
4448 if (V.isValid()) S.insert(V.getPointer());
4449}
4450
John McCall42227ed2010-07-31 23:20:56 +00004451void FragileHazards::collectLocals() {
4452 // Compute a set of allocas to ignore.
4453 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
4454 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
4455 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00004456
4457 // Collect all the allocas currently in the function. This is
4458 // probably way too aggressive.
4459 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
4460 for (llvm::BasicBlock::iterator
4461 I = Entry.begin(), E = Entry.end(); I != E; ++I)
4462 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
4463 Locals.push_back(&*I);
4464}
4465
4466llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004467 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00004468 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
4469 tys[i] = Locals[i]->getType();
4470 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00004471}
4472
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004473/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004474
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004475 Objective-C setjmp-longjmp (sjlj) Exception Handling
4476 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004477
John McCallbd309292010-07-06 01:34:17 +00004478 A catch buffer is a setjmp buffer plus:
4479 - a pointer to the exception that was caught
4480 - a pointer to the previous exception data buffer
4481 - two pointers of reserved storage
4482 Therefore catch buffers form a stack, with a pointer to the top
4483 of the stack kept in thread-local storage.
4484
4485 objc_exception_try_enter pushes a catch buffer onto the EH stack.
4486 objc_exception_try_exit pops the given catch buffer, which is
4487 required to be the top of the EH stack.
4488 objc_exception_throw pops the top of the EH stack, writes the
4489 thrown exception into the appropriate field, and longjmps
4490 to the setjmp buffer. It crashes the process (with a printf
4491 and an abort()) if there are no catch buffers on the stack.
4492 objc_exception_extract just reads the exception pointer out of the
4493 catch buffer.
4494
4495 There's no reason an implementation couldn't use a light-weight
4496 setjmp here --- something like __builtin_setjmp, but API-compatible
4497 with the heavyweight setjmp. This will be more important if we ever
4498 want to implement correct ObjC/C++ exception interactions for the
4499 fragile ABI.
4500
4501 Note that for this use of setjmp/longjmp to be correct, we may need
4502 to mark some local variables volatile: if a non-volatile local
4503 variable is modified between the setjmp and the longjmp, it has
4504 indeterminate value. For the purposes of LLVM IR, it may be
4505 sufficient to make loads and stores within the @try (to variables
4506 declared outside the @try) volatile. This is necessary for
4507 optimized correctness, but is not currently being done; this is
4508 being tracked as rdar://problem/8160285
4509
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004510 The basic framework for a @try-catch-finally is as follows:
4511 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004512 objc_exception_data d;
4513 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00004514 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004515
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004516 objc_exception_try_enter(&d);
4517 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004518 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004519 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004520 // exception path
4521 id _caught = objc_exception_extract(&d);
4522
4523 // enter new try scope for handlers
4524 if (!setjmp(d.jmp_buf)) {
4525 ... match exception and execute catch blocks ...
4526
4527 // fell off end, rethrow.
4528 _rethrow = _caught;
4529 ... jump-through-finally to finally_rethrow ...
4530 } else {
4531 // exception in catch block
4532 _rethrow = objc_exception_extract(&d);
4533 _call_try_exit = false;
4534 ... jump-through-finally to finally_rethrow ...
4535 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004536 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004537 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004538
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004539 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00004540 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004541 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00004542
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004543 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004544 ... dispatch to finally destination ...
4545
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004546 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004547 objc_exception_throw(_rethrow);
4548
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004549 finally_end:
4550 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004551
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004552 This framework differs slightly from the one gcc uses, in that gcc
4553 uses _rethrow to determine if objc_exception_try_exit should be called
4554 and if the object should be rethrown. This breaks in the face of
4555 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004556
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004557 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004558
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004559 - If there are no catch blocks, then we avoid emitting the second
4560 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004561
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004562 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
4563 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004564
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004565 - FIXME: If there is no @finally block we can do a few more
4566 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004567
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004568 Rethrows and Jumps-Through-Finally
4569 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004570
John McCallbd309292010-07-06 01:34:17 +00004571 '@throw;' is supported by pushing the currently-caught exception
4572 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004573
John McCallbd309292010-07-06 01:34:17 +00004574 Branches through the @finally block are handled with an ordinary
4575 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
4576 exceptions are not compatible with C++ exceptions, and this is
4577 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004578
John McCallbd309292010-07-06 01:34:17 +00004579 @synchronized(expr) { stmt; } is emitted as if it were:
4580 id synch_value = expr;
4581 objc_sync_enter(synch_value);
4582 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004583*/
4584
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00004585void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
4586 const Stmt &S) {
4587 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00004588
4589 // A destination for the fall-through edges of the catch handlers to
4590 // jump to.
4591 CodeGenFunction::JumpDest FinallyEnd =
4592 CGF.getJumpDestInCurrentScope("finally.end");
4593
4594 // A destination for the rethrow edge of the catch handlers to jump
4595 // to.
4596 CodeGenFunction::JumpDest FinallyRethrow =
4597 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004598
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004599 // For @synchronized, call objc_sync_enter(sync.expr). The
4600 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00004601 // @synchronized. We can't avoid a temp here because we need the
4602 // value to be preserved. If the backend ever does liveness
4603 // correctly after setjmp, this will be unnecessary.
John McCall7f416cc2015-09-08 08:05:57 +00004604 Address SyncArgSlot = Address::invalid();
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004605 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00004606 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004607 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4608 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004609 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);
John McCall2dd7d442010-08-04 05:59:32 +00004610
John McCall7f416cc2015-09-08 08:05:57 +00004611 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(),
4612 CGF.getPointerAlign(), "sync.arg");
John McCall2dd7d442010-08-04 05:59:32 +00004613 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004614 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004615
John McCall2dd7d442010-08-04 05:59:32 +00004616 // Allocate memory for the setjmp buffer. This needs to be kept
4617 // live throughout the try and catch blocks.
John McCall7f416cc2015-09-08 08:05:57 +00004618 Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
4619 CGF.getPointerAlign(),
4620 "exceptiondata.ptr");
John McCall2dd7d442010-08-04 05:59:32 +00004621
John McCall42227ed2010-07-31 23:20:56 +00004622 // Create the fragile hazards. Note that this will not capture any
4623 // of the allocas required for exception processing, but will
4624 // capture the current basic block (which extends all the way to the
4625 // setjmp call) as "before the @try".
4626 FragileHazards Hazards(CGF);
4627
John McCallbd309292010-07-06 01:34:17 +00004628 // Create a flag indicating whether the cleanup needs to call
4629 // objc_exception_try_exit. This is true except when
4630 // - no catches match and we're branching through the cleanup
4631 // just to rethrow the exception, or
4632 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00004633 // The setjmp-safety rule here is that we should always store to this
4634 // variable in a place that dominates the branch through the cleanup
4635 // without passing through any setjmps.
John McCall7f416cc2015-09-08 08:05:57 +00004636 Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
4637 CharUnits::One(),
4638 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004639
John McCall9916e3f2010-10-04 23:42:51 +00004640 // A slot containing the exception to rethrow. Only needed when we
4641 // have both a @catch and a @finally.
John McCall7f416cc2015-09-08 08:05:57 +00004642 Address PropagatingExnVar = Address::invalid();
John McCall9916e3f2010-10-04 23:42:51 +00004643
John McCallbd309292010-07-06 01:34:17 +00004644 // Push a normal cleanup to leave the try scope.
John McCall638d4f52013-04-03 00:56:07 +00004645 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00004646 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00004647 CallTryExitVar,
4648 ExceptionData,
4649 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00004650
4651 // Enter a try block:
4652 // - Call objc_exception_try_enter to push ExceptionData on top of
4653 // the EH stack.
Nico Weber6307cf02015-02-26 20:43:00 +00004654 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004655 ExceptionData.getPointer());
John McCallbd309292010-07-06 01:34:17 +00004656
4657 // - Call setjmp on the exception data buffer.
4658 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
4659 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
David Blaikie6b2a8302015-04-03 17:47:16 +00004660 llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
John McCall7f416cc2015-09-08 08:05:57 +00004661 ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes,
4662 "setjmp_buffer");
Nico Weber6307cf02015-02-26 20:43:00 +00004663 llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
4664 ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004665 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00004666
4667 // If setjmp returned 0, enter the protected block; otherwise,
4668 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00004669 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
4670 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00004671 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00004672 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4673 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004674
John McCallbd309292010-07-06 01:34:17 +00004675 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004676 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00004677 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004678 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00004679 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00004680
4681 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004682
John McCallbd309292010-07-06 01:34:17 +00004683 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00004684 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004685
John McCall42227ed2010-07-31 23:20:56 +00004686 // Don't optimize loads of the in-scope locals across this point.
4687 Hazards.emitWriteHazard();
4688
John McCallbd309292010-07-06 01:34:17 +00004689 // For a @synchronized (or a @try with no catches), just branch
4690 // through the cleanup to the rethrow block.
4691 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4692 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00004693 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004694 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00004695
4696 // Otherwise, we have to match against the caught exceptions.
4697 } else {
John McCall2dd7d442010-08-04 05:59:32 +00004698 // Retrieve the exception object. We may emit multiple blocks but
4699 // nothing can cross this so the value is already in SSA form.
4700 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004701 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004702 ExceptionData.getPointer(), "caught");
John McCall2dd7d442010-08-04 05:59:32 +00004703
John McCallbd309292010-07-06 01:34:17 +00004704 // Push the exception to rethrow onto the EH value stack for the
4705 // benefit of any @throws in the handlers.
4706 CGF.ObjCEHValueStack.push_back(Caught);
4707
Douglas Gregor96c79492010-04-23 22:50:49 +00004708 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004709
Craig Topper8a13c412014-05-21 05:09:00 +00004710 bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr);
John McCallbd309292010-07-06 01:34:17 +00004711
Craig Topper8a13c412014-05-21 05:09:00 +00004712 llvm::BasicBlock *CatchBlock = nullptr;
4713 llvm::BasicBlock *CatchHandler = nullptr;
John McCall2dd7d442010-08-04 05:59:32 +00004714 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00004715 // Save the currently-propagating exception before
4716 // objc_exception_try_enter clears the exception slot.
4717 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
John McCall7f416cc2015-09-08 08:05:57 +00004718 CGF.getPointerAlign(),
John McCall9916e3f2010-10-04 23:42:51 +00004719 "propagating_exception");
4720 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
4721
John McCall2dd7d442010-08-04 05:59:32 +00004722 // Enter a new exception try block (in case a @catch block
4723 // throws an exception).
John McCall882987f2013-02-28 19:01:20 +00004724 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004725 ExceptionData.getPointer());
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004726
John McCall2dd7d442010-08-04 05:59:32 +00004727 llvm::CallInst *SetJmpResult =
John McCall882987f2013-02-28 19:01:20 +00004728 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(),
4729 SetJmpBuffer, "setjmp.result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004730 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004731
John McCall2dd7d442010-08-04 05:59:32 +00004732 llvm::Value *Threw =
4733 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4734
4735 CatchBlock = CGF.createBasicBlock("catch");
4736 CatchHandler = CGF.createBasicBlock("catch_for_catch");
4737 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4738
4739 CGF.EmitBlock(CatchBlock);
4740 }
4741
4742 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004743
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004744 // Handle catch list. As a special case we check if everything is
4745 // matched and avoid generating code for falling off the end if
4746 // so.
4747 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00004748 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
4749 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004750
Douglas Gregor46a572b2010-04-26 16:46:50 +00004751 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Craig Topper8a13c412014-05-21 05:09:00 +00004752 const ObjCObjectPointerType *OPT = nullptr;
Daniel Dunbar523208f2008-09-27 07:36:24 +00004753
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004754 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004755 if (!CatchParam) {
4756 AllMatched = true;
4757 } else {
John McCall9dd450b2009-09-21 23:43:11 +00004758 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004759
John McCallbd309292010-07-06 01:34:17 +00004760 // catch(id e) always matches under this ABI, since only
4761 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00004762 // FIXME: For the time being we also match id<X>; this should
4763 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00004764 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004765 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004766 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004767
John McCallbd309292010-07-06 01:34:17 +00004768 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004769 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00004770 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4771
Anders Carlsson9396a892008-09-11 09:15:33 +00004772 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00004773 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004774 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00004775
4776 // These types work out because ConvertType(id) == i8*.
John McCall17f02752015-10-30 00:56:02 +00004777 EmitInitOfCatchParam(CGF, Caught, CatchParam);
Anders Carlsson9396a892008-09-11 09:15:33 +00004778 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004779
Anders Carlsson9396a892008-09-11 09:15:33 +00004780 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004781
4782 // The scope of the catch variable ends right here.
4783 CatchVarCleanups.ForceCleanup();
4784
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004785 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004786 break;
4787 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004788
Steve Naroff7cae42b2009-07-10 23:34:53 +00004789 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00004790 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00004791
4792 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00004793 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
4794 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004795
4796 // Check if the @catch block matches the exception object.
John McCall882987f2013-02-28 19:01:20 +00004797 llvm::Value *Class = EmitClassRef(CGF, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004798
John McCall882987f2013-02-28 19:01:20 +00004799 llvm::Value *matchArgs[] = { Class, Caught };
John McCallbd309292010-07-06 01:34:17 +00004800 llvm::CallInst *Match =
John McCall882987f2013-02-28 19:01:20 +00004801 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(),
4802 matchArgs, "match");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004803
John McCallbd309292010-07-06 01:34:17 +00004804 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
4805 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004806
4807 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00004808 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004809
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004810 // Emit the @catch block.
4811 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00004812
4813 // Collect any cleanups for the catch variable. The scope lasts until
4814 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00004815 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00004816
John McCall1c9c3fd2010-10-15 04:57:14 +00004817 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004818 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004819
John McCallbd309292010-07-06 01:34:17 +00004820 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004821 llvm::Value *Tmp =
4822 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004823 CGF.ConvertType(CatchParam->getType()));
John McCall17f02752015-10-30 00:56:02 +00004824 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004825
Anders Carlsson9396a892008-09-11 09:15:33 +00004826 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004827
4828 // We're done with the catch variable.
4829 CatchVarCleanups.ForceCleanup();
4830
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004831 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004832
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004833 CGF.EmitBlock(NextCatchBlock);
4834 }
4835
John McCallbd309292010-07-06 01:34:17 +00004836 CGF.ObjCEHValueStack.pop_back();
4837
John McCall2dd7d442010-08-04 05:59:32 +00004838 // If nothing wanted anything to do with the caught exception,
4839 // kill the extract call.
4840 if (Caught->use_empty())
4841 Caught->eraseFromParent();
4842
4843 if (!AllMatched)
4844 CGF.EmitBranchThroughCleanup(FinallyRethrow);
4845
4846 if (HasFinally) {
4847 // Emit the exception handler for the @catch blocks.
4848 CGF.EmitBlock(CatchHandler);
4849
4850 // In theory we might now need a write hazard, but actually it's
4851 // unnecessary because there's no local-accessing code between
4852 // the try's write hazard and here.
4853 //Hazards.emitWriteHazard();
4854
John McCall9916e3f2010-10-04 23:42:51 +00004855 // Extract the new exception and save it to the
4856 // propagating-exception slot.
John McCall7f416cc2015-09-08 08:05:57 +00004857 assert(PropagatingExnVar.isValid());
John McCall9916e3f2010-10-04 23:42:51 +00004858 llvm::CallInst *NewCaught =
John McCall882987f2013-02-28 19:01:20 +00004859 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004860 ExceptionData.getPointer(), "caught");
John McCall9916e3f2010-10-04 23:42:51 +00004861 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4862
John McCall2dd7d442010-08-04 05:59:32 +00004863 // Don't pop the catch handler; the throw already did.
4864 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004865 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004866 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004867 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004868
John McCall42227ed2010-07-31 23:20:56 +00004869 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00004870 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004871
John McCallbd309292010-07-06 01:34:17 +00004872 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00004873 CGF.Builder.restoreIP(TryFallthroughIP);
4874 if (CGF.HaveInsertPoint())
4875 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00004876 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00004877 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004878
John McCallbd309292010-07-06 01:34:17 +00004879 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00004880 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00004881 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00004882 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00004883 // If we have a propagating-exception variable, check it.
4884 llvm::Value *PropagatingExn;
John McCall7f416cc2015-09-08 08:05:57 +00004885 if (PropagatingExnVar.isValid()) {
John McCall9916e3f2010-10-04 23:42:51 +00004886 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00004887
John McCall9916e3f2010-10-04 23:42:51 +00004888 // Otherwise, just look in the buffer for the exception to throw.
4889 } else {
4890 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004891 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004892 ExceptionData.getPointer());
John McCall9916e3f2010-10-04 23:42:51 +00004893 PropagatingExn = Caught;
4894 }
4895
John McCall882987f2013-02-28 19:01:20 +00004896 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(),
4897 PropagatingExn);
John McCallbd309292010-07-06 01:34:17 +00004898 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00004899 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004900
John McCall42227ed2010-07-31 23:20:56 +00004901 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004902}
4903
4904void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004905 const ObjCAtThrowStmt &S,
4906 bool ClearInsertionPoint) {
Anders Carlssone005aa12008-09-09 16:16:55 +00004907 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004908
Anders Carlssone005aa12008-09-09 16:16:55 +00004909 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00004910 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004911 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004912 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00004913 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004914 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004915 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00004916 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00004917 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004918
John McCall882987f2013-02-28 19:01:20 +00004919 CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
John McCallbd309292010-07-06 01:34:17 +00004920 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004921 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004922
4923 // Clear the insertion point to indicate we are in unreachable code.
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004924 if (ClearInsertionPoint)
4925 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004926}
4927
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004928/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004929/// object: objc_read_weak (id *src)
4930///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004931llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004932 Address AddrWeakObj) {
4933 llvm::Type* DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004934 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4935 ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004936 llvm::Value *read_weak =
4937 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004938 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00004939 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004940 return read_weak;
4941}
4942
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004943/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4944/// objc_assign_weak (id src, id *dst)
4945///
4946void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004947 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004948 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004949 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004950 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004951 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004952 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4953 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004954 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4955 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004956 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4957 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004958 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00004959 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4960 args, "weakassign");
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004961}
4962
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004963/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4964/// objc_assign_global (id src, id *dst)
4965///
4966void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004967 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00004968 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004969 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004970 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004971 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004972 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004973 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4974 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004975 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4976 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004977 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4978 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004979 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00004980 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00004981 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4982 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00004983 else
John McCall882987f2013-02-28 19:01:20 +00004984 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4985 args, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004986}
4987
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004988/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004989/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004990///
4991void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004992 llvm::Value *src, Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004993 llvm::Value *ivarOffset) {
4994 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00004995 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004996 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004997 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004998 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004999 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
5000 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005001 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5002 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00005003 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5004 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00005005 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00005006 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00005007}
5008
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00005009/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5010/// objc_assign_strongCast (id src, id *dst)
5011///
5012void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00005013 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00005014 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005015 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00005016 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005017 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00005018 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
5019 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005020 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5021 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00005022 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5023 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00005024 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00005025 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
John McCall7f416cc2015-09-08 08:05:57 +00005026 args, "strongassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00005027}
5028
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005029void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00005030 Address DestPtr,
5031 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00005032 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005033 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5034 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00005035 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size };
John McCall882987f2013-02-28 19:01:20 +00005036 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005037}
5038
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00005039/// EmitObjCValueForIvar - Code Gen for ivar reference.
5040///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00005041LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
5042 QualType ObjectTy,
5043 llvm::Value *BaseValue,
5044 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00005045 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00005046 const ObjCInterfaceDecl *ID =
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00005047 ObjectTy->castAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00005048 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5049 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00005050}
5051
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005052llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00005053 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005054 const ObjCIvarDecl *Ivar) {
Eli Friedman8cbca202012-11-06 22:15:52 +00005055 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
5056 return llvm::ConstantInt::get(
5057 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
5058 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005059}
5060
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005061/* *** Private Interface *** */
5062
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005063std::string CGObjCCommonMac::GetSectionName(StringRef Section,
5064 StringRef MachOAttributes) {
5065 switch (CGM.getTriple().getObjectFormat()) {
Hubert Tong53a83b72019-07-04 21:40:28 +00005066 case llvm::Triple::UnknownObjectFormat:
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005067 llvm_unreachable("unexpected object file format");
5068 case llvm::Triple::MachO: {
5069 if (MachOAttributes.empty())
5070 return ("__DATA," + Section).str();
5071 return ("__DATA," + Section + "," + MachOAttributes).str();
5072 }
5073 case llvm::Triple::ELF:
5074 assert(Section.substr(0, 2) == "__" &&
5075 "expected the name to begin with __");
5076 return Section.substr(2).str();
5077 case llvm::Triple::COFF:
5078 assert(Section.substr(0, 2) == "__" &&
5079 "expected the name to begin with __");
5080 return ("." + Section.substr(2) + "$B").str();
Hubert Tong53a83b72019-07-04 21:40:28 +00005081 case llvm::Triple::Wasm:
5082 case llvm::Triple::XCOFF:
5083 llvm::report_fatal_error(
5084 "Objective-C support is unimplemented for object file format.");
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005085 }
Mikael Holmenc72cb1f2019-07-05 06:12:24 +00005086
5087 llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType enum");
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005088}
5089
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005090/// EmitImageInfo - Emit the image info marker used to encode some module
5091/// level information.
5092///
5093/// See: <rdr://4810609&4810587&4810587>
5094/// struct IMAGE_INFO {
5095/// unsigned version;
5096/// unsigned flags;
5097/// };
5098enum ImageInfoFlags {
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00005099 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005100 eImageInfo_GarbageCollected = (1 << 1),
5101 eImageInfo_GCOnly = (1 << 2),
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00005102 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
Daniel Dunbar75e909f2009-04-20 07:11:47 +00005103
Daniel Dunbar5e639272010-04-25 20:39:01 +00005104 // A flag indicating that the module has no instances of a @synthesize of a
5105 // superclass variable. <rdar://problem/6803242>
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00005106 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
Manman Ren96df0b32016-01-29 23:45:01 +00005107 eImageInfo_ImageIsSimulated = (1 << 5),
5108 eImageInfo_ClassProperties = (1 << 6)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005109};
5110
Daniel Dunbar5e639272010-04-25 20:39:01 +00005111void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005112 unsigned version = 0; // Version is unused?
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005113 std::string Section =
5114 (ObjCABI == 1)
5115 ? "__OBJC,__image_info,regular"
5116 : GetSectionName("__objc_imageinfo", "regular,no_dead_strip");
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005117
Bill Wendlingb6f795e2012-02-16 01:13:30 +00005118 // Generate module-level named metadata to convey this information to the
5119 // linker and code-gen.
5120 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005121
Bill Wendlingb6f795e2012-02-16 01:13:30 +00005122 // Add the ObjC ABI version to the module flags.
5123 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
5124 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
5125 version);
5126 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005127 llvm::MDString::get(VMContext, Section));
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005128
David Blaikiebbafb8a2012-03-11 07:00:24 +00005129 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00005130 // Non-GC overrides those files which specify GC.
5131 Mod.addModuleFlag(llvm::Module::Override,
5132 "Objective-C Garbage Collection", (uint32_t)0);
5133 } else {
5134 // Add the ObjC garbage collection value.
5135 Mod.addModuleFlag(llvm::Module::Error,
5136 "Objective-C Garbage Collection",
5137 eImageInfo_GarbageCollected);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005138
David Blaikiebbafb8a2012-03-11 07:00:24 +00005139 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00005140 // Add the ObjC GC Only value.
5141 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
5142 eImageInfo_GCOnly);
5143
5144 // Require that GC be specified and set to eImageInfo_GarbageCollected.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +00005145 llvm::Metadata *Ops[2] = {
5146 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
5147 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
5148 llvm::Type::getInt32Ty(VMContext), eImageInfo_GarbageCollected))};
Bill Wendlingb6f795e2012-02-16 01:13:30 +00005149 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
5150 llvm::MDNode::get(VMContext, Ops));
5151 }
5152 }
Bill Wendling1e60a2c2012-04-24 11:04:57 +00005153
5154 // Indicate whether we're compiling this to run on a simulator.
Alex Lorenz6cdef0e2017-12-07 19:04:10 +00005155 if (CGM.getTarget().getTriple().isSimulatorEnvironment())
Bill Wendling1e60a2c2012-04-24 11:04:57 +00005156 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
5157 eImageInfo_ImageIsSimulated);
Manman Ren96df0b32016-01-29 23:45:01 +00005158
5159 // Indicate whether we are generating class properties.
5160 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Class Properties",
5161 eImageInfo_ClassProperties);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005162}
5163
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005164// struct objc_module {
5165// unsigned long version;
5166// unsigned long size;
5167// const char *name;
5168// Symtab symtab;
5169// };
5170
5171// FIXME: Get from somewhere
5172static const int ModuleVersion = 7;
5173
5174void CGObjCMac::EmitModuleInfo() {
Micah Villmowdd31ca12012-10-08 16:25:52 +00005175 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005176
John McCall176f8922016-11-30 02:39:18 +00005177 ConstantInitBuilder builder(CGM);
5178 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
5179 values.addInt(ObjCTypes.LongTy, ModuleVersion);
5180 values.addInt(ObjCTypes.LongTy, Size);
5181 // This used to be the filename, now it is unused. <rdr://4327263>
5182 values.add(GetClassName(StringRef("")));
5183 values.add(EmitModuleSymbols());
5184 CreateMetadataVar("OBJC_MODULES", values,
John McCall7f416cc2015-09-08 08:05:57 +00005185 "__OBJC,__module_info,regular,no_dead_strip",
5186 CGM.getPointerAlign(), true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005187}
5188
5189llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005190 unsigned NumClasses = DefinedClasses.size();
5191 unsigned NumCategories = DefinedCategories.size();
5192
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005193 // Return null if no symbols were defined.
5194 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00005195 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005196
John McCall176f8922016-11-30 02:39:18 +00005197 ConstantInitBuilder builder(CGM);
5198 auto values = builder.beginStruct();
5199 values.addInt(ObjCTypes.LongTy, 0);
5200 values.addNullPointer(ObjCTypes.SelectorPtrTy);
5201 values.addInt(ObjCTypes.ShortTy, NumClasses);
5202 values.addInt(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005203
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005204 // The runtime expects exactly the list of defined classes followed
5205 // by the list of defined categories, in a single array.
John McCall176f8922016-11-30 02:39:18 +00005206 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005207 for (unsigned i=0; i<NumClasses; i++) {
5208 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5209 assert(ID);
5210 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5211 // We are implementing a weak imported interface. Give it external linkage
5212 if (ID->isWeakImported() && !IMP->isWeakImported())
5213 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
John McCall176f8922016-11-30 02:39:18 +00005214
5215 array.addBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005216 }
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005217 for (unsigned i=0; i<NumCategories; i++)
John McCall176f8922016-11-30 02:39:18 +00005218 array.addBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005219
John McCall176f8922016-11-30 02:39:18 +00005220 array.finishAndAddTo(values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005221
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005222 llvm::GlobalVariable *GV = CreateMetadataVar(
John McCall176f8922016-11-30 02:39:18 +00005223 "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip",
John McCall7f416cc2015-09-08 08:05:57 +00005224 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00005225 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005226}
5227
John McCall882987f2013-02-28 19:01:20 +00005228llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
5229 IdentifierInfo *II) {
John McCall31168b02011-06-15 23:02:42 +00005230 LazySymbols.insert(II);
Fangrui Song6907ce22018-07-30 19:24:48 +00005231
John McCall31168b02011-06-15 23:02:42 +00005232 llvm::GlobalVariable *&Entry = ClassReferences[II];
Fangrui Song6907ce22018-07-30 19:24:48 +00005233
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005234 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005235 llvm::Constant *Casted =
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00005236 llvm::ConstantExpr::getBitCast(GetClassName(II->getName()),
John McCall31168b02011-06-15 23:02:42 +00005237 ObjCTypes.ClassPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005238 Entry = CreateMetadataVar(
5239 "OBJC_CLASS_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00005240 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
5241 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005242 }
Fangrui Song6907ce22018-07-30 19:24:48 +00005243
John McCall7f416cc2015-09-08 08:05:57 +00005244 return CGF.Builder.CreateAlignedLoad(Entry, CGF.getPointerAlign());
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005245}
5246
John McCall882987f2013-02-28 19:01:20 +00005247llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00005248 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00005249 // If the class has the objc_runtime_visible attribute, we need to
5250 // use the Objective-C runtime to get the class.
5251 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
5252 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
5253
Akira Hatanaka0c194462018-04-03 22:50:16 +00005254 IdentifierInfo *RuntimeName =
5255 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
5256 return EmitClassRefFromId(CGF, RuntimeName);
John McCall31168b02011-06-15 23:02:42 +00005257}
5258
John McCall882987f2013-02-28 19:01:20 +00005259llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00005260 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
John McCall882987f2013-02-28 19:01:20 +00005261 return EmitClassRefFromId(CGF, II);
John McCall31168b02011-06-15 23:02:42 +00005262}
5263
John McCall7f416cc2015-09-08 08:05:57 +00005264llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5265 return CGF.Builder.CreateLoad(EmitSelectorAddr(CGF, Sel));
5266}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005267
John McCall7f416cc2015-09-08 08:05:57 +00005268Address CGObjCMac::EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel) {
5269 CharUnits Align = CGF.getPointerAlign();
5270
5271 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005272 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005273 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00005274 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005275 ObjCTypes.SelectorPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005276 Entry = CreateMetadataVar(
5277 "OBJC_SELECTOR_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00005278 "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true);
Michael Gottesman5c205962013-02-05 23:08:45 +00005279 Entry->setExternallyInitialized(true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005280 }
5281
John McCall7f416cc2015-09-08 08:05:57 +00005282 return Address(Entry, Align);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005283}
5284
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00005285llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
5286 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
5287 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005288 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00005289 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005290}
5291
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005292llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
5293 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
5294 I = MethodDefinitions.find(MD);
5295 if (I != MethodDefinitions.end())
5296 return I->second;
5297
Craig Topper8a13c412014-05-21 05:09:00 +00005298 return nullptr;
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005299}
5300
Fariborz Jahanian01dff422009-03-05 19:17:31 +00005301/// GetIvarLayoutName - Returns a unique constant for the given
5302/// ivar layout bitmap.
5303llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005304 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00005305 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00005306}
5307
John McCall3fd13f062015-10-21 18:06:47 +00005308void IvarLayoutBuilder::visitRecord(const RecordType *RT,
5309 CharUnits offset) {
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005310 const RecordDecl *RD = RT->getDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005311
John McCall3fd13f062015-10-21 18:06:47 +00005312 // If this is a union, remember that we had one, because it might mess
5313 // up the ordering of layout entries.
5314 if (RD->isUnion())
5315 IsDisordered = true;
5316
5317 const ASTRecordLayout *recLayout = nullptr;
5318 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5319 [&](const FieldDecl *field) -> CharUnits {
5320 if (!recLayout)
5321 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5322 auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
5323 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5324 });
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005325}
5326
John McCall3fd13f062015-10-21 18:06:47 +00005327template <class Iterator, class GetOffsetFn>
Fangrui Song6907ce22018-07-30 19:24:48 +00005328void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
John McCall3fd13f062015-10-21 18:06:47 +00005329 CharUnits aggregateOffset,
5330 const GetOffsetFn &getOffset) {
5331 for (; begin != end; ++begin) {
5332 auto field = *begin;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005333
John McCall3fd13f062015-10-21 18:06:47 +00005334 // Skip over bitfields.
5335 if (field->isBitField()) {
5336 continue;
5337 }
5338
5339 // Compute the offset of the field within the aggregate.
5340 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5341
5342 visitField(field, fieldOffset);
5343 }
5344}
5345
5346/// Collect layout information for the given fields into IvarsInfo.
5347void IvarLayoutBuilder::visitField(const FieldDecl *field,
5348 CharUnits fieldOffset) {
5349 QualType fieldType = field->getType();
5350
5351 // Drill down into arrays.
5352 uint64_t numElts = 1;
Volodymyr Sapsai636ed472017-10-27 00:56:23 +00005353 if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
5354 numElts = 0;
5355 fieldType = arrayType->getElementType();
5356 }
5357 // Unlike incomplete arrays, constant arrays can be nested.
John McCall3fd13f062015-10-21 18:06:47 +00005358 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5359 numElts *= arrayType->getSize().getZExtValue();
5360 fieldType = arrayType->getElementType();
5361 }
5362
5363 assert(!fieldType->isArrayType() && "ivar of non-constant array type?");
5364
5365 // If we ended up with a zero-sized array, we've done what we can do within
5366 // the limits of this layout encoding.
5367 if (numElts == 0) return;
5368
5369 // Recurse if the base element type is a record type.
5370 if (auto recType = fieldType->getAs<RecordType>()) {
5371 size_t oldEnd = IvarsInfo.size();
5372
5373 visitRecord(recType, fieldOffset);
5374
5375 // If we have an array, replicate the first entry's layout information.
5376 auto numEltEntries = IvarsInfo.size() - oldEnd;
5377 if (numElts != 1 && numEltEntries != 0) {
5378 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5379 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5380 // Copy the last numEltEntries onto the end of the array, adjusting
5381 // each for the element size.
5382 for (size_t i = 0; i != numEltEntries; ++i) {
5383 auto firstEntry = IvarsInfo[oldEnd + i];
5384 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5385 firstEntry.SizeInWords));
5386 }
5387 }
5388 }
5389
Fariborz Jahanian524bb202009-03-10 16:22:08 +00005390 return;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00005391 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005392
John McCall3fd13f062015-10-21 18:06:47 +00005393 // Classify the element type.
5394 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005395
John McCall3fd13f062015-10-21 18:06:47 +00005396 // If it matches what we're looking for, add an entry.
5397 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
5398 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5399 assert(CGM.getContext().getTypeSizeInChars(fieldType)
5400 == CGM.getPointerSize());
5401 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5402 }
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00005403}
5404
John McCall3fd13f062015-10-21 18:06:47 +00005405/// buildBitmap - This routine does the horsework of taking the offsets of
5406/// strong/weak references and creating a bitmap. The bitmap is also
5407/// returned in the given buffer, suitable for being passed to \c dump().
5408llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5409 llvm::SmallVectorImpl<unsigned char> &buffer) {
5410 // The bitmap is a series of skip/scan instructions, aligned to word
5411 // boundaries. The skip is performed first.
5412 const unsigned char MaxNibble = 0xF;
5413 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5414 const unsigned char ScanMask = 0x0F, ScanShift = 0;
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005415
John McCall3fd13f062015-10-21 18:06:47 +00005416 assert(!IvarsInfo.empty() && "generating bitmap for no data");
5417
5418 // Sort the ivar info on byte position in case we encounterred a
5419 // union nested in the ivar list.
5420 if (IsDisordered) {
5421 // This isn't a stable sort, but our algorithm should handle it fine.
5422 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5423 } else {
Craig Toppera3467052016-01-03 19:43:20 +00005424 assert(std::is_sorted(IvarsInfo.begin(), IvarsInfo.end()));
John McCall3fd13f062015-10-21 18:06:47 +00005425 }
5426 assert(IvarsInfo.back().Offset < InstanceEnd);
5427
5428 assert(buffer.empty());
5429
5430 // Skip the next N words.
5431 auto skip = [&](unsigned numWords) {
5432 assert(numWords > 0);
5433
5434 // Try to merge into the previous byte. Since scans happen second, we
5435 // can't do this if it includes a scan.
5436 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5437 unsigned lastSkip = buffer.back() >> SkipShift;
5438 if (lastSkip < MaxNibble) {
5439 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5440 numWords -= claimed;
5441 lastSkip += claimed;
5442 buffer.back() = (lastSkip << SkipShift);
5443 }
5444 }
5445
5446 while (numWords >= MaxNibble) {
5447 buffer.push_back(MaxNibble << SkipShift);
5448 numWords -= MaxNibble;
5449 }
5450 if (numWords) {
5451 buffer.push_back(numWords << SkipShift);
5452 }
5453 };
5454
5455 // Scan the next N words.
5456 auto scan = [&](unsigned numWords) {
5457 assert(numWords > 0);
5458
5459 // Try to merge into the previous byte. Since scans happen second, we can
5460 // do this even if it includes a skip.
5461 if (!buffer.empty()) {
5462 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5463 if (lastScan < MaxNibble) {
5464 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5465 numWords -= claimed;
5466 lastScan += claimed;
5467 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5468 }
5469 }
5470
5471 while (numWords >= MaxNibble) {
5472 buffer.push_back(MaxNibble << ScanShift);
5473 numWords -= MaxNibble;
5474 }
5475 if (numWords) {
5476 buffer.push_back(numWords << ScanShift);
5477 }
5478 };
5479
5480 // One past the end of the last scan.
5481 unsigned endOfLastScanInWords = 0;
5482 const CharUnits WordSize = CGM.getPointerSize();
5483
5484 // Consider all the scan requests.
5485 for (auto &request : IvarsInfo) {
5486 CharUnits beginOfScan = request.Offset - InstanceBegin;
5487
5488 // Ignore scan requests that don't start at an even multiple of the
5489 // word size. We can't encode them.
5490 if ((beginOfScan % WordSize) != 0) continue;
5491
5492 // Ignore scan requests that start before the instance start.
5493 // This assumes that scans never span that boundary. The boundary
5494 // isn't the true start of the ivars, because in the fragile-ARC case
5495 // it's rounded up to word alignment, but the test above should leave
5496 // us ignoring that possibility.
5497 if (beginOfScan.isNegative()) {
5498 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5499 continue;
5500 }
5501
5502 unsigned beginOfScanInWords = beginOfScan / WordSize;
5503 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5504
5505 // If the scan starts some number of words after the last one ended,
5506 // skip forward.
5507 if (beginOfScanInWords > endOfLastScanInWords) {
5508 skip(beginOfScanInWords - endOfLastScanInWords);
5509
5510 // Otherwise, start scanning where the last left off.
5511 } else {
5512 beginOfScanInWords = endOfLastScanInWords;
5513
5514 // If that leaves us with nothing to scan, ignore this request.
5515 if (beginOfScanInWords >= endOfScanInWords) continue;
5516 }
5517
5518 // Scan to the end of the request.
5519 assert(beginOfScanInWords < endOfScanInWords);
5520 scan(endOfScanInWords - beginOfScanInWords);
5521 endOfLastScanInWords = endOfScanInWords;
5522 }
5523
John McCallf5ea0722015-10-29 23:36:14 +00005524 if (buffer.empty())
5525 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5526
John McCall3fd13f062015-10-21 18:06:47 +00005527 // For GC layouts, emit a skip to the end of the allocation so that we
5528 // have precise information about the entire thing. This isn't useful
5529 // or necessary for the ARC-style layout strings.
5530 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5531 unsigned lastOffsetInWords =
5532 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5533 if (lastOffsetInWords > endOfLastScanInWords) {
5534 skip(lastOffsetInWords - endOfLastScanInWords);
5535 }
5536 }
5537
5538 // Null terminate the string.
5539 buffer.push_back(0);
5540
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005541 auto *Entry = CGObjC.CreateCStringLiteral(
5542 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
John McCall3fd13f062015-10-21 18:06:47 +00005543 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005544}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005545
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005546/// BuildIvarLayout - Builds ivar layout bitmap for the class
5547/// implementation for the __strong or __weak case.
5548/// The layout map displays which words in ivar list must be skipped
5549/// and which must be scanned by GC (see below). String is built of bytes.
5550/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
5551/// of words to skip and right nibble is count of words to scan. So, each
5552/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
5553/// represented by a 0x00 byte which also ends the string.
5554/// 1. when ForStrongLayout is true, following ivars are scanned:
5555/// - id, Class
5556/// - object *
5557/// - __strong anything
5558///
5559/// 2. When ForStrongLayout is false, following ivars are scanned:
5560/// - __weak anything
5561///
John McCall3fd13f062015-10-21 18:06:47 +00005562llvm::Constant *
5563CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5564 CharUnits beginOffset, CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +00005565 bool ForStrongLayout, bool HasMRCWeakIvars) {
5566 // If this is MRC, and we're either building a strong layout or there
5567 // are no weak ivars, bail out early.
Chris Lattnerece04092012-02-07 00:39:47 +00005568 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikiebbafb8a2012-03-11 07:00:24 +00005569 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
John McCall460ce582015-10-22 18:38:17 +00005570 !CGM.getLangOpts().ObjCAutoRefCount &&
5571 (ForStrongLayout || !HasMRCWeakIvars))
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005572 return llvm::Constant::getNullValue(PtrTy);
5573
Jordy Rosea91768e2011-07-22 02:08:32 +00005574 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
John McCall3fd13f062015-10-21 18:06:47 +00005575 SmallVector<const ObjCIvarDecl*, 32> ivars;
5576
5577 // GC layout strings include the complete object layout, possibly
5578 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5579 // up.
5580 //
5581 // ARC layout strings only include the class's ivars. In non-fragile
John McCallf5ea0722015-10-29 23:36:14 +00005582 // runtimes, that means starting at InstanceStart, rounded up to word
5583 // alignment. In fragile runtimes, there's no InstanceStart, so it means
John McCalld80218f2015-11-19 02:27:55 +00005584 // starting at the offset of the first ivar, rounded up to word alignment.
John McCall460ce582015-10-22 18:38:17 +00005585 //
5586 // MRC weak layout strings follow the ARC style.
John McCall3fd13f062015-10-21 18:06:47 +00005587 CharUnits baseOffset;
John McCall460ce582015-10-22 18:38:17 +00005588 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Fangrui Song6907ce22018-07-30 19:24:48 +00005589 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005590 IVD; IVD = IVD->getNextIvar())
John McCall3fd13f062015-10-21 18:06:47 +00005591 ivars.push_back(IVD);
5592
5593 if (isNonFragileABI()) {
5594 baseOffset = beginOffset; // InstanceStart
John McCalld80218f2015-11-19 02:27:55 +00005595 } else if (!ivars.empty()) {
5596 baseOffset =
5597 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
John McCall3fd13f062015-10-21 18:06:47 +00005598 } else {
5599 baseOffset = CharUnits::Zero();
5600 }
John McCallf5ea0722015-10-29 23:36:14 +00005601
Rui Ueyama83aa9792016-01-14 21:00:27 +00005602 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005603 }
5604 else {
John McCall3fd13f062015-10-21 18:06:47 +00005605 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005606
John McCall3fd13f062015-10-21 18:06:47 +00005607 baseOffset = CharUnits::Zero();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005608 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005609
John McCall3fd13f062015-10-21 18:06:47 +00005610 if (ivars.empty())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005611 return llvm::Constant::getNullValue(PtrTy);
5612
John McCall3fd13f062015-10-21 18:06:47 +00005613 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005614
John McCall3fd13f062015-10-21 18:06:47 +00005615 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5616 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5617 return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
5618 });
5619
5620 if (!builder.hasBitmapData())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005621 return llvm::Constant::getNullValue(PtrTy);
John McCall3fd13f062015-10-21 18:06:47 +00005622
5623 llvm::SmallVector<unsigned char, 4> buffer;
5624 llvm::Constant *C = builder.buildBitmap(*this, buffer);
Fangrui Song6907ce22018-07-30 19:24:48 +00005625
John McCallf5ea0722015-10-29 23:36:14 +00005626 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005627 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005628 ForStrongLayout ? "strong" : "weak",
Ben Langmuire013bdc2014-07-11 00:43:47 +00005629 OMD->getClassInterface()->getName().str().c_str());
John McCall3fd13f062015-10-21 18:06:47 +00005630 builder.dump(buffer);
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005631 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005632 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00005633}
5634
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005635llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005636 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
Chris Lattner3def9ae2012-02-06 22:16:34 +00005637 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005638 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005639 Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
Owen Anderson170229f2009-07-14 23:10:40 +00005640 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005641}
5642
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005643// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005644llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005645 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5646}
5647
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005648llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005649 std::string TypeStr;
5650 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5651
5652 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005653 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005654 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005655 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005656}
5657
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005658llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5659 bool Extended) {
John McCall843dfcc2016-11-29 21:57:00 +00005660 std::string TypeStr =
5661 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005662
5663 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbar3241fae2009-04-14 23:14:47 +00005664 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005665 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005666 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005667}
5668
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005669// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005670llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005671 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005672 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005673 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
Owen Anderson170229f2009-07-14 23:10:40 +00005674 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005675}
5676
5677// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00005678// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005679llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005680CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5681 const Decl *Container) {
John McCall843dfcc2016-11-29 21:57:00 +00005682 std::string TypeStr =
5683 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005684 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5685}
5686
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005687void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005688 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005689 SmallVectorImpl<char> &Name) {
Daniel Dunbard2386812009-10-19 01:21:19 +00005690 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00005691 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00005692 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
5693 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005694 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00005695 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer2f569922012-02-07 11:57:45 +00005696 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00005697 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00005698}
5699
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005700void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005701 EmitModuleInfo();
5702
Daniel Dunbarc475d422008-10-29 22:36:39 +00005703 // Emit the dummy bodies for any protocols which were referenced but
5704 // never defined.
John McCall176f8922016-11-30 02:39:18 +00005705 for (auto &entry : Protocols) {
5706 llvm::GlobalVariable *global = entry.second;
5707 if (global->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00005708 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005709
John McCall176f8922016-11-30 02:39:18 +00005710 ConstantInitBuilder builder(CGM);
5711 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5712 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5713 values.add(GetClassName(entry.first->getName()));
5714 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5715 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5716 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5717 values.finishAndSetAsInitializer(global);
5718 CGM.addCompilerUsedGlobal(global);
Daniel Dunbarc475d422008-10-29 22:36:39 +00005719 }
5720
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005721 // Add assembler directives to add lazy undefined symbol references
5722 // for classes which are referenced but not defined. This is
5723 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00005724 //
5725 // FIXME: It would be nice if we had an LLVM construct for this.
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005726 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5727 CGM.getTriple().isOSBinFormatMachO()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005728 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00005729 Asm += CGM.getModule().getModuleInlineAsm();
5730 if (!Asm.empty() && Asm.back() != '\n')
5731 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005732
Daniel Dunbard027a922009-09-07 00:20:42 +00005733 llvm::raw_svector_ostream OS(Asm);
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005734 for (const auto *Sym : DefinedSymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005735 OS << "\t.objc_class_name_" << Sym->getName() << "=0\n"
5736 << "\t.globl .objc_class_name_" << Sym->getName() << "\n";
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005737 for (const auto *Sym : LazySymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005738 OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n";
5739 for (const auto &Category : DefinedCategoryNames)
5740 OS << "\t.objc_category_name_" << Category << "=0\n"
5741 << "\t.globl .objc_category_name_" << Category << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00005742
Daniel Dunbard027a922009-09-07 00:20:42 +00005743 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005744 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005745}
5746
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005747CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00005748 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5749 ObjCEmptyVtableVar(nullptr) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005750 ObjCABI = 2;
5751}
5752
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005753/* *** */
5754
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005755ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Craig Topper8a13c412014-05-21 05:09:00 +00005756 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00005757{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005758 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5759 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005760
John McCall176f8922016-11-30 02:39:18 +00005761 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5762 IntTy = CGM.IntTy;
5763 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
Chris Lattnerece04092012-02-07 00:39:47 +00005764 Int8PtrTy = CGM.Int8PtrTy;
5765 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005766
Tim Northover238b5082014-03-29 13:42:40 +00005767 // arm64 targets use "int" ivar offset variables. All others,
5768 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
Tim Northover40956e62014-07-23 12:32:58 +00005769 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
Tim Northover238b5082014-03-29 13:42:40 +00005770 IvarOffsetVarTy = IntTy;
5771 else
5772 IvarOffsetVarTy = LongTy;
5773
John McCall176f8922016-11-30 02:39:18 +00005774 ObjectPtrTy =
5775 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5776 PtrObjectPtrTy =
5777 llvm::PointerType::getUnqual(ObjectPtrTy);
5778 SelectorPtrTy =
5779 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005780
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005781 // I'm not sure I like this. The implicit coordination is a bit
5782 // gross. We should solve this in a reasonable fashion because this
5783 // is a pretty common task (match some runtime data structure with
5784 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005785
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005786 // FIXME: This is leaked.
5787 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005788
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005789 // struct _objc_super {
5790 // id self;
5791 // Class cls;
5792 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00005793 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005794 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005795 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005796 &Ctx.Idents.get("_objc_super"));
Craig Topper8a13c412014-05-21 05:09:00 +00005797 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5798 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5799 false, ICIS_NoInit));
5800 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5801 nullptr, Ctx.getObjCClassType(), nullptr,
5802 nullptr, false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005803 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005804
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005805 SuperCTy = Ctx.getTagDeclType(RD);
5806 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005807
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005808 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005809 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5810
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005811 // struct _prop_t {
5812 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005813 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005814 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005815 PropertyTy = llvm::StructType::create("struct._prop_t", Int8PtrTy, Int8PtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005816
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005817 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005818 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005819 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005820 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005821 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005822 PropertyListTy = llvm::StructType::create(
5823 "struct._prop_list_t", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0));
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005824 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005825 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005826
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005827 // struct _objc_method {
5828 // SEL _cmd;
5829 // char *method_type;
5830 // char *_imp;
5831 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005832 MethodTy = llvm::StructType::create("struct._objc_method", SelectorPtrTy,
5833 Int8PtrTy, Int8PtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005834
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005835 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00005836 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005837 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005838}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005839
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005840ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005841 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005842 // struct _objc_method_description {
5843 // SEL name;
5844 // char *types;
5845 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005846 MethodDescriptionTy = llvm::StructType::create(
5847 "struct._objc_method_description", SelectorPtrTy, Int8PtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005848
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005849 // struct _objc_method_description_list {
5850 // int count;
5851 // struct _objc_method_description[1];
5852 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005853 MethodDescriptionListTy =
5854 llvm::StructType::create("struct._objc_method_description_list", IntTy,
5855 llvm::ArrayType::get(MethodDescriptionTy, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005856
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005857 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005858 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005859 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005860
Daniel Dunbarb036db82008-08-13 03:21:16 +00005861 // Protocol description structures
5862
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005863 // struct _objc_protocol_extension {
5864 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5865 // struct _objc_method_description_list *optional_instance_methods;
5866 // struct _objc_method_description_list *optional_class_methods;
5867 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005868 // const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00005869 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005870 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005871 ProtocolExtensionTy = llvm::StructType::create(
5872 "struct._objc_protocol_extension", IntTy, MethodDescriptionListPtrTy,
5873 MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy,
5874 PropertyListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005875
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005876 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005877 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005878
Daniel Dunbarc475d422008-10-29 22:36:39 +00005879 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00005880
Chris Lattnera5f58b02011-07-09 17:41:47 +00005881 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005882 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00005883
Chris Lattnera5f58b02011-07-09 17:41:47 +00005884 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005885 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Serge Guelton1d993272017-05-09 19:31:30 +00005886 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), LongTy,
5887 llvm::ArrayType::get(ProtocolTy, 0));
Daniel Dunbarb036db82008-08-13 03:21:16 +00005888
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005889 // struct _objc_protocol {
5890 // struct _objc_protocol_extension *isa;
5891 // char *protocol_name;
5892 // struct _objc_protocol **_objc_protocol_list;
5893 // struct _objc_method_description_list *instance_methods;
5894 // struct _objc_method_description_list *class_methods;
5895 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005896 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5897 llvm::PointerType::getUnqual(ProtocolListTy),
Serge Guelton1d993272017-05-09 19:31:30 +00005898 MethodDescriptionListPtrTy, MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005899
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005900 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005901 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005902
Owen Anderson9793f0e2009-07-29 22:16:19 +00005903 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005904
5905 // Class description structures
5906
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005907 // struct _objc_ivar {
5908 // char *ivar_name;
5909 // char *ivar_type;
5910 // int ivar_offset;
5911 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005912 IvarTy = llvm::StructType::create("struct._objc_ivar", Int8PtrTy, Int8PtrTy,
5913 IntTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005914
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005915 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005916 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005917 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005918 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005919
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005920 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005921 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005922 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005923 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005924
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005925 // struct _objc_class_extension *
Serge Guelton1d993272017-05-09 19:31:30 +00005926 ClassExtensionTy = llvm::StructType::create(
5927 "struct._objc_class_extension", IntTy, Int8PtrTy, PropertyListPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005928 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005929
Chris Lattner5ec04a52011-08-12 17:43:31 +00005930 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005931
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005932 // struct _objc_class {
5933 // Class isa;
5934 // Class super_class;
5935 // char *name;
5936 // long version;
5937 // long info;
5938 // long instance_size;
5939 // struct _objc_ivar_list *ivars;
5940 // struct _objc_method_list *methods;
5941 // struct _objc_cache *cache;
5942 // struct _objc_protocol_list *protocols;
5943 // char *ivar_layout;
5944 // struct _objc_class_ext *ext;
5945 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005946 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
Serge Guelton1d993272017-05-09 19:31:30 +00005947 llvm::PointerType::getUnqual(ClassTy), Int8PtrTy, LongTy,
5948 LongTy, LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy,
5949 ProtocolListPtrTy, Int8PtrTy, ClassExtensionPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005950
Owen Anderson9793f0e2009-07-29 22:16:19 +00005951 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005952
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005953 // struct _objc_category {
5954 // char *category_name;
5955 // char *class_name;
5956 // struct _objc_method_list *instance_method;
5957 // struct _objc_method_list *class_method;
Manman Renb3736772016-01-25 22:37:47 +00005958 // struct _objc_protocol_list *protocols;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005959 // uint32_t size; // sizeof(struct _objc_category)
5960 // struct _objc_property_list *instance_properties;// category's @property
Manman Ren96df0b32016-01-29 23:45:01 +00005961 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005962 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005963 CategoryTy = llvm::StructType::create(
5964 "struct._objc_category", Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5965 MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy,
5966 PropertyListPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005967
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005968 // Global metadata structures
5969
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005970 // struct _objc_symtab {
5971 // long sel_ref_cnt;
5972 // SEL *refs;
5973 // short cls_def_cnt;
5974 // short cat_def_cnt;
5975 // char *defs[cls_def_cnt + cat_def_cnt];
5976 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005977 SymtabTy = llvm::StructType::create("struct._objc_symtab", LongTy,
5978 SelectorPtrTy, ShortTy, ShortTy,
5979 llvm::ArrayType::get(Int8PtrTy, 0));
Owen Anderson9793f0e2009-07-29 22:16:19 +00005980 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005981
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00005982 // struct _objc_module {
5983 // long version;
5984 // long size; // sizeof(struct _objc_module)
5985 // char *name;
5986 // struct _objc_symtab* symtab;
5987 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005988 ModuleTy = llvm::StructType::create("struct._objc_module", LongTy, LongTy,
5989 Int8PtrTy, SymtabPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005990
Mike Stump18bb9282009-05-16 07:57:57 +00005991 // FIXME: This is the size of the setjmp buffer and should be target
5992 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00005993 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005994
Anders Carlsson9ff22482008-09-09 10:10:21 +00005995 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00005996 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005997
Serge Guelton1d993272017-05-09 19:31:30 +00005998 ExceptionDataTy = llvm::StructType::create(
5999 "struct._objc_exception_data",
6000 llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00006001}
6002
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006003ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00006004 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006005 // struct _method_list_t {
6006 // uint32_t entsize; // sizeof(struct _objc_method)
6007 // uint32_t method_count;
6008 // struct _objc_method method_list[method_count];
6009 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00006010 MethodListnfABITy =
Serge Guelton1d993272017-05-09 19:31:30 +00006011 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
6012 llvm::ArrayType::get(MethodTy, 0));
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006013 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00006014 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006015
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006016 // struct _protocol_t {
6017 // id isa; // NULL
6018 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006019 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006020 // const struct method_list_t * const instance_methods;
6021 // const struct method_list_t * const class_methods;
6022 // const struct method_list_t *optionalInstanceMethods;
6023 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006024 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006025 // const uint32_t size; // sizeof(struct _protocol_t)
6026 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006027 // const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006028 // const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00006029 // const struct _prop_list_t * class_properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006030 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006031
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006032 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00006033 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00006034 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006035
Serge Guelton1d993272017-05-09 19:31:30 +00006036 ProtocolnfABITy = llvm::StructType::create(
6037 "struct._protocol_t", ObjectPtrTy, Int8PtrTy,
6038 llvm::PointerType::getUnqual(ProtocolListnfABITy), MethodListnfABIPtrTy,
6039 MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy,
6040 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy,
6041 PropertyListPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006042
6043 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00006044 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006045
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006046 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006047 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006048 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006049 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00006050 ProtocolListnfABITy->setBody(LongTy,
Serge Guelton1d993272017-05-09 19:31:30 +00006051 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006052
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006053 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00006054 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006055
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006056 // struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00006057 // unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006058 // char *name;
6059 // char *type;
6060 // uint32_t alignment;
6061 // uint32_t size;
6062 // }
Tim Northover238b5082014-03-29 13:42:40 +00006063 IvarnfABITy = llvm::StructType::create(
6064 "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy),
Serge Guelton1d993272017-05-09 19:31:30 +00006065 Int8PtrTy, Int8PtrTy, IntTy, IntTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006066
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006067 // struct _ivar_list_t {
6068 // uint32 entsize; // sizeof(struct _ivar_t)
6069 // uint32 count;
6070 // struct _iver_t list[count];
6071 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00006072 IvarListnfABITy =
Serge Guelton1d993272017-05-09 19:31:30 +00006073 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
6074 llvm::ArrayType::get(IvarnfABITy, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006075
Owen Anderson9793f0e2009-07-29 22:16:19 +00006076 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006077
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006078 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006079 // uint32_t const flags;
6080 // uint32_t const instanceStart;
6081 // uint32_t const instanceSize;
6082 // uint32_t const reserved; // only when building for 64bit targets
6083 // const uint8_t * const ivarLayout;
6084 // const char *const name;
6085 // const struct _method_list_t * const baseMethods;
6086 // const struct _objc_protocol_list *const baseProtocols;
6087 // const struct _ivar_list_t *const ivars;
6088 // const uint8_t * const weakIvarLayout;
6089 // const struct _prop_list_t * const properties;
6090 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006091
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006092 // FIXME. Add 'reserved' field in 64bit abi mode!
Serge Guelton1d993272017-05-09 19:31:30 +00006093 ClassRonfABITy = llvm::StructType::create(
6094 "struct._class_ro_t", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy,
6095 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy,
6096 Int8PtrTy, PropertyListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006097
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006098 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00006099 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00006100 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
6101 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006102
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006103 // struct _class_t {
6104 // struct _class_t *isa;
6105 // struct _class_t * const superclass;
6106 // void *cache;
6107 // IMP *vtable;
6108 // struct class_ro_t *ro;
6109 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006110
Chris Lattner5ec04a52011-08-12 17:43:31 +00006111 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00006112 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
Serge Guelton1d993272017-05-09 19:31:30 +00006113 llvm::PointerType::getUnqual(ClassnfABITy), CachePtrTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00006114 llvm::PointerType::getUnqual(ImpnfABITy),
Serge Guelton1d993272017-05-09 19:31:30 +00006115 llvm::PointerType::getUnqual(ClassRonfABITy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006116
Fariborz Jahanian71394042009-01-23 23:53:38 +00006117 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00006118 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006119
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006120 // struct _category_t {
6121 // const char * const name;
6122 // struct _class_t *const cls;
6123 // const struct _method_list_t * const instance_methods;
6124 // const struct _method_list_t * const class_methods;
6125 // const struct _protocol_list_t * const protocols;
6126 // const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00006127 // const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00006128 // const uint32_t size;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00006129 // }
Serge Guelton1d993272017-05-09 19:31:30 +00006130 CategorynfABITy = llvm::StructType::create(
6131 "struct._category_t", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy,
6132 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy,
6133 PropertyListPtrTy, IntTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006134
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006135 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006136 CodeGen::CodeGenTypes &Types = CGM.getTypes();
6137 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006138
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006139 // MessageRefTy - LLVM for:
6140 // struct _message_ref_t {
6141 // IMP messenger;
6142 // SEL name;
6143 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006144
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006145 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00006146 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00006147 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00006148 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006149 &Ctx.Idents.get("_message_ref_t"));
Craig Topper8a13c412014-05-21 05:09:00 +00006150 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6151 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
Richard Smith2b013182012-06-10 03:12:00 +00006152 ICIS_NoInit));
Craig Topper8a13c412014-05-21 05:09:00 +00006153 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6154 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
6155 false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00006156 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006157
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006158 MessageRefCTy = Ctx.getTagDeclType(RD);
6159 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
6160 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006161
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006162 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00006163 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006164
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006165 // SuperMessageRefTy - LLVM for:
6166 // struct _super_message_ref_t {
6167 // SUPER_IMP messenger;
6168 // SEL name;
6169 // };
Serge Guelton1d993272017-05-09 19:31:30 +00006170 SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t",
6171 ImpnfABITy, SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006172
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006173 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006174 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fangrui Song6907ce22018-07-30 19:24:48 +00006175
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006176
6177 // struct objc_typeinfo {
6178 // const void** vtable; // objc_ehtype_vtable + 2
6179 // const char* name; // c++ typeinfo string
6180 // Class cls;
6181 // };
Serge Guelton1d993272017-05-09 19:31:30 +00006182 EHTypeTy = llvm::StructType::create("struct._objc_typeinfo",
6183 llvm::PointerType::getUnqual(Int8PtrTy),
6184 Int8PtrTy, ClassnfABIPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00006185 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00006186}
6187
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006188llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00006189 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006190
Craig Topper8a13c412014-05-21 05:09:00 +00006191 return nullptr;
Fariborz Jahanian71394042009-01-23 23:53:38 +00006192}
6193
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00006194void CGObjCNonFragileABIMac::AddModuleClassList(
6195 ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
6196 StringRef SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00006197 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006198
Daniel Dunbar19573e72009-05-15 21:48:48 +00006199 if (!NumClasses)
6200 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006201
Chris Lattner3def9ae2012-02-06 22:16:34 +00006202 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00006203 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00006204 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00006205 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00006206 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00006207 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00006208 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00006209 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006210
Akira Hatanaka187770d2019-05-09 17:43:52 +00006211 // Section name is obtained by calling GetSectionName, which returns
6212 // sections in the __DATA segment on MachO.
6213 assert((!CGM.getTriple().isOSBinFormatMachO() ||
6214 SectionName.startswith("__DATA")) &&
6215 "SectionName expected to start with __DATA on MachO");
6216 llvm::GlobalValue::LinkageTypes LT =
6217 getLinkageTypeForObjCMetadata(CGM, SectionName);
Daniel Dunbar19573e72009-05-15 21:48:48 +00006218 llvm::GlobalVariable *GV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00006219 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, LT, Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006220 SymbolName);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006221 GV->setAlignment(
6222 llvm::Align(CGM.getDataLayout().getABITypeAlignment(Init->getType())));
Daniel Dunbar19573e72009-05-15 21:48:48 +00006223 GV->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00006224 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00006225}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006226
Fariborz Jahanian71394042009-01-23 23:53:38 +00006227void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
6228 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006229
Daniel Dunbar19573e72009-05-15 21:48:48 +00006230 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006231 // L_OBJC_LABEL_CLASS_$.
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00006232
6233 for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) {
6234 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
6235 assert(ID);
6236 if (ObjCImplementationDecl *IMP = ID->getImplementation())
6237 // We are implementing a weak imported interface. Give it external linkage
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00006238 if (ID->isWeakImported() && !IMP->isWeakImported()) {
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00006239 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00006240 DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
6241 }
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00006242 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006243
6244 AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006245 GetSectionName("__objc_classlist",
6246 "regular,no_dead_strip"));
Rafael Espindola554256c2014-02-26 22:25:45 +00006247
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006248 AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006249 GetSectionName("__objc_nlclslist",
6250 "regular,no_dead_strip"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006251
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006252 // Build list of all implemented category addresses in array
6253 // L_OBJC_LABEL_CATEGORY_$.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006254 AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006255 GetSectionName("__objc_catlist",
6256 "regular,no_dead_strip"));
John McCall2c91c3b2019-05-30 04:09:01 +00006257 AddModuleClassList(DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$",
6258 GetSectionName("__objc_catlist2",
6259 "regular,no_dead_strip"));
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006260 AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006261 GetSectionName("__objc_nlcatlist",
6262 "regular,no_dead_strip"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006263
Daniel Dunbar5e639272010-04-25 20:39:01 +00006264 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00006265}
6266
John McCall9e8bb002011-05-14 03:10:52 +00006267/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
6268/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006269/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006270/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00006271bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
6272 // At various points we've experimented with using vtable-based
6273 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006274 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006275 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00006276 return false;
John McCall9e8bb002011-05-14 03:10:52 +00006277 case CodeGenOptions::NonLegacy:
6278 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006279 case CodeGenOptions::Mixed:
6280 break;
6281 }
6282
6283 // If so, see whether this selector is in the white-list of things which must
6284 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00006285 if (VTableDispatchMethods.empty()) {
6286 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
6287 VTableDispatchMethods.insert(GetNullarySelector("class"));
6288 VTableDispatchMethods.insert(GetNullarySelector("self"));
6289 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
6290 VTableDispatchMethods.insert(GetNullarySelector("length"));
6291 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006292
John McCall9e8bb002011-05-14 03:10:52 +00006293 // These are vtable-based if GC is disabled.
6294 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006295 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00006296 VTableDispatchMethods.insert(GetNullarySelector("retain"));
6297 VTableDispatchMethods.insert(GetNullarySelector("release"));
6298 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
6299 }
6300
6301 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
6302 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
6303 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
6304 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
6305 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
6306 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
6307 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
6308
6309 // These are vtable-based if GC is enabled.
6310 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006311 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00006312 VTableDispatchMethods.insert(GetNullarySelector("hash"));
6313 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
Fangrui Song6907ce22018-07-30 19:24:48 +00006314
John McCall9e8bb002011-05-14 03:10:52 +00006315 // "countByEnumeratingWithState:objects:count"
6316 IdentifierInfo *KeyIdents[] = {
6317 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
6318 &CGM.getContext().Idents.get("objects"),
6319 &CGM.getContext().Idents.get("count")
6320 };
6321 VTableDispatchMethods.insert(
6322 CGM.getContext().Selectors.getSelector(3, KeyIdents));
6323 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006324 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006325
John McCall9e8bb002011-05-14 03:10:52 +00006326 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006327}
6328
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006329/// BuildClassRoTInitializer - generate meta-data for:
6330/// struct _class_ro_t {
6331/// uint32_t const flags;
6332/// uint32_t const instanceStart;
6333/// uint32_t const instanceSize;
6334/// uint32_t const reserved; // only when building for 64bit targets
6335/// const uint8_t * const ivarLayout;
6336/// const char *const name;
6337/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006338/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006339/// const struct _ivar_list_t *const ivars;
6340/// const uint8_t * const weakIvarLayout;
6341/// const struct _prop_list_t * const properties;
6342/// }
6343///
6344llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006345 unsigned flags,
6346 unsigned InstanceStart,
6347 unsigned InstanceSize,
6348 const ObjCImplementationDecl *ID) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006349 std::string ClassName = ID->getObjCRuntimeNameAsString();
John McCall31168b02011-06-15 23:02:42 +00006350
John McCall3fd13f062015-10-21 18:06:47 +00006351 CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
6352 CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
6353
John McCall460ce582015-10-22 18:38:17 +00006354 bool hasMRCWeak = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00006355 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCallef19dbb2012-10-17 04:53:23 +00006356 flags |= NonFragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00006357 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
6358 flags |= NonFragileABI_Class_HasMRCWeakIvars;
John McCall31168b02011-06-15 23:02:42 +00006359
John McCall176f8922016-11-30 02:39:18 +00006360 ConstantInitBuilder builder(CGM);
6361 auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
6362
6363 values.addInt(ObjCTypes.IntTy, flags);
6364 values.addInt(ObjCTypes.IntTy, InstanceStart);
6365 values.addInt(ObjCTypes.IntTy, InstanceSize);
6366 values.add((flags & NonFragileABI_Class_Meta)
6367 ? GetIvarLayoutName(nullptr, ObjCTypes)
6368 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
6369 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
6370
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006371 // const struct _method_list_t * const baseMethods;
John McCall176f8922016-11-30 02:39:18 +00006372 SmallVector<const ObjCMethodDecl*, 16> methods;
John McCallef19dbb2012-10-17 04:53:23 +00006373 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00006374 for (const auto *MD : ID->class_methods())
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08006375 if (!MD->isDirectMethod())
6376 methods.push_back(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006377 } else {
John McCall176f8922016-11-30 02:39:18 +00006378 for (const auto *MD : ID->instance_methods())
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08006379 if (!MD->isDirectMethod())
6380 methods.push_back(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006381 }
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006382
John McCall176f8922016-11-30 02:39:18 +00006383 values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
6384 (flags & NonFragileABI_Class_Meta)
6385 ? MethodListType::ClassMethods
6386 : MethodListType::InstanceMethods,
6387 methods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006388
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006389 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6390 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Akira Hatanaka187770d2019-05-09 17:43:52 +00006391 values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006392 + OID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006393 OID->all_referenced_protocol_begin(),
6394 OID->all_referenced_protocol_end()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006395
John McCallef19dbb2012-10-17 04:53:23 +00006396 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00006397 values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
6398 values.add(GetIvarLayoutName(nullptr, ObjCTypes));
6399 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00006400 "_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006401 ID, ID->getClassInterface(), ObjCTypes, true));
John McCallef19dbb2012-10-17 04:53:23 +00006402 } else {
John McCall176f8922016-11-30 02:39:18 +00006403 values.add(EmitIvarList(ID));
6404 values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
6405 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00006406 "_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006407 ID, ID->getClassInterface(), ObjCTypes, false));
John McCallef19dbb2012-10-17 04:53:23 +00006408 }
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006409
John McCall176f8922016-11-30 02:39:18 +00006410 llvm::SmallString<64> roLabel;
6411 llvm::raw_svector_ostream(roLabel)
Akira Hatanaka187770d2019-05-09 17:43:52 +00006412 << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_"
6413 : "_OBJC_CLASS_RO_$_")
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006414 << ClassName;
6415
Akira Hatanaka187770d2019-05-09 17:43:52 +00006416 return finishAndCreateGlobal(values, roLabel, CGM);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006417}
6418
John McCalldba63a72016-11-30 23:54:50 +00006419/// Build the metaclass object for a class.
6420///
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006421/// struct _class_t {
6422/// struct _class_t *isa;
6423/// struct _class_t * const superclass;
6424/// void *cache;
6425/// IMP *vtable;
6426/// struct class_ro_t *ro;
6427/// }
6428///
John McCalldba63a72016-11-30 23:54:50 +00006429llvm::GlobalVariable *
6430CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI,
6431 bool isMetaclass,
6432 llvm::Constant *IsAGV,
6433 llvm::Constant *SuperClassGV,
6434 llvm::Constant *ClassRoGV,
6435 bool HiddenVisibility) {
John McCall176f8922016-11-30 02:39:18 +00006436 ConstantInitBuilder builder(CGM);
6437 auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
6438 values.add(IsAGV);
6439 if (SuperClassGV) {
6440 values.add(SuperClassGV);
6441 } else {
6442 values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
6443 }
6444 values.add(ObjCEmptyCacheVar);
6445 values.add(ObjCEmptyVtableVar);
6446 values.add(ClassRoGV);
6447
John McCalldba63a72016-11-30 23:54:50 +00006448 llvm::GlobalVariable *GV =
6449 cast<llvm::GlobalVariable>(GetClassGlobal(CI, isMetaclass, ForDefinition));
John McCall176f8922016-11-30 02:39:18 +00006450 values.finishAndSetAsInitializer(GV);
6451
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006452 if (CGM.getTriple().isOSBinFormatMachO())
6453 GV->setSection("__DATA, __objc_data");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006454 GV->setAlignment(llvm::Align(
6455 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy)));
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006456 if (!CGM.getTriple().isOSBinFormatCOFF())
6457 if (HiddenVisibility)
6458 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006459 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006460}
6461
Joe Danielsf7393d22019-02-04 23:32:55 +00006462bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(
6463 const ObjCImplDecl *OD) const {
6464 return OD->getClassMethod(GetNullarySelector("load")) != nullptr ||
Erik Pilkington1138d8c2019-04-11 17:55:34 +00006465 OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() ||
6466 OD->hasAttr<ObjCNonLazyClassAttr>();
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006467}
6468
Daniel Dunbar961202372009-05-03 12:57:56 +00006469void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00006470 uint32_t &InstanceStart,
6471 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006472 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00006473 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006474
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006475 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00006476 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006477
6478 // If there are no fields, the start is the same as the end.
6479 if (!RL.getFieldCount())
6480 InstanceStart = InstanceSize;
6481 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00006482 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00006483}
6484
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006485static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
6486 StringRef Name) {
6487 IdentifierInfo &II = CGM.getContext().Idents.get(Name);
6488 TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
6489 DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
6490
6491 const VarDecl *VD = nullptr;
6492 for (const auto &Result : DC->lookup(&II))
6493 if ((VD = dyn_cast<VarDecl>(Result)))
6494 break;
6495
6496 if (!VD)
6497 return llvm::GlobalValue::DLLImportStorageClass;
6498 if (VD->hasAttr<DLLExportAttr>())
6499 return llvm::GlobalValue::DLLExportStorageClass;
6500 if (VD->hasAttr<DLLImportAttr>())
6501 return llvm::GlobalValue::DLLImportStorageClass;
6502 return llvm::GlobalValue::DefaultStorageClass;
6503}
6504
Fariborz Jahanian71394042009-01-23 23:53:38 +00006505void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00006506 if (!ObjCEmptyCacheVar) {
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006507 ObjCEmptyCacheVar =
6508 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false,
6509 llvm::GlobalValue::ExternalLinkage, nullptr,
6510 "_objc_empty_cache");
6511 if (CGM.getTriple().isOSBinFormatCOFF())
6512 ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache"));
Craig Topper8a13c412014-05-21 05:09:00 +00006513
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006514 // Only OS X with deployment version <10.9 use the empty vtable symbol
Fariborz Jahanian42d49552013-10-24 17:40:28 +00006515 const llvm::Triple &Triple = CGM.getTarget().getTriple();
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006516 if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006517 ObjCEmptyVtableVar =
6518 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false,
6519 llvm::GlobalValue::ExternalLinkage, nullptr,
6520 "_objc_empty_vtable");
John McCall176f8922016-11-30 02:39:18 +00006521 else
6522 ObjCEmptyVtableVar =
6523 llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
Fariborz Jahanian71394042009-01-23 23:53:38 +00006524 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006525
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00006526 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006527 uint32_t InstanceStart =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006528 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006529 uint32_t InstanceSize = InstanceStart;
John McCallef19dbb2012-10-17 04:53:23 +00006530 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006531
John McCalldba63a72016-11-30 23:54:50 +00006532 llvm::Constant *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006533
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006534 const auto *CI = ID->getClassInterface();
6535 assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0");
6536
John McCall0d54a172012-10-17 04:53:31 +00006537 // Build the flags for the metaclass.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006538 bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
6539 ? !CI->hasAttr<DLLExportAttr>()
6540 : CI->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006541 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006542 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006543
6544 // FIXME: why is this flag set on the metaclass?
6545 // ObjC metaclasses have no fields and don't really get constructed.
6546 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006547 flags |= NonFragileABI_Class_HasCXXStructors;
John McCall0d54a172012-10-17 04:53:31 +00006548 if (!ID->hasNonZeroConstructors())
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006549 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
John McCall0d54a172012-10-17 04:53:31 +00006550 }
6551
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006552 if (!CI->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006553 // class is root
John McCallef19dbb2012-10-17 04:53:23 +00006554 flags |= NonFragileABI_Class_Root;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006555
John McCalldba63a72016-11-30 23:54:50 +00006556 SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
6557 IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006558 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006559 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00006560 const ObjCInterfaceDecl *Root = ID->getClassInterface();
6561 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
6562 Root = Super;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006563
6564 const auto *Super = CI->getSuperClass();
John McCalldba63a72016-11-30 23:54:50 +00006565 IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
6566 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006567 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006568
6569 llvm::GlobalVariable *CLASS_RO_GV =
6570 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6571
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006572 llvm::GlobalVariable *MetaTClass =
John McCalldba63a72016-11-30 23:54:50 +00006573 BuildClassObject(CI, /*metaclass*/ true,
6574 IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
Rafael Espindolab7350042018-03-01 00:35:47 +00006575 CGM.setGVProperties(MetaTClass, CI);
Fariborz Jahanian67260552009-11-17 21:37:35 +00006576 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00006577
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006578 // Metadata for the class
John McCallef19dbb2012-10-17 04:53:23 +00006579 flags = 0;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006580 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006581 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006582
6583 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006584 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006585
John McCall0d54a172012-10-17 04:53:31 +00006586 // Set a flag to enable a runtime optimization when a class has
6587 // fields that require destruction but which don't require
6588 // anything except zero-initialization during construction. This
6589 // is most notably true of __strong and __weak types, but you can
6590 // also imagine there being C++ types with non-trivial default
6591 // constructors that merely set all fields to null.
6592 if (!ID->hasNonZeroConstructors())
6593 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6594 }
6595
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006596 if (hasObjCExceptionAttribute(CGM.getContext(), CI))
John McCallef19dbb2012-10-17 04:53:23 +00006597 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006598
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006599 if (!CI->getSuperClass()) {
John McCallef19dbb2012-10-17 04:53:23 +00006600 flags |= NonFragileABI_Class_Root;
Craig Topper8a13c412014-05-21 05:09:00 +00006601 SuperClassGV = nullptr;
Chris Lattnerb433b272009-04-19 06:02:28 +00006602 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006603 // Has a root. Current class is not a root.
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006604 const auto *Super = CI->getSuperClass();
John McCalldba63a72016-11-30 23:54:50 +00006605 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006606 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006607
Daniel Dunbar961202372009-05-03 12:57:56 +00006608 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006609 CLASS_RO_GV =
6610 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006611
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006612 llvm::GlobalVariable *ClassMD =
John McCalldba63a72016-11-30 23:54:50 +00006613 BuildClassObject(CI, /*metaclass*/ false,
6614 MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden);
Rafael Espindolab7350042018-03-01 00:35:47 +00006615 CGM.setGVProperties(ClassMD, CI);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006616 DefinedClasses.push_back(ClassMD);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006617 ImplementedClasses.push_back(CI);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006618
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006619 // Determine if this class is also "non-lazy".
6620 if (ImplementationIsNonLazy(ID))
6621 DefinedNonLazyClasses.push_back(ClassMD);
6622
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006623 // Force the definition of the EHType if necessary.
John McCallef19dbb2012-10-17 04:53:23 +00006624 if (flags & NonFragileABI_Class_Exception)
John McCalldba63a72016-11-30 23:54:50 +00006625 (void) GetInterfaceEHType(CI, ForDefinition);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006626 // Make sure method definition entries are all clear for next implementation.
6627 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00006628}
6629
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006630/// GenerateProtocolRef - This routine is called to generate code for
6631/// a protocol reference expression; as in:
6632/// @code
6633/// @protocol(Proto1);
6634/// @endcode
6635/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
6636/// which will hold address of the protocol meta-data.
6637///
John McCall882987f2013-02-28 19:01:20 +00006638llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006639 const ObjCProtocolDecl *PD) {
6640
Fariborz Jahanian464423d2009-04-10 18:47:34 +00006641 // This routine is called for @protocol only. So, we must build definition
6642 // of protocol's meta-data (not a reference to it!)
6643 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006644 llvm::Constant *Init =
6645 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00006646 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006647
Akira Hatanaka187770d2019-05-09 17:43:52 +00006648 std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_");
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006649 ProtocolName += PD->getObjCRuntimeNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006650
John McCall7f416cc2015-09-08 08:05:57 +00006651 CharUnits Align = CGF.getPointerAlign();
6652
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006653 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
6654 if (PTGV)
John McCall7f416cc2015-09-08 08:05:57 +00006655 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Saleem Abdulrasool9f83f3b2017-06-29 00:54:44 +00006656 PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
6657 llvm::GlobalValue::WeakAnyLinkage, Init,
6658 ProtocolName);
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006659 PTGV->setSection(GetSectionName("__objc_protorefs",
6660 "coalesced,no_dead_strip"));
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006661 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006662 PTGV->setAlignment(Align.getAsAlign());
Saleem Abdulrasool9f83f3b2017-06-29 00:54:44 +00006663 if (!CGM.getTriple().isOSBinFormatMachO())
6664 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
Saleem Abdulrasoolbe2b5cb2018-01-23 19:35:51 +00006665 CGM.addUsedGlobal(PTGV);
John McCall7f416cc2015-09-08 08:05:57 +00006666 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006667}
6668
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006669/// GenerateCategory - Build metadata for a category implementation.
6670/// struct _category_t {
6671/// const char * const name;
6672/// struct _class_t *const cls;
6673/// const struct _method_list_t * const instance_methods;
6674/// const struct _method_list_t * const class_methods;
6675/// const struct _protocol_list_t * const protocols;
6676/// const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00006677/// const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00006678/// const uint32_t size;
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006679/// }
6680///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006681void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006682 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Akira Hatanaka187770d2019-05-09 17:43:52 +00006683 const char *Prefix = "_OBJC_$_CATEGORY_";
Fangrui Song6907ce22018-07-30 19:24:48 +00006684
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006685 llvm::SmallString<64> ExtCatName(Prefix);
6686 ExtCatName += Interface->getObjCRuntimeNameAsString();
6687 ExtCatName += "_$_";
6688 ExtCatName += OCD->getNameAsString();
Fangrui Song6907ce22018-07-30 19:24:48 +00006689
John McCall176f8922016-11-30 02:39:18 +00006690 ConstantInitBuilder builder(CGM);
6691 auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
6692 values.add(GetClassName(OCD->getIdentifier()->getName()));
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006693 // meta-class entry symbol
John McCalldba63a72016-11-30 23:54:50 +00006694 values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
John McCall176f8922016-11-30 02:39:18 +00006695 std::string listName =
Saleem Abdulrasool209150a2016-10-24 21:25:57 +00006696 (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006697
John McCall176f8922016-11-30 02:39:18 +00006698 SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
6699 SmallVector<const ObjCMethodDecl *, 8> classMethods;
6700 for (const auto *MD : OCD->methods()) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08006701 if (MD->isDirectMethod())
6702 continue;
John McCall176f8922016-11-30 02:39:18 +00006703 if (MD->isInstanceMethod()) {
6704 instanceMethods.push_back(MD);
6705 } else {
6706 classMethods.push_back(MD);
6707 }
6708 }
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006709
John McCall176f8922016-11-30 02:39:18 +00006710 values.add(emitMethodList(listName, MethodListType::CategoryInstanceMethods,
6711 instanceMethods));
6712 values.add(emitMethodList(listName, MethodListType::CategoryClassMethods,
6713 classMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006714
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006715 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00006716 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006717 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006718 SmallString<256> ExtName;
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006719 llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006720 << OCD->getName();
Akira Hatanaka187770d2019-05-09 17:43:52 +00006721 values.add(EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006722 + Interface->getObjCRuntimeNameAsString() + "_$_"
6723 + Category->getName(),
John McCall176f8922016-11-30 02:39:18 +00006724 Category->protocol_begin(),
6725 Category->protocol_end()));
Akira Hatanaka187770d2019-05-09 17:43:52 +00006726 values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00006727 OCD, Category, ObjCTypes, false));
Akira Hatanaka187770d2019-05-09 17:43:52 +00006728 values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00006729 OCD, Category, ObjCTypes, true));
Mike Stump658fe022009-07-30 22:28:39 +00006730 } else {
John McCall176f8922016-11-30 02:39:18 +00006731 values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
6732 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6733 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006734 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006735
Manman Ren42ff3902016-02-24 17:49:50 +00006736 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
John McCall176f8922016-11-30 02:39:18 +00006737 values.addInt(ObjCTypes.IntTy, Size);
Manman Ren42ff3902016-02-24 17:49:50 +00006738
John McCall176f8922016-11-30 02:39:18 +00006739 llvm::GlobalVariable *GCATV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00006740 finishAndCreateGlobal(values, ExtCatName.str(), CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00006741 CGM.addCompilerUsedGlobal(GCATV);
John McCall2c91c3b2019-05-30 04:09:01 +00006742 if (Interface->hasAttr<ObjCClassStubAttr>())
6743 DefinedStubCategories.push_back(GCATV);
6744 else
6745 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006746
6747 // Determine if this category is also "non-lazy".
6748 if (ImplementationIsNonLazy(OCD))
6749 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006750 // method definition entries must be clear for next implementation.
6751 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006752}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006753
John McCall176f8922016-11-30 02:39:18 +00006754/// emitMethodConstant - Return a struct objc_method constant. If
6755/// forProtocol is true, the implementation will be null; otherwise,
6756/// the method must have a definition registered with the runtime.
6757///
6758/// struct _objc_method {
6759/// SEL _cmd;
6760/// char *method_type;
6761/// char *_imp;
6762/// }
6763void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
6764 const ObjCMethodDecl *MD,
6765 bool forProtocol) {
6766 auto method = builder.beginStruct(ObjCTypes.MethodTy);
6767 method.addBitCast(GetMethodVarName(MD->getSelector()),
6768 ObjCTypes.SelectorPtrTy);
6769 method.add(GetMethodVarType(MD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006770
John McCall176f8922016-11-30 02:39:18 +00006771 if (forProtocol) {
6772 // Protocol methods have no implementation. So, this entry is always NULL.
6773 method.addNullPointer(ObjCTypes.Int8PtrTy);
6774 } else {
6775 llvm::Function *fn = GetMethodDefinition(MD);
6776 assert(fn && "no definition for method?");
6777 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
6778 }
6779
6780 method.finishAndAddTo(builder);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006781}
6782
John McCall176f8922016-11-30 02:39:18 +00006783/// Build meta-data for method declarations.
6784///
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006785/// struct _method_list_t {
6786/// uint32_t entsize; // sizeof(struct _objc_method)
6787/// uint32_t method_count;
6788/// struct _objc_method method_list[method_count];
6789/// }
6790///
Zachary Turner41a9ee92017-10-11 23:54:34 +00006791llvm::Constant *
6792CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
6793 ArrayRef<const ObjCMethodDecl *> methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006794 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006795 if (methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006796 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006797
John McCall176f8922016-11-30 02:39:18 +00006798 StringRef prefix;
6799 bool forProtocol;
6800 switch (kind) {
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006801 case MethodListType::CategoryInstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006802 prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006803 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006804 break;
6805 case MethodListType::CategoryClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006806 prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006807 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006808 break;
6809 case MethodListType::InstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006810 prefix = "_OBJC_$_INSTANCE_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006811 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006812 break;
6813 case MethodListType::ClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006814 prefix = "_OBJC_$_CLASS_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006815 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006816 break;
6817
6818 case MethodListType::ProtocolInstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006819 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006820 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006821 break;
6822 case MethodListType::ProtocolClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006823 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006824 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006825 break;
6826 case MethodListType::OptionalProtocolInstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006827 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_";
John McCall176f8922016-11-30 02:39:18 +00006828 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006829 break;
6830 case MethodListType::OptionalProtocolClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006831 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_";
John McCall176f8922016-11-30 02:39:18 +00006832 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006833 break;
6834 }
6835
John McCall176f8922016-11-30 02:39:18 +00006836 ConstantInitBuilder builder(CGM);
6837 auto values = builder.beginStruct();
6838
6839 // sizeof(struct _objc_method)
6840 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
6841 values.addInt(ObjCTypes.IntTy, Size);
6842 // method_count
6843 values.addInt(ObjCTypes.IntTy, methods.size());
6844 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
Adrian Prantl2073dd22019-11-04 14:28:14 -08006845 for (auto MD : methods)
John McCall176f8922016-11-30 02:39:18 +00006846 emitMethodConstant(methodArray, MD, forProtocol);
John McCall176f8922016-11-30 02:39:18 +00006847 methodArray.finishAndAddTo(values);
6848
Akira Hatanaka187770d2019-05-09 17:43:52 +00006849 llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00006850 CGM.addCompilerUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006851 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006852}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006853
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006854/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6855/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006856llvm::GlobalVariable *
6857CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6858 const ObjCIvarDecl *Ivar) {
6859 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006860 llvm::SmallString<64> Name("OBJC_IVAR_$_");
6861 Name += Container->getObjCRuntimeNameAsString();
6862 Name += ".";
6863 Name += Ivar->getName();
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006864 llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
6865 if (!IvarOffsetGV) {
6866 IvarOffsetGV =
6867 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy,
6868 false, llvm::GlobalValue::ExternalLinkage,
6869 nullptr, Name.str());
6870 if (CGM.getTriple().isOSBinFormatCOFF()) {
6871 bool IsPrivateOrPackage =
6872 Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6873 Ivar->getAccessControl() == ObjCIvarDecl::Package;
6874
Saleem Abdulrasoolad75c7d2017-10-25 03:58:15 +00006875 const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();
6876
6877 if (ContainingID->hasAttr<DLLImportAttr>())
6878 IvarOffsetGV
6879 ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
6880 else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
6881 IvarOffsetGV
6882 ->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006883 }
6884 }
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006885 return IvarOffsetGV;
6886}
6887
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006888llvm::Constant *
6889CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6890 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00006891 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006892 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Tim Northover238b5082014-03-29 13:42:40 +00006893 IvarOffsetGV->setInitializer(
6894 llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006895 IvarOffsetGV->setAlignment(llvm::Align(
6896 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy)));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006897
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006898 if (!CGM.getTriple().isOSBinFormatCOFF()) {
6899 // FIXME: This matches gcc, but shouldn't the visibility be set on the use
6900 // as well (i.e., in ObjCIvarOffsetVariable).
6901 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6902 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6903 ID->getVisibility() == HiddenVisibility)
6904 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6905 else
6906 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
6907 }
6908
Erik Pilkington2ff012d2019-01-17 18:18:53 +00006909 // If ID's layout is known, then make the global constant. This serves as a
6910 // useful assertion: we'll never use this variable to calculate ivar offsets,
6911 // so if the runtime tries to patch it then we should crash.
6912 if (isClassLayoutKnownStatically(ID))
6913 IvarOffsetGV->setConstant(true);
6914
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006915 if (CGM.getTriple().isOSBinFormatMachO())
6916 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006917 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006918}
6919
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006920/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006921/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006922/// IvarListnfABIPtrTy.
6923/// struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00006924/// unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006925/// char *name;
6926/// char *type;
6927/// uint32_t alignment;
6928/// uint32_t size;
6929/// }
6930/// struct _ivar_list_t {
6931/// uint32 entsize; // sizeof(struct _ivar_t)
6932/// uint32 count;
6933/// struct _iver_t list[count];
6934/// }
6935///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00006936
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006937llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006938 const ObjCImplementationDecl *ID) {
6939
John McCall176f8922016-11-30 02:39:18 +00006940 ConstantInitBuilder builder(CGM);
6941 auto ivarList = builder.beginStruct();
6942 ivarList.addInt(ObjCTypes.IntTy,
6943 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
6944 auto ivarCountSlot = ivarList.addPlaceholder();
6945 auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006946
Jordy Rosea91768e2011-07-22 02:08:32 +00006947 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006948 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006949
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006950 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006951
Fangrui Song6907ce22018-07-30 19:24:48 +00006952 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00006953 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00006954 // Ignore unnamed bit-fields.
6955 if (!IVD->getDeclName())
6956 continue;
John McCall176f8922016-11-30 02:39:18 +00006957
6958 auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
6959 ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
6960 ComputeIvarBaseOffset(CGM, ID, IVD)));
6961 ivar.add(GetMethodVarName(IVD->getIdentifier()));
6962 ivar.add(GetMethodVarType(IVD));
Chris Lattner2192fe52011-07-18 04:24:23 +00006963 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006964 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmowdd31ca12012-10-08 16:25:52 +00006965 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006966 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006967 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006968 Align = llvm::Log2_32(Align);
John McCall176f8922016-11-30 02:39:18 +00006969 ivar.addInt(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00006970 // NOTE. Size of a bitfield does not match gcc's, because of the
6971 // way bitfields are treated special in each. But I am told that
6972 // 'size' for bitfield ivars is ignored by the runtime so it does
6973 // not matter. If it matters, there is enough info to get the
6974 // bitfield right!
John McCall176f8922016-11-30 02:39:18 +00006975 ivar.addInt(ObjCTypes.IntTy, Size);
6976 ivar.finishAndAddTo(ivars);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006977 }
6978 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006979 if (ivars.empty()) {
6980 ivars.abandon();
6981 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00006982 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCall176f8922016-11-30 02:39:18 +00006983 }
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006984
John McCall176f8922016-11-30 02:39:18 +00006985 auto ivarCount = ivars.size();
6986 ivars.finishAndAddTo(ivarList);
6987 ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
6988
Akira Hatanaka187770d2019-05-09 17:43:52 +00006989 const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_";
6990 llvm::GlobalVariable *GV = finishAndCreateGlobal(
6991 ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00006992 CGM.addCompilerUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00006993 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006994}
6995
6996llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006997 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006998 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006999
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007000 if (!Entry) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007001 // We use the initializer as a marker of whether this is a forward
7002 // reference or not. At module finalization we add the empty
7003 // contents for protocols which were referenced but never defined.
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007004 llvm::SmallString<64> Protocol;
Akira Hatanaka6bc3a772019-03-14 15:17:37 +00007005 llvm::raw_svector_ostream(Protocol) << "_OBJC_PROTOCOL_$_"
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007006 << PD->getObjCRuntimeNameAsString();
7007
7008 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
7009 false, llvm::GlobalValue::ExternalLinkage,
7010 nullptr, Protocol);
7011 if (!CGM.getTriple().isOSBinFormatMachO())
7012 Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
7013 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007014
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007015 return Entry;
7016}
7017
7018/// GetOrEmitProtocol - Generate the protocol meta-data:
7019/// @code
7020/// struct _protocol_t {
7021/// id isa; // NULL
7022/// const char * const protocol_name;
7023/// const struct _protocol_list_t * protocol_list; // super protocols
7024/// const struct method_list_t * const instance_methods;
7025/// const struct method_list_t * const class_methods;
7026/// const struct method_list_t *optionalInstanceMethods;
7027/// const struct method_list_t *optionalClassMethods;
7028/// const struct _prop_list_t * properties;
7029/// const uint32_t size; // sizeof(struct _protocol_t)
7030/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00007031/// const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00007032/// const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00007033/// const struct _prop_list_t * class_properties;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007034/// }
7035/// @endcode
7036///
7037
7038llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007039 const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00007040 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007041
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007042 // Early exit if a defining object has already been generated.
7043 if (Entry && Entry->hasInitializer())
7044 return Entry;
7045
Douglas Gregora715bff2012-01-01 19:51:50 +00007046 // Use the protocol definition, if there is one.
Alex Lorenzb111da12018-08-17 22:18:08 +00007047 assert(PD->hasDefinition() &&
7048 "emitting protocol metadata without definition");
7049 PD = PD->getDefinition();
Fangrui Song6907ce22018-07-30 19:24:48 +00007050
John McCall176f8922016-11-30 02:39:18 +00007051 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007052
John McCall176f8922016-11-30 02:39:18 +00007053 ConstantInitBuilder builder(CGM);
7054 auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
Douglas Gregora9d84932011-05-27 01:19:52 +00007055
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007056 // isa is NULL
John McCall176f8922016-11-30 02:39:18 +00007057 values.addNullPointer(ObjCTypes.ObjectPtrTy);
7058 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
Akira Hatanaka187770d2019-05-09 17:43:52 +00007059 values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_"
John McCall176f8922016-11-30 02:39:18 +00007060 + PD->getObjCRuntimeNameAsString(),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007061 PD->protocol_begin(),
John McCall176f8922016-11-30 02:39:18 +00007062 PD->protocol_end()));
7063 values.add(methodLists.emitMethodList(this, PD,
7064 ProtocolMethodLists::RequiredInstanceMethods));
7065 values.add(methodLists.emitMethodList(this, PD,
7066 ProtocolMethodLists::RequiredClassMethods));
7067 values.add(methodLists.emitMethodList(this, PD,
7068 ProtocolMethodLists::OptionalInstanceMethods));
7069 values.add(methodLists.emitMethodList(this, PD,
7070 ProtocolMethodLists::OptionalClassMethods));
7071 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00007072 "_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00007073 nullptr, PD, ObjCTypes, false));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007074 uint32_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00007075 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
John McCall176f8922016-11-30 02:39:18 +00007076 values.addInt(ObjCTypes.IntTy, Size);
7077 values.addInt(ObjCTypes.IntTy, 0);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007078 values.add(EmitProtocolMethodTypes("_OBJC_$_PROTOCOL_METHOD_TYPES_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007079 + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00007080 methodLists.emitExtendedTypesArray(this),
7081 ObjCTypes));
7082
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00007083 // const char *demangledName;
John McCall176f8922016-11-30 02:39:18 +00007084 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Rence7bff52016-01-29 23:46:55 +00007085
John McCall176f8922016-11-30 02:39:18 +00007086 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00007087 "_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00007088 nullptr, PD, ObjCTypes, true));
Fangrui Song6907ce22018-07-30 19:24:48 +00007089
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007090 if (Entry) {
Rafael Espindola24615092014-09-12 20:14:20 +00007091 // Already created, fix the linkage and update the initializer.
7092 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
John McCall176f8922016-11-30 02:39:18 +00007093 values.finishAndSetAsInitializer(Entry);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007094 } else {
John McCall176f8922016-11-30 02:39:18 +00007095 llvm::SmallString<64> symbolName;
7096 llvm::raw_svector_ostream(symbolName)
Akira Hatanaka6bc3a772019-03-14 15:17:37 +00007097 << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007098
John McCall176f8922016-11-30 02:39:18 +00007099 Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
7100 /*constant*/ false,
7101 llvm::GlobalValue::WeakAnyLinkage);
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007102 if (!CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00007103 Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
John McCallf9582a72012-03-30 21:29:05 +00007104
7105 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007106 }
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007107 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoolbe2b5cb2018-01-23 19:35:51 +00007108 CGM.addUsedGlobal(Entry);
Chris Lattnerf56501c2009-07-17 23:57:13 +00007109
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00007110 // Use this protocol meta-data to build protocol list table in section
7111 // __DATA, __objc_protolist
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007112 llvm::SmallString<64> ProtocolRef;
Akira Hatanaka6bc3a772019-03-14 15:17:37 +00007113 llvm::raw_svector_ostream(ProtocolRef) << "_OBJC_LABEL_PROTOCOL_$_"
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007114 << PD->getObjCRuntimeNameAsString();
7115
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007116 llvm::GlobalVariable *PTGV =
7117 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007118 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007119 ProtocolRef);
7120 if (!CGM.getTriple().isOSBinFormatMachO())
7121 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007122 PTGV->setAlignment(llvm::Align(
7123 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)));
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00007124 PTGV->setSection(GetSectionName("__objc_protolist",
7125 "coalesced,no_dead_strip"));
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007126 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoolbe2b5cb2018-01-23 19:35:51 +00007127 CGM.addUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007128 return Entry;
7129}
7130
7131/// EmitProtocolList - Generate protocol list meta-data:
7132/// @code
7133/// struct _protocol_list_t {
7134/// long protocol_count; // Note, this is 32/64 bit
7135/// struct _protocol_t[protocol_count];
7136/// }
7137/// @endcode
7138///
Zachary Turner41a9ee92017-10-11 23:54:34 +00007139llvm::Constant *
7140CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
7141 ObjCProtocolDecl::protocol_iterator begin,
7142 ObjCProtocolDecl::protocol_iterator end) {
Dmitri Gribenkof8579502013-01-12 19:30:44 +00007143 SmallVector<llvm::Constant *, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007144
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007145 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007146 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00007147 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007148
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007149 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00007150 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007151 Name.toVector(TmpName);
7152 llvm::GlobalVariable *GV =
7153 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007154 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007155 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007156
John McCall176f8922016-11-30 02:39:18 +00007157 ConstantInitBuilder builder(CGM);
7158 auto values = builder.beginStruct();
7159 auto countSlot = values.addPlaceholder();
7160
7161 // A null-terminated array of protocols.
7162 auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007163 for (; begin != end; ++begin)
John McCall176f8922016-11-30 02:39:18 +00007164 array.add(GetProtocolRef(*begin)); // Implemented???
7165 auto count = array.size();
7166 array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007167
John McCall176f8922016-11-30 02:39:18 +00007168 array.finishAndAddTo(values);
7169 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007170
Akira Hatanaka187770d2019-05-09 17:43:52 +00007171 GV = finishAndCreateGlobal(values, Name, CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00007172 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007173 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007174 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007175}
7176
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00007177/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
7178/// This code gen. amounts to generating code for:
7179/// @code
7180/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
7181/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007182///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00007183LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00007184 CodeGen::CodeGenFunction &CGF,
7185 QualType ObjectTy,
7186 llvm::Value *BaseValue,
7187 const ObjCIvarDecl *Ivar,
7188 unsigned CVRQualifiers) {
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00007189 ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00007190 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00007191 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00007192 Offset);
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00007193}
7194
Erik Pilkington2ff012d2019-01-17 18:18:53 +00007195llvm::Value *
7196CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
7197 const ObjCInterfaceDecl *Interface,
7198 const ObjCIvarDecl *Ivar) {
7199 llvm::Value *IvarOffsetValue;
7200 if (isClassLayoutKnownStatically(Interface)) {
7201 IvarOffsetValue = llvm::ConstantInt::get(
7202 ObjCTypes.IvarOffsetVarTy,
7203 ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar));
7204 } else {
7205 llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
7206 IvarOffsetValue =
7207 CGF.Builder.CreateAlignedLoad(GV, CGF.getSizeAlign(), "ivar");
7208 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
7209 cast<llvm::LoadInst>(IvarOffsetValue)
7210 ->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
7211 llvm::MDNode::get(VMContext, None));
7212 }
Tim Northover238b5082014-03-29 13:42:40 +00007213
7214 // This could be 32bit int or 64bit integer depending on the architecture.
7215 // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007216 // as this is what caller always expects.
Tim Northover238b5082014-03-29 13:42:40 +00007217 if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
7218 IvarOffsetValue = CGF.Builder.CreateIntCast(
7219 IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
7220 return IvarOffsetValue;
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00007221}
7222
John McCall234eac82011-05-13 23:16:18 +00007223static void appendSelectorForMessageRefTable(std::string &buffer,
7224 Selector selector) {
7225 if (selector.isUnarySelector()) {
7226 buffer += selector.getNameForSlot(0);
7227 return;
7228 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007229
John McCall234eac82011-05-13 23:16:18 +00007230 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
7231 buffer += selector.getNameForSlot(i);
7232 buffer += '_';
7233 }
7234}
7235
Eric Christopherd160c502016-01-29 01:35:53 +00007236/// Emit a "vtable" message send. We emit a weak hidden-visibility
John McCall9e8bb002011-05-14 03:10:52 +00007237/// struct, initially containing the selector pointer and a pointer to
7238/// a "fixup" variant of the appropriate objc_msgSend. To call, we
7239/// load and call the function pointer, passing the address of the
7240/// struct as the second parameter. The runtime determines whether
7241/// the selector is currently emitted using vtable dispatch; if so, it
7242/// substitutes a stub function which simply tail-calls through the
7243/// appropriate vtable slot, and if not, it substitues a stub function
7244/// which tail-calls objc_msgSend. Both stubs adjust the selector
7245/// argument to correctly point to the selector.
7246RValue
7247CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
7248 ReturnValueSlot returnSlot,
7249 QualType resultType,
7250 Selector selector,
7251 llvm::Value *arg0,
7252 QualType arg0Type,
7253 bool isSuper,
7254 const CallArgList &formalArgs,
7255 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00007256 // Compute the actual arguments.
7257 CallArgList args;
7258
John McCall9e8bb002011-05-14 03:10:52 +00007259 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00007260 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00007261 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
7262 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00007263
John McCall9e8bb002011-05-14 03:10:52 +00007264 // Second argument: a pointer to the message ref structure. Leave
7265 // the actual argument value blank for now.
Craig Topper8a13c412014-05-21 05:09:00 +00007266 args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
John McCall234eac82011-05-13 23:16:18 +00007267
7268 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
7269
John McCalla729c622012-02-17 03:33:10 +00007270 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCall234eac82011-05-13 23:16:18 +00007271
John McCall5880fb82011-05-14 21:12:11 +00007272 NullReturnState nullReturn;
7273
John McCall9e8bb002011-05-14 03:10:52 +00007274 // Find the function to call and the mangled name for the message
7275 // ref structure. Using a different mangled name wouldn't actually
7276 // be a problem; it would just be a waste.
7277 //
7278 // The runtime currently never uses vtable dispatch for anything
7279 // except normal, non-super message-sends.
7280 // FIXME: don't use this for that.
James Y Knight9871db02019-02-05 16:42:33 +00007281 llvm::FunctionCallee fn = nullptr;
Akira Hatanaka187770d2019-05-09 17:43:52 +00007282 std::string messageRefName("_");
Tim Northovere77cc392014-03-29 13:28:05 +00007283 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
John McCall234eac82011-05-13 23:16:18 +00007284 if (isSuper) {
7285 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
7286 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007287 } else {
John McCall5880fb82011-05-14 21:12:11 +00007288 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00007289 fn = ObjCTypes.getMessageSendStretFixupFn();
7290 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007291 }
John McCall234eac82011-05-13 23:16:18 +00007292 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
7293 fn = ObjCTypes.getMessageSendFpretFixupFn();
7294 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00007295 } else {
John McCall234eac82011-05-13 23:16:18 +00007296 if (isSuper) {
7297 fn = ObjCTypes.getMessageSendSuper2FixupFn();
7298 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007299 } else {
John McCall234eac82011-05-13 23:16:18 +00007300 fn = ObjCTypes.getMessageSendFixupFn();
7301 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007302 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00007303 }
John McCall234eac82011-05-13 23:16:18 +00007304 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
7305 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007306
John McCall234eac82011-05-13 23:16:18 +00007307 // Append the selector name, except use underscores anywhere we
7308 // would have used colons.
7309 appendSelectorForMessageRefTable(messageRefName, selector);
7310
7311 llvm::GlobalVariable *messageRef
7312 = CGM.getModule().getGlobalVariable(messageRefName);
7313 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00007314 // Build the message ref structure.
John McCall176f8922016-11-30 02:39:18 +00007315 ConstantInitBuilder builder(CGM);
7316 auto values = builder.beginStruct();
James Y Knight9871db02019-02-05 16:42:33 +00007317 values.add(cast<llvm::Constant>(fn.getCallee()));
John McCall176f8922016-11-30 02:39:18 +00007318 values.add(GetMethodVarName(selector));
7319 messageRef = values.finishAndCreateGlobal(messageRefName,
7320 CharUnits::fromQuantity(16),
7321 /*constant*/ false,
7322 llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007323 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00007324 messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced"));
John McCall234eac82011-05-13 23:16:18 +00007325 }
Fangrui Song6907ce22018-07-30 19:24:48 +00007326
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00007327 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00007328 if (CGM.getLangOpts().ObjCAutoRefCount && method)
David Majnemer59f77922016-06-24 04:05:48 +00007329 for (const auto *ParamDecl : method->parameters()) {
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00007330 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
7331 if (!nullReturn.NullBB)
7332 nullReturn.init(CGF, arg0);
7333 requiresnullCheck = true;
7334 break;
7335 }
7336 }
Fangrui Song6907ce22018-07-30 19:24:48 +00007337
John McCall7f416cc2015-09-08 08:05:57 +00007338 Address mref =
7339 Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
7340 CGF.getPointerAlign());
John McCall234eac82011-05-13 23:16:18 +00007341
John McCall9e8bb002011-05-14 03:10:52 +00007342 // Update the message ref argument.
Yaxun Liu5b330e82018-03-15 15:25:19 +00007343 args[1].setRValue(RValue::get(mref.getPointer()));
John McCall234eac82011-05-13 23:16:18 +00007344
7345 // Load the function to call from the message ref table.
James Y Knight751fe282019-02-09 22:22:28 +00007346 Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0);
John McCallb92ab1a2016-10-26 23:46:34 +00007347 llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
John McCall234eac82011-05-13 23:16:18 +00007348
John McCallb92ab1a2016-10-26 23:46:34 +00007349 calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
7350 CGCallee callee(CGCalleeInfo(), calleePtr);
John McCall234eac82011-05-13 23:16:18 +00007351
John McCalla729c622012-02-17 03:33:10 +00007352 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Kuba Mracekbce5cea2017-06-30 16:28:15 +00007353 return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
Craig Topper8a13c412014-05-21 05:09:00 +00007354 requiresnullCheck ? method : nullptr);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007355}
7356
7357/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007358CodeGen::RValue
7359CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007360 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007361 QualType ResultType,
7362 Selector Sel,
7363 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007364 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00007365 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007366 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00007367 return isVTableDispatchedSelector(Sel)
7368 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007369 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00007370 false, CallArgs, Method)
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08007371 : EmitMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007372 Receiver, CGF.getContext().getObjCIdType(),
John McCall1e3157b2015-09-10 22:27:50 +00007373 false, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007374}
7375
John McCalldba63a72016-11-30 23:54:50 +00007376llvm::Constant *
7377CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
7378 bool metaclass,
7379 ForDefinition_t isForDefinition) {
7380 auto prefix =
7381 (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
7382 return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
7383 isForDefinition,
7384 ID->isWeakImported(),
7385 !isForDefinition
7386 && CGM.getTriple().isOSBinFormatCOFF()
7387 && ID->hasAttr<DLLImportAttr>());
7388}
7389
7390llvm::Constant *
7391CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
7392 ForDefinition_t IsForDefinition,
7393 bool Weak, bool DLLImport) {
Rafael Espindola554256c2014-02-26 22:25:45 +00007394 llvm::GlobalValue::LinkageTypes L =
7395 Weak ? llvm::GlobalValue::ExternalWeakLinkage
7396 : llvm::GlobalValue::ExternalLinkage;
7397
John McCalldba63a72016-11-30 23:54:50 +00007398 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
Erik Pilkington92d8a292018-10-12 17:22:10 +00007399 if (!GV || GV->getType() != ObjCTypes.ClassnfABITy->getPointerTo()) {
7400 auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
7401 nullptr, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007402
John McCalldba63a72016-11-30 23:54:50 +00007403 if (DLLImport)
Erik Pilkington92d8a292018-10-12 17:22:10 +00007404 NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
7405
7406 if (GV) {
7407 GV->replaceAllUsesWith(
7408 llvm::ConstantExpr::getBitCast(NewGV, GV->getType()));
7409 GV->eraseFromParent();
7410 }
7411 GV = NewGV;
7412 CGM.getModule().getGlobalList().push_back(GV);
John McCalldba63a72016-11-30 23:54:50 +00007413 }
7414
Rafael Espindola554256c2014-02-26 22:25:45 +00007415 assert(GV->getLinkage() == L);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007416 return GV;
7417}
7418
John McCall2c91c3b2019-05-30 04:09:01 +00007419llvm::Constant *
7420CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
7421 llvm::Constant *ClassGV = GetClassGlobal(ID, /*metaclass*/ false,
7422 NotForDefinition);
7423
7424 if (!ID->hasAttr<ObjCClassStubAttr>())
7425 return ClassGV;
7426
7427 ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy);
7428
7429 // Stub classes are pointer-aligned. Classrefs pointing at stub classes
7430 // must set the least significant bit set to 1.
7431 auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
7432 return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx);
7433}
7434
7435llvm::Value *
7436CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF,
7437 const ObjCInterfaceDecl *ID,
7438 llvm::GlobalVariable *Entry) {
7439 if (ID && ID->hasAttr<ObjCClassStubAttr>()) {
7440 // Classrefs pointing at Objective-C stub classes must be loaded by calling
7441 // a special runtime function.
7442 return CGF.EmitRuntimeCall(
7443 ObjCTypes.getLoadClassrefFn(), Entry, "load_classref_result");
7444 }
7445
7446 CharUnits Align = CGF.getPointerAlign();
7447 return CGF.Builder.CreateAlignedLoad(Entry, Align);
7448}
7449
John McCalldba63a72016-11-30 23:54:50 +00007450llvm::Value *
7451CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
7452 IdentifierInfo *II,
7453 const ObjCInterfaceDecl *ID) {
John McCall31168b02011-06-15 23:02:42 +00007454 llvm::GlobalVariable *&Entry = ClassReferences[II];
Fangrui Song6907ce22018-07-30 19:24:48 +00007455
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007456 if (!Entry) {
John McCalldba63a72016-11-30 23:54:50 +00007457 llvm::Constant *ClassGV;
7458 if (ID) {
John McCall2c91c3b2019-05-30 04:09:01 +00007459 ClassGV = GetClassGlobalForClassRef(ID);
John McCalldba63a72016-11-30 23:54:50 +00007460 } else {
7461 ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
7462 NotForDefinition);
John McCall2c91c3b2019-05-30 04:09:01 +00007463 assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy &&
7464 "classref was emitted with the wrong type?");
John McCalldba63a72016-11-30 23:54:50 +00007465 }
7466
Akira Hatanaka187770d2019-05-09 17:43:52 +00007467 std::string SectionName =
7468 GetSectionName("__objc_classrefs", "regular,no_dead_strip");
7469 Entry = new llvm::GlobalVariable(
John McCall2c91c3b2019-05-30 04:09:01 +00007470 CGM.getModule(), ClassGV->getType(), false,
Akira Hatanaka187770d2019-05-09 17:43:52 +00007471 getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
7472 "OBJC_CLASSLIST_REFERENCES_$_");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007473 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
John McCall2c91c3b2019-05-30 04:09:01 +00007474 if (!ID || !ID->hasAttr<ObjCClassStubAttr>())
7475 Entry->setSection(SectionName);
7476
Rafael Espindola060062a2014-03-06 22:15:10 +00007477 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007478 }
John McCall2c91c3b2019-05-30 04:09:01 +00007479
7480 return EmitLoadOfClassRef(CGF, ID, Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007481}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007482
John McCall882987f2013-02-28 19:01:20 +00007483llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00007484 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00007485 // If the class has the objc_runtime_visible attribute, we need to
7486 // use the Objective-C runtime to get the class.
7487 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
7488 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
7489
John McCalldba63a72016-11-30 23:54:50 +00007490 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
John McCall31168b02011-06-15 23:02:42 +00007491}
7492
7493llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
John McCall882987f2013-02-28 19:01:20 +00007494 CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00007495 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
John McCalldba63a72016-11-30 23:54:50 +00007496 return EmitClassRefFromId(CGF, II, nullptr);
John McCall31168b02011-06-15 23:02:42 +00007497}
7498
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007499llvm::Value *
John McCall882987f2013-02-28 19:01:20 +00007500CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007501 const ObjCInterfaceDecl *ID) {
7502 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007503
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007504 if (!Entry) {
John McCall2c91c3b2019-05-30 04:09:01 +00007505 llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007506 std::string SectionName =
7507 GetSectionName("__objc_superrefs", "regular,no_dead_strip");
7508 Entry = new llvm::GlobalVariable(
John McCall2c91c3b2019-05-30 04:09:01 +00007509 CGM.getModule(), ClassGV->getType(), false,
Akira Hatanaka187770d2019-05-09 17:43:52 +00007510 getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
7511 "OBJC_CLASSLIST_SUP_REFS_$_");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007512 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
Akira Hatanaka187770d2019-05-09 17:43:52 +00007513 Entry->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00007514 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007515 }
John McCall2c91c3b2019-05-30 04:09:01 +00007516
7517 return EmitLoadOfClassRef(CGF, ID, Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007518}
7519
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007520/// EmitMetaClassRef - Return a Value * of the address of _class_t
7521/// meta-data
7522///
John McCall882987f2013-02-28 19:01:20 +00007523llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00007524 const ObjCInterfaceDecl *ID,
7525 bool Weak) {
John McCall7f416cc2015-09-08 08:05:57 +00007526 CharUnits Align = CGF.getPointerAlign();
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007527 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
Rafael Espindola21039aa2014-02-27 16:26:32 +00007528 if (!Entry) {
John McCalldba63a72016-11-30 23:54:50 +00007529 auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007530 std::string SectionName =
7531 GetSectionName("__objc_superrefs", "regular,no_dead_strip");
7532 Entry = new llvm::GlobalVariable(
7533 CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
7534 getLinkageTypeForObjCMetadata(CGM, SectionName), MetaClassGV,
7535 "OBJC_CLASSLIST_SUP_REFS_$_");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007536 Entry->setAlignment(Align.getAsAlign());
Akira Hatanaka187770d2019-05-09 17:43:52 +00007537 Entry->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00007538 CGM.addCompilerUsedGlobal(Entry);
Rafael Espindola21039aa2014-02-27 16:26:32 +00007539 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007540
John McCall7f416cc2015-09-08 08:05:57 +00007541 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007542}
7543
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007544/// GetClass - Return a reference to the class for the given interface
7545/// decl.
John McCall882987f2013-02-28 19:01:20 +00007546llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007547 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00007548 if (ID->isWeakImported()) {
John McCalldba63a72016-11-30 23:54:50 +00007549 auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
Nick Lewycky9a441642014-02-27 00:36:00 +00007550 (void)ClassGV;
John McCalldba63a72016-11-30 23:54:50 +00007551 assert(!isa<llvm::GlobalVariable>(ClassGV) ||
7552 cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
Fariborz Jahanian95ace552009-11-17 22:42:00 +00007553 }
Fangrui Song6907ce22018-07-30 19:24:48 +00007554
John McCall882987f2013-02-28 19:01:20 +00007555 return EmitClassRef(CGF, ID);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007556}
7557
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007558/// Generates a message send where the super is the receiver. This is
7559/// a message send to self with special delivery semantics indicating
7560/// which class's method should be called.
7561CodeGen::RValue
7562CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007563 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007564 QualType ResultType,
7565 Selector Sel,
7566 const ObjCInterfaceDecl *Class,
7567 bool isCategoryImpl,
7568 llvm::Value *Receiver,
7569 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007570 const CodeGen::CallArgList &CallArgs,
7571 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007572 // ...
7573 // Create and init a super structure; this is a (receiver, class)
7574 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00007575 Address ObjCSuper =
7576 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
7577 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007578
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007579 llvm::Value *ReceiverAsObject =
7580 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
James Y Knight751fe282019-02-09 22:22:28 +00007581 CGF.Builder.CreateStore(ReceiverAsObject,
7582 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007583
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007584 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00007585 llvm::Value *Target;
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007586 if (IsClassMessage)
Fariborz Jahanian85b99da2014-08-28 17:05:17 +00007587 Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007588 else
John McCall882987f2013-02-28 19:01:20 +00007589 Target = EmitSuperClassRef(CGF, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007590
Mike Stump18bb9282009-05-16 07:57:57 +00007591 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
7592 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00007593 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007594 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
7595 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
James Y Knight751fe282019-02-09 22:22:28 +00007596 CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007597
John McCall9e8bb002011-05-14 03:10:52 +00007598 return (isVTableDispatchedSelector(Sel))
7599 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
John McCall7f416cc2015-09-08 08:05:57 +00007600 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00007601 true, CallArgs, Method)
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08007602 : EmitMessageSend(CGF, Return, ResultType, Sel,
John McCall7f416cc2015-09-08 08:05:57 +00007603 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall1e3157b2015-09-10 22:27:50 +00007604 true, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007605}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007606
John McCall882987f2013-02-28 19:01:20 +00007607llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007608 Selector Sel) {
7609 Address Addr = EmitSelectorAddr(CGF, Sel);
7610
7611 llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
Fangrui Song6907ce22018-07-30 19:24:48 +00007612 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
John McCall7f416cc2015-09-08 08:05:57 +00007613 llvm::MDNode::get(VMContext, None));
7614 return LI;
7615}
7616
7617Address CGObjCNonFragileABIMac::EmitSelectorAddr(CodeGenFunction &CGF,
7618 Selector Sel) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007619 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007620
John McCall7f416cc2015-09-08 08:05:57 +00007621 CharUnits Align = CGF.getPointerAlign();
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007622 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007623 llvm::Constant *Casted =
7624 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
7625 ObjCTypes.SelectorPtrTy);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007626 std::string SectionName =
7627 GetSectionName("__objc_selrefs", "literal_pointers,no_dead_strip");
7628 Entry = new llvm::GlobalVariable(
7629 CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
7630 getLinkageTypeForObjCMetadata(CGM, SectionName), Casted,
7631 "OBJC_SELECTOR_REFERENCES_");
Michael Gottesman5c205962013-02-05 23:08:45 +00007632 Entry->setExternallyInitialized(true);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007633 Entry->setSection(SectionName);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007634 Entry->setAlignment(Align.getAsAlign());
Rafael Espindola060062a2014-03-06 22:15:10 +00007635 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007636 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007637
John McCall7f416cc2015-09-08 08:05:57 +00007638 return Address(Entry, Align);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007639}
John McCall7f416cc2015-09-08 08:05:57 +00007640
Fariborz Jahanian06292952009-02-16 22:52:32 +00007641/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007642/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00007643///
7644void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00007645 llvm::Value *src,
John McCall7f416cc2015-09-08 08:05:57 +00007646 Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007647 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007648 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007649 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007650 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007651 assert(Size <= 8 && "does not support size > 8");
7652 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7653 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007654 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7655 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007656 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7657 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007658 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00007659 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007660}
7661
7662/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
7663/// objc_assign_strongCast (id src, id *dst)
7664///
7665void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007666 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007667 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007668 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007669 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007670 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007671 assert(Size <= 8 && "does not support size > 8");
7672 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007673 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007674 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7675 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007676 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7677 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007678 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007679 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
7680 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007681}
7682
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007683void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007684 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007685 Address DestPtr,
7686 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00007687 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007688 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
7689 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007690 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size };
John McCall882987f2013-02-28 19:01:20 +00007691 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007692}
7693
Fariborz Jahanian06292952009-02-16 22:52:32 +00007694/// EmitObjCWeakRead - Code gen for loading value of a __weak
7695/// object: objc_read_weak (id *src)
7696///
7697llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007698 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007699 Address AddrWeakObj) {
7700 llvm::Type *DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007701 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00007702 llvm::Value *read_weak =
7703 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00007704 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00007705 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007706 return read_weak;
7707}
7708
7709/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
7710/// objc_assign_weak (id src, id *dst)
7711///
7712void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007713 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007714 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007715 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007716 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007717 assert(Size <= 8 && "does not support size > 8");
7718 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7719 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007720 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7721 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007722 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7723 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007724 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007725 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
7726 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007727}
7728
7729/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
7730/// objc_assign_global (id src, id *dst)
7731///
7732void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007733 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00007734 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007735 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007736 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007737 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007738 assert(Size <= 8 && "does not support size > 8");
7739 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7740 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007741 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7742 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007743 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7744 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007745 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00007746 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00007747 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
7748 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00007749 else
John McCall882987f2013-02-28 19:01:20 +00007750 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
7751 args, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007752}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007753
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007754void
John McCallbd309292010-07-06 01:34:17 +00007755CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
7756 const ObjCAtSynchronizedStmt &S) {
James Y Knight9871db02019-02-05 16:42:33 +00007757 EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(),
7758 ObjCTypes.getSyncExitFn());
John McCallbd309292010-07-06 01:34:17 +00007759}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007760
John McCall2ca705e2010-07-24 00:37:23 +00007761llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00007762CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00007763 // There's a particular fixed type info for 'id'.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007764 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
7765 auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007766 if (!IDEHType) {
John McCall2ca705e2010-07-24 00:37:23 +00007767 IDEHType =
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007768 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
7769 llvm::GlobalValue::ExternalLinkage, nullptr,
7770 "OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007771 if (CGM.getTriple().isOSBinFormatCOFF())
7772 IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id"));
7773 }
John McCall2ca705e2010-07-24 00:37:23 +00007774 return IDEHType;
7775 }
7776
7777 // All other types should be Objective-C interface pointer types.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007778 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
John McCall2ca705e2010-07-24 00:37:23 +00007779 assert(PT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007780
John McCall2ca705e2010-07-24 00:37:23 +00007781 const ObjCInterfaceType *IT = PT->getInterfaceType();
7782 assert(IT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007783
John McCalldba63a72016-11-30 23:54:50 +00007784 return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007785}
John McCall2ca705e2010-07-24 00:37:23 +00007786
John McCallbd309292010-07-06 01:34:17 +00007787void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
7788 const ObjCAtTryStmt &S) {
James Y Knight9871db02019-02-05 16:42:33 +00007789 EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(),
7790 ObjCTypes.getObjCEndCatchFn(),
7791 ObjCTypes.getExceptionRethrowFn());
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00007792}
7793
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007794/// EmitThrowStmt - Generate code for a throw statement.
7795void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007796 const ObjCAtThrowStmt &S,
7797 bool ClearInsertionPoint) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007798 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00007799 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00007800 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
James Y Knight3933add2019-01-30 02:54:28 +00007801 llvm::CallBase *Call =
7802 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception);
7803 Call->setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007804 } else {
James Y Knight3933add2019-01-30 02:54:28 +00007805 llvm::CallBase *Call =
7806 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn());
7807 Call->setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007808 }
7809
John McCall17afe452010-10-16 08:21:07 +00007810 CGF.Builder.CreateUnreachable();
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007811 if (ClearInsertionPoint)
7812 CGF.Builder.ClearInsertionPoint();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007813}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007814
John McCall2ca705e2010-07-24 00:37:23 +00007815llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007816CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
John McCalldba63a72016-11-30 23:54:50 +00007817 ForDefinition_t IsForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007818 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007819 StringRef ClassName = ID->getObjCRuntimeNameAsString();
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007820
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007821 // If we don't need a definition, return the entry if found or check
7822 // if we use an external reference.
John McCalldba63a72016-11-30 23:54:50 +00007823 if (!IsForDefinition) {
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007824 if (Entry)
7825 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00007826
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007827 // If this type (or a super class) has the __objc_exception__
7828 // attribute, emit an external reference.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007829 if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
7830 std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str();
7831 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
7832 false, llvm::GlobalValue::ExternalLinkage,
7833 nullptr, EHTypeName);
Rafael Espindolab7350042018-03-01 00:35:47 +00007834 CGM.setGVProperties(Entry, ID);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007835 return Entry;
7836 }
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007837 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007838
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007839 // Otherwise we need to either make a new entry or fill in the initializer.
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007840 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007841
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007842 std::string VTableName = "objc_ehtype_vtable";
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007843 auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007844 if (!VTableGV) {
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007845 VTableGV =
7846 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false,
7847 llvm::GlobalValue::ExternalLinkage, nullptr,
7848 VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007849 if (CGM.getTriple().isOSBinFormatCOFF())
7850 VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
7851 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007852
Chris Lattnerece04092012-02-07 00:39:47 +00007853 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
John McCall176f8922016-11-30 02:39:18 +00007854 ConstantInitBuilder builder(CGM);
7855 auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
Ahmed Bougacha5d0199a2017-11-17 19:46:47 +00007856 values.add(
7857 llvm::ConstantExpr::getInBoundsGetElementPtr(VTableGV->getValueType(),
7858 VTableGV, VTableIdx));
John McCalldba63a72016-11-30 23:54:50 +00007859 values.add(GetClassName(ClassName));
7860 values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007861
John McCalldba63a72016-11-30 23:54:50 +00007862 llvm::GlobalValue::LinkageTypes L = IsForDefinition
Rafael Espindola554256c2014-02-26 22:25:45 +00007863 ? llvm::GlobalValue::ExternalLinkage
7864 : llvm::GlobalValue::WeakAnyLinkage;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007865 if (Entry) {
John McCall176f8922016-11-30 02:39:18 +00007866 values.finishAndSetAsInitializer(Entry);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007867 Entry->setAlignment(CGM.getPointerAlign().getAsAlign());
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007868 } else {
John McCall176f8922016-11-30 02:39:18 +00007869 Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName,
7870 CGM.getPointerAlign(),
7871 /*constant*/ false,
7872 L);
Rafael Espindolab7350042018-03-01 00:35:47 +00007873 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
7874 CGM.setGVProperties(Entry, ID);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007875 }
Rafael Espindola554256c2014-02-26 22:25:45 +00007876 assert(Entry->getLinkage() == L);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007877
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007878 if (!CGM.getTriple().isOSBinFormatCOFF())
7879 if (ID->getVisibility() == HiddenVisibility)
7880 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007881
John McCalldba63a72016-11-30 23:54:50 +00007882 if (IsForDefinition)
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00007883 if (CGM.getTriple().isOSBinFormatMachO())
7884 Entry->setSection("__DATA,__objc_const");
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007885
7886 return Entry;
7887}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007888
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00007889/* *** */
7890
Daniel Dunbarb036db82008-08-13 03:21:16 +00007891CodeGen::CGObjCRuntime *
7892CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall5fb5df92012-06-20 06:18:46 +00007893 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7894 case ObjCRuntime::FragileMacOSX:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007895 return new CGObjCMac(CGM);
John McCall5fb5df92012-06-20 06:18:46 +00007896
7897 case ObjCRuntime::MacOSX:
7898 case ObjCRuntime::iOS:
Tim Northover756447a2015-10-30 16:30:36 +00007899 case ObjCRuntime::WatchOS:
John McCall5fb5df92012-06-20 06:18:46 +00007900 return new CGObjCNonFragileABIMac(CGM);
7901
David Chisnallb601c962012-07-03 20:49:52 +00007902 case ObjCRuntime::GNUstep:
7903 case ObjCRuntime::GCC:
John McCall775086e2012-07-12 02:07:58 +00007904 case ObjCRuntime::ObjFW:
John McCall5fb5df92012-06-20 06:18:46 +00007905 llvm_unreachable("these runtimes are not Mac runtimes");
7906 }
7907 llvm_unreachable("bad runtime");
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007908}