blob: 8e28b2f05c16739693864a81c90d601d6ec2f26f [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
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000877 /// PropertyNames - uniqued method variable names.
878 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000879
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000880 /// ClassReferences - uniqued class references.
881 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000882
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000883 /// SelectorReferences - uniqued selector references.
884 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000885
Daniel Dunbarb036db82008-08-13 03:21:16 +0000886 /// Protocols - Protocols for which an objc_protocol structure has
887 /// been emitted. Forward declarations are handled by creating an
888 /// empty structure whose initializer is filled in when/if defined.
889 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000890
Daniel Dunbarc475d422008-10-29 22:36:39 +0000891 /// DefinedProtocols - Protocols which have actually been
892 /// defined. We should not need this, see FIXME in GenerateProtocol.
893 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000894
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000895 /// DefinedClasses - List of defined classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000896 SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
Fangrui Song6907ce22018-07-30 19:24:48 +0000897
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +0000898 /// ImplementedClasses - List of @implemented classes.
899 SmallVector<const ObjCInterfaceDecl*, 16> ImplementedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000900
901 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000902 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000903
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000904 /// DefinedCategories - List of defined categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000905 SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000906
John McCall2c91c3b2019-05-30 04:09:01 +0000907 /// DefinedStubCategories - List of defined categories on class stubs.
908 SmallVector<llvm::GlobalValue*, 16> DefinedStubCategories;
909
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000910 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000911 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000912
John McCallcd21d542016-11-30 23:15:55 +0000913 /// Cached reference to the class for constant strings. This value has type
914 /// int * but is actually an Obj-C class pointer.
Sanjoy Dase369bd92017-05-01 17:08:00 +0000915 llvm::WeakTrackingVH ConstantStringClassRef;
John McCallcd21d542016-11-30 23:15:55 +0000916
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000917 /// The LLVM type corresponding to NSConstantString.
John McCallcd21d542016-11-30 23:15:55 +0000918 llvm::StructType *NSConstantStringType = nullptr;
919
920 llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
921
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000922 /// GetNameForMethod - Return a name for the given method.
923 /// \param[out] NameOut - The return value.
924 void GetNameForMethod(const ObjCMethodDecl *OMD,
925 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000926 SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000927
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000928 /// GetMethodVarName - Return a unique constant for the given
929 /// selector's name. The return value has type char *.
930 llvm::Constant *GetMethodVarName(Selector Sel);
931 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000932
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000933 /// GetMethodVarType - Return a unique constant for the given
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000934 /// method's type encoding string. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000935
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000936 // FIXME: This is a horrible name.
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000937 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
938 bool Extended = false);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000939 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000940
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000941 /// GetPropertyName - Return a unique constant for the given
942 /// name. The return value has type char *.
943 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000944
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000945 // FIXME: This can be dropped once string functions are unified.
946 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
947 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000948
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000949 /// GetClassName - Return a unique constant for the given selector's
Fariborz Jahanian451b92a2014-07-16 16:16:04 +0000950 /// runtime name (which may change via use of objc_runtime_name attribute on
951 /// class or protocol definition. The return value has type char *.
952 llvm::Constant *GetClassName(StringRef RuntimeName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000953
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000954 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
955
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000956 /// BuildIvarLayout - Builds ivar layout bitmap for the class
957 /// implementation for the __strong or __weak case.
958 ///
John McCall460ce582015-10-22 18:38:17 +0000959 /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there
960 /// are any weak ivars defined directly in the class. Meaningless unless
961 /// building a weak layout. Does not guarantee that the layout will
962 /// actually have any entries, because the ivar might be under-aligned.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000963 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
John McCall3fd13f062015-10-21 18:06:47 +0000964 CharUnits beginOffset,
965 CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +0000966 bool forStrongLayout,
967 bool hasMRCWeakIvars);
968
969 llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI,
970 CharUnits beginOffset,
971 CharUnits endOffset) {
972 return BuildIvarLayout(OI, beginOffset, endOffset, true, false);
973 }
974
975 llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI,
976 CharUnits beginOffset,
977 CharUnits endOffset,
978 bool hasMRCWeakIvars) {
979 return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
980 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000981
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000982 Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
Fangrui Song6907ce22018-07-30 19:24:48 +0000983
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000984 void UpdateRunSkipBlockVars(bool IsByref,
985 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000986 CharUnits FieldOffset,
987 CharUnits FieldSize);
Fangrui Song6907ce22018-07-30 19:24:48 +0000988
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000989 void BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000990 CharUnits BytePos, bool &HasUnion,
991 bool ByrefLayout=false);
Fangrui Song6907ce22018-07-30 19:24:48 +0000992
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000993 void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
994 const RecordDecl *RD,
995 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000996 CharUnits BytePos, bool &HasUnion,
997 bool ByrefLayout);
Fangrui Song6907ce22018-07-30 19:24:48 +0000998
Fariborz Jahanian23290b02012-11-01 18:32:55 +0000999 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
Fangrui Song6907ce22018-07-30 19:24:48 +00001000
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00001001 llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
Fangrui Song6907ce22018-07-30 19:24:48 +00001002
Fariborz Jahanian01dff422009-03-05 19:17:31 +00001003 /// GetIvarLayoutName - Returns a unique constant for the given
1004 /// ivar layout bitmap.
1005 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
1006 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001007
Fariborz Jahanian066347e2009-01-28 22:18:42 +00001008 /// EmitPropertyList - Emit the given property list. The return
1009 /// value has type PropertyListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001010 llvm::Constant *EmitPropertyList(Twine Name,
1011 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +00001012 const ObjCContainerDecl *OCD,
Manman Renad0e7912016-01-29 19:22:54 +00001013 const ObjCCommonTypesHelper &ObjCTypes,
1014 bool IsClassProperty);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001015
Fangrui Song6907ce22018-07-30 19:24:48 +00001016 /// EmitProtocolMethodTypes - Generate the array of extended method type
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001017 /// strings. The return value has type Int8PtrPtrTy.
Fangrui Song6907ce22018-07-30 19:24:48 +00001018 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
Zachary Turner41a9ee92017-10-11 23:54:34 +00001019 ArrayRef<llvm::Constant*> MethodTypes,
1020 const ObjCCommonTypesHelper &ObjCTypes);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001021
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001022 /// GetProtocolRef - Return a reference to the internal protocol
1023 /// description, creating an empty one if it has not been
1024 /// defined. The return value has type ProtocolPtrTy.
1025 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +00001026
Douglas Gregor24ae22c2016-04-01 23:23:52 +00001027 /// Return a reference to the given Class using runtime calls rather than
1028 /// by a symbol reference.
1029 llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
1030 const ObjCInterfaceDecl *ID,
1031 ObjCCommonTypesHelper &ObjCTypes);
1032
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00001033 std::string GetSectionName(StringRef Section, StringRef MachOAttributes);
1034
John McCall3fd13f062015-10-21 18:06:47 +00001035public:
Daniel Dunbar30c65362009-03-09 20:09:19 +00001036 /// CreateMetadataVar - Create a global variable with internal
1037 /// linkage for use by the Objective-C runtime.
1038 ///
1039 /// This is a convenience wrapper which not only creates the
1040 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +00001041 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001042 ///
1043 /// \param Name - The variable name.
1044 /// \param Init - The variable initializer; this is also used to
John McCall176f8922016-11-30 02:39:18 +00001045 /// define the type of the variable.
Alp Toker541d5072014-06-07 23:30:53 +00001046 /// \param Section - The section the variable should go into, or empty.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001047 /// \param Align - The alignment for the variable, or 0.
1048 /// \param AddToUsed - Whether the variable should be added to
John McCall176f8922016-11-30 02:39:18 +00001049 /// "llvm.used".
Zachary Turner41a9ee92017-10-11 23:54:34 +00001050 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
John McCall176f8922016-11-30 02:39:18 +00001051 ConstantStructBuilder &Init,
1052 StringRef Section, CharUnits Align,
1053 bool AddToUsed);
Zachary Turner41a9ee92017-10-11 23:54:34 +00001054 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
John McCall176f8922016-11-30 02:39:18 +00001055 llvm::Constant *Init,
John McCall7f416cc2015-09-08 08:05:57 +00001056 StringRef Section, CharUnits Align,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001057 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +00001058
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001059 llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00001060 ObjCLabelType LabelType,
1061 bool ForceNonFragileABI = false,
1062 bool NullTerminate = true);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001063
John McCall3fd13f062015-10-21 18:06:47 +00001064protected:
John McCall9e8bb002011-05-14 03:10:52 +00001065 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1066 ReturnValueSlot Return,
1067 QualType ResultType,
1068 llvm::Value *Sel,
1069 llvm::Value *Arg0,
1070 QualType Arg0Ty,
1071 bool IsSuper,
1072 const CallArgList &CallArgs,
1073 const ObjCMethodDecl *OMD,
John McCall1e3157b2015-09-10 22:27:50 +00001074 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00001075 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +00001076
Daniel Dunbar5e639272010-04-25 20:39:01 +00001077 /// EmitImageInfo - Emit the image info marker used to encode some module
1078 /// level information.
1079 void EmitImageInfo();
1080
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001081public:
Owen Andersonae86c192009-07-13 04:10:07 +00001082 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
John McCalla729c622012-02-17 03:33:10 +00001083 CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001084
John McCall3fd13f062015-10-21 18:06:47 +00001085 bool isNonFragileABI() const {
1086 return ObjCABI == 2;
1087 }
1088
John McCall7f416cc2015-09-08 08:05:57 +00001089 ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
John McCallcd21d542016-11-30 23:15:55 +00001090 ConstantAddress GenerateConstantNSString(const StringLiteral *SL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001091
Craig Topper4f12f102014-03-12 06:41:41 +00001092 llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
Craig Topper8a13c412014-05-21 05:09:00 +00001093 const ObjCContainerDecl *CD=nullptr) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001094
1095 void GenerateProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001096
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001097 /// GetOrEmitProtocol - Get the protocol object for the given
1098 /// declaration, emitting it if necessary. The return value has type
1099 /// ProtocolPtrTy.
1100 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001101
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001102 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1103 /// object for the given declaration, emitting it if needed. These
1104 /// forward references will be filled in with empty bodies if no
1105 /// definition is seen. The return value has type ProtocolPtrTy.
1106 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCallcd21d542016-11-30 23:15:55 +00001107
1108 virtual llvm::Constant *getNSConstantStringClassRef() = 0;
1109
Craig Topper4f12f102014-03-12 06:41:41 +00001110 llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1111 const CGBlockInfo &blockInfo) override;
1112 llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1113 const CGBlockInfo &blockInfo) override;
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00001114 std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM,
1115 const CGBlockInfo &blockInfo) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001116
1117 llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1118 QualType T) override;
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00001119
1120private:
1121 void fillRunSkipBlockVars(CodeGenModule &CGM, const CGBlockInfo &blockInfo);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001122};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001123
John McCall176f8922016-11-30 02:39:18 +00001124namespace {
1125
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001126enum class MethodListType {
1127 CategoryInstanceMethods,
1128 CategoryClassMethods,
1129 InstanceMethods,
1130 ClassMethods,
1131 ProtocolInstanceMethods,
1132 ProtocolClassMethods,
1133 OptionalProtocolInstanceMethods,
1134 OptionalProtocolClassMethods,
1135};
1136
John McCall176f8922016-11-30 02:39:18 +00001137/// A convenience class for splitting the methods of a protocol into
1138/// the four interesting groups.
1139class ProtocolMethodLists {
1140public:
1141 enum Kind {
1142 RequiredInstanceMethods,
1143 RequiredClassMethods,
1144 OptionalInstanceMethods,
1145 OptionalClassMethods
1146 };
1147 enum {
1148 NumProtocolMethodLists = 4
1149 };
1150
1151 static MethodListType getMethodListKind(Kind kind) {
1152 switch (kind) {
1153 case RequiredInstanceMethods:
1154 return MethodListType::ProtocolInstanceMethods;
1155 case RequiredClassMethods:
1156 return MethodListType::ProtocolClassMethods;
1157 case OptionalInstanceMethods:
1158 return MethodListType::OptionalProtocolInstanceMethods;
1159 case OptionalClassMethods:
1160 return MethodListType::OptionalProtocolClassMethods;
1161 }
1162 llvm_unreachable("bad kind");
1163 }
1164
1165 SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];
1166
1167 static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
1168 ProtocolMethodLists result;
1169
1170 for (auto MD : PD->methods()) {
1171 size_t index = (2 * size_t(MD->isOptional()))
1172 + (size_t(MD->isClassMethod()));
1173 result.Methods[index].push_back(MD);
1174 }
1175
1176 return result;
1177 }
1178
1179 template <class Self>
1180 SmallVector<llvm::Constant*, 8> emitExtendedTypesArray(Self *self) const {
1181 // In both ABIs, the method types list is parallel with the
1182 // concatenation of the methods arrays in the following order:
1183 // instance methods
1184 // class methods
1185 // optional instance methods
1186 // optional class methods
1187 SmallVector<llvm::Constant*, 8> result;
1188
1189 // Methods is already in the correct order for both ABIs.
1190 for (auto &list : Methods) {
1191 for (auto MD : list) {
1192 result.push_back(self->GetMethodVarType(MD, true));
1193 }
1194 }
1195
1196 return result;
1197 }
1198
1199 template <class Self>
1200 llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD,
1201 Kind kind) const {
1202 return self->emitMethodList(PD->getObjCRuntimeNameAsString(),
1203 getMethodListKind(kind), Methods[kind]);
1204 }
1205};
1206
1207} // end anonymous namespace
1208
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001209class CGObjCMac : public CGObjCCommonMac {
1210private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001211 friend ProtocolMethodLists;
John McCall176f8922016-11-30 02:39:18 +00001212
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001213 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001214
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001215 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001216 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001217 void EmitModuleInfo();
1218
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001219 /// EmitModuleSymols - Emit module symbols, the list of defined
1220 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001221 llvm::Constant *EmitModuleSymbols();
1222
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001223 /// FinishModule - Write out global data structures at the end of
1224 /// processing a translation unit.
1225 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +00001226
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001227 /// EmitClassExtension - Generate the class extension structure used
1228 /// to store the weak ivar layout and properties. The return value
1229 /// has type ClassExtensionPtrTy.
John McCall3fd13f062015-10-21 18:06:47 +00001230 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
John McCall460ce582015-10-22 18:38:17 +00001231 CharUnits instanceSize,
Manman Renad0e7912016-01-29 19:22:54 +00001232 bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00001233 bool isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001234
1235 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1236 /// for the given class.
John McCall882987f2013-02-28 19:01:20 +00001237 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001238 const ObjCInterfaceDecl *ID);
Fangrui Song6907ce22018-07-30 19:24:48 +00001239
John McCall882987f2013-02-28 19:01:20 +00001240 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00001241 IdentifierInfo *II);
Craig Topper4f12f102014-03-12 06:41:41 +00001242
1243 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
1244
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001245 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1246 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001247
1248 /// EmitIvarList - Emit the ivar list for the given
1249 /// implementation. If ForClass is true the list of class ivars
1250 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1251 /// interface ivars will be emitted. The return value has type
1252 /// IvarListPtrTy.
1253 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00001254 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001255
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001256 /// EmitMetaClass - Emit a forward reference to the class structure
1257 /// for the metaclass of the given interface. The return value has
1258 /// type ClassPtrTy.
1259 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1260
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001261 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001262 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001263 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1264 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00001265 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001266
John McCall176f8922016-11-30 02:39:18 +00001267 void emitMethodConstant(ConstantArrayBuilder &builder,
1268 const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001269
John McCall176f8922016-11-30 02:39:18 +00001270 void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
1271 const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001272
1273 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +00001274 /// implementation. The return value has type MethodListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001275 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
John McCall176f8922016-11-30 02:39:18 +00001276 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001277
Daniel Dunbarc475d422008-10-29 22:36:39 +00001278 /// GetOrEmitProtocol - Get the protocol object for the given
1279 /// declaration, emitting it if necessary. The return value has type
1280 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001281 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001282
1283 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1284 /// object for the given declaration, emitting it if needed. These
1285 /// forward references will be filled in with empty bodies if no
1286 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001287 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001288
Daniel Dunbarb036db82008-08-13 03:21:16 +00001289 /// EmitProtocolExtension - Generate the protocol extension
1290 /// structure used to store optional instance and class methods, and
1291 /// protocol properties. The return value has type
1292 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001293 llvm::Constant *
1294 EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00001295 const ProtocolMethodLists &methodLists);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001296
1297 /// EmitProtocolList - Generate the list of referenced
1298 /// protocols. The return value has type ProtocolListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001299 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001300 ObjCProtocolDecl::protocol_iterator begin,
1301 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001302
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001303 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1304 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001305 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1306 Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001307
1308public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001309 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001310
John McCallcd21d542016-11-30 23:15:55 +00001311 llvm::Constant *getNSConstantStringClassRef() override;
1312
Craig Topper4f12f102014-03-12 06:41:41 +00001313 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001314
Craig Topper4f12f102014-03-12 06:41:41 +00001315 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1316 ReturnValueSlot Return,
1317 QualType ResultType,
1318 Selector Sel, llvm::Value *Receiver,
1319 const CallArgList &CallArgs,
1320 const ObjCInterfaceDecl *Class,
1321 const ObjCMethodDecl *Method) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001322
Craig Topper4f12f102014-03-12 06:41:41 +00001323 CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001324 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001325 ReturnValueSlot Return, QualType ResultType,
1326 Selector Sel, const ObjCInterfaceDecl *Class,
1327 bool isCategoryImpl, llvm::Value *Receiver,
1328 bool IsClassMessage, const CallArgList &CallArgs,
1329 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001330
Craig Topper4f12f102014-03-12 06:41:41 +00001331 llvm::Value *GetClass(CodeGenFunction &CGF,
1332 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001333
John McCall7f416cc2015-09-08 08:05:57 +00001334 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
1335 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001336
1337 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1338 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001339 llvm::Value *GetSelector(CodeGenFunction &CGF,
1340 const ObjCMethodDecl *Method) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001341
Craig Topper4f12f102014-03-12 06:41:41 +00001342 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001343
Craig Topper4f12f102014-03-12 06:41:41 +00001344 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001345
Craig Topper4f12f102014-03-12 06:41:41 +00001346 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001347
Craig Topper4f12f102014-03-12 06:41:41 +00001348 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001349
Craig Topper4f12f102014-03-12 06:41:41 +00001350 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1351 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001352
James Y Knight9871db02019-02-05 16:42:33 +00001353 llvm::FunctionCallee GetPropertyGetFunction() override;
1354 llvm::FunctionCallee GetPropertySetFunction() override;
1355 llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
1356 bool copy) override;
1357 llvm::FunctionCallee GetGetStructFunction() override;
1358 llvm::FunctionCallee GetSetStructFunction() override;
1359 llvm::FunctionCallee GetCppAtomicObjectGetFunction() override;
1360 llvm::FunctionCallee GetCppAtomicObjectSetFunction() override;
1361 llvm::FunctionCallee EnumerationMutationFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001362
Craig Topper4f12f102014-03-12 06:41:41 +00001363 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1364 const ObjCAtTryStmt &S) override;
1365 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1366 const ObjCAtSynchronizedStmt &S) override;
John McCallbd309292010-07-06 01:34:17 +00001367 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Craig Topper4f12f102014-03-12 06:41:41 +00001368 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1369 bool ClearInsertionPoint=true) override;
1370 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001371 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001372 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001373 llvm::Value *src, Address dst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001374 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001375 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001376 bool threadlocal = false) override;
1377 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001378 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001379 llvm::Value *ivarOffset) override;
1380 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001381 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001382 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001383 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001384 llvm::Value *size) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001385
Craig Topper4f12f102014-03-12 06:41:41 +00001386 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1387 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1388 unsigned CVRQualifiers) override;
1389 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1390 const ObjCInterfaceDecl *Interface,
1391 const ObjCIvarDecl *Ivar) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001392};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001393
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001394class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001395private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001396 friend ProtocolMethodLists;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001397 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001398 llvm::GlobalVariable* ObjCEmptyCacheVar;
John McCall176f8922016-11-30 02:39:18 +00001399 llvm::Constant* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001400
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001401 /// SuperClassReferences - uniqued super class references.
1402 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001403
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001404 /// MetaClassReferences - uniqued meta class references.
1405 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001406
1407 /// EHTypeReferences - uniqued class ehtype references.
1408 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001409
John McCall9e8bb002011-05-14 03:10:52 +00001410 /// VTableDispatchMethods - List of methods for which we generate
1411 /// vtable-based message dispatch.
1412 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001413
Fariborz Jahanian67260552009-11-17 21:37:35 +00001414 /// DefinedMetaClasses - List of defined meta-classes.
1415 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
Fangrui Song6907ce22018-07-30 19:24:48 +00001416
John McCall9e8bb002011-05-14 03:10:52 +00001417 /// isVTableDispatchedSelector - Returns true if SEL is a
1418 /// vtable-based selector.
1419 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001420
Fariborz Jahanian71394042009-01-23 23:53:38 +00001421 /// FinishNonFragileABIModule - Write out global data structures at the end of
1422 /// processing a translation unit.
1423 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001424
Daniel Dunbar19573e72009-05-15 21:48:48 +00001425 /// AddModuleClassList - Add the given list of class pointers to the
1426 /// module with the provided symbol and section names.
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001427 void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container,
1428 StringRef SymbolName, StringRef SectionName);
Daniel Dunbar19573e72009-05-15 21:48:48 +00001429
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001430 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1431 unsigned InstanceStart,
1432 unsigned InstanceSize,
1433 const ObjCImplementationDecl *ID);
John McCalldba63a72016-11-30 23:54:50 +00001434 llvm::GlobalVariable *BuildClassObject(const ObjCInterfaceDecl *CI,
1435 bool isMetaclass,
1436 llvm::Constant *IsAGV,
1437 llvm::Constant *SuperClassGV,
1438 llvm::Constant *ClassRoGV,
1439 bool HiddenVisibility);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001440
John McCall176f8922016-11-30 02:39:18 +00001441 void emitMethodConstant(ConstantArrayBuilder &builder,
1442 const ObjCMethodDecl *MD,
1443 bool forProtocol);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001444
John McCall176f8922016-11-30 02:39:18 +00001445 /// Emit the method list for the given implementation. The return value
1446 /// has type MethodListnfABITy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001447 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
John McCall176f8922016-11-30 02:39:18 +00001448 ArrayRef<const ObjCMethodDecl *> Methods);
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001449
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001450 /// EmitIvarList - Emit the ivar list for the given
1451 /// implementation. If ForClass is true the list of class ivars
1452 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1453 /// interface ivars will be emitted. The return value has type
1454 /// IvarListnfABIPtrTy.
1455 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001456
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001457 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001458 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00001459 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001460
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001461 /// GetOrEmitProtocol - Get the protocol object for the given
1462 /// declaration, emitting it if necessary. The return value has type
1463 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001464 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001465
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001466 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1467 /// object for the given declaration, emitting it if needed. These
1468 /// forward references will be filled in with empty bodies if no
1469 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001470 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001471
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001472 /// EmitProtocolList - Generate the list of referenced
1473 /// protocols. The return value has type ProtocolListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001474 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001475 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001476 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001477
John McCall9e8bb002011-05-14 03:10:52 +00001478 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1479 ReturnValueSlot Return,
1480 QualType ResultType,
1481 Selector Sel,
1482 llvm::Value *Receiver,
1483 QualType Arg0Ty,
1484 bool IsSuper,
1485 const CallArgList &CallArgs,
1486 const ObjCMethodDecl *Method);
Fangrui Song6907ce22018-07-30 19:24:48 +00001487
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001488 /// GetClassGlobal - Return the global variable for the Objective-C
1489 /// class of the given name.
John McCalldba63a72016-11-30 23:54:50 +00001490 llvm::Constant *GetClassGlobal(StringRef Name,
1491 ForDefinition_t IsForDefinition,
1492 bool Weak = false, bool DLLImport = false);
1493 llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID,
1494 bool isMetaclass,
1495 ForDefinition_t isForDefinition);
Rafael Espindola554256c2014-02-26 22:25:45 +00001496
John McCall2c91c3b2019-05-30 04:09:01 +00001497 llvm::Constant *GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID);
1498
1499 llvm::Value *EmitLoadOfClassRef(CodeGenFunction &CGF,
1500 const ObjCInterfaceDecl *ID,
1501 llvm::GlobalVariable *Entry);
1502
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001503 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001504 /// for the given class reference.
John McCall882987f2013-02-28 19:01:20 +00001505 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001506 const ObjCInterfaceDecl *ID);
Fangrui Song6907ce22018-07-30 19:24:48 +00001507
John McCall882987f2013-02-28 19:01:20 +00001508 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
John McCalldba63a72016-11-30 23:54:50 +00001509 IdentifierInfo *II,
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00001510 const ObjCInterfaceDecl *ID);
Craig Topper4f12f102014-03-12 06:41:41 +00001511
1512 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001513
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001514 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1515 /// for the given super class reference.
John McCall882987f2013-02-28 19:01:20 +00001516 llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001517 const ObjCInterfaceDecl *ID);
1518
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001519 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1520 /// meta-data
John McCall882987f2013-02-28 19:01:20 +00001521 llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00001522 const ObjCInterfaceDecl *ID, bool Weak);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001523
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001524 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1525 /// the given ivar.
1526 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001527 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001528 const ObjCInterfaceDecl *ID,
1529 const ObjCIvarDecl *Ivar);
1530
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001531 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1532 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001533 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1534 Address EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001535
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001536 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001537 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001538 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
John McCalldba63a72016-11-30 23:54:50 +00001539 ForDefinition_t IsForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001540
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001541 StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001542
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001543 StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; }
Daniel Dunbar15894b72009-04-07 05:48:37 +00001544
Daniel Dunbar961202372009-05-03 12:57:56 +00001545 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001546 uint32_t &InstanceStart,
1547 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001548
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001549 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001550 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001551 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1552 return CGM.getContext().Selectors.getSelector(0, &II);
1553 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001554
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001555 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001556 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1557 return CGM.getContext().Selectors.getSelector(1, &II);
1558 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001559
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001560 /// ImplementationIsNonLazy - Check whether the given category or
1561 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001562 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001563
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001564 bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001565 const ObjCIvarDecl *IV) {
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001566 // Annotate the load as an invariant load iff inside an instance method
1567 // and ivar belongs to instance method's class and one of its super class.
1568 // This check is needed because the ivar offset is a lazily
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001569 // initialised value that may depend on objc_msgSend to perform a fixup on
1570 // the first message dispatch.
1571 //
1572 // An additional opportunity to mark the load as invariant arises when the
1573 // base of the ivar access is a parameter to an Objective C method.
1574 // However, because the parameters are not available in the current
1575 // interface, we cannot perform this check.
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001576 if (const ObjCMethodDecl *MD =
1577 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
Fariborz Jahanian7a583022014-03-04 22:57:32 +00001578 if (MD->isInstanceMethod())
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001579 if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
1580 return IV->getContainingInterface()->isSuperClassOf(ID);
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001581 return false;
1582 }
1583
Erik Pilkington2ff012d2019-01-17 18:18:53 +00001584 bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) {
1585 // NSObject is a fixed size. If we can see the @implementation of a class
1586 // which inherits from NSObject then we know that all it's offsets also must
1587 // be fixed. FIXME: Can we do this if see a chain of super classes with
1588 // implementations leading to NSObject?
1589 return ID->getImplementation() && ID->getSuperClass() &&
1590 ID->getSuperClass()->getName() == "NSObject";
1591 }
1592
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001593public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001594 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
John McCallcd21d542016-11-30 23:15:55 +00001595
1596 llvm::Constant *getNSConstantStringClassRef() override;
1597
Craig Topper4f12f102014-03-12 06:41:41 +00001598 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001599
Craig Topper4f12f102014-03-12 06:41:41 +00001600 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1601 ReturnValueSlot Return,
1602 QualType ResultType, Selector Sel,
1603 llvm::Value *Receiver,
1604 const CallArgList &CallArgs,
1605 const ObjCInterfaceDecl *Class,
1606 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001607
Craig Topper4f12f102014-03-12 06:41:41 +00001608 CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001609 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001610 ReturnValueSlot Return, QualType ResultType,
1611 Selector Sel, const ObjCInterfaceDecl *Class,
1612 bool isCategoryImpl, llvm::Value *Receiver,
1613 bool IsClassMessage, const CallArgList &CallArgs,
1614 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001615
Craig Topper4f12f102014-03-12 06:41:41 +00001616 llvm::Value *GetClass(CodeGenFunction &CGF,
1617 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001618
John McCall7f416cc2015-09-08 08:05:57 +00001619 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override
1620 { return EmitSelector(CGF, Sel); }
1621 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override
1622 { return EmitSelectorAddr(CGF, Sel); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001623
1624 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1625 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001626 llvm::Value *GetSelector(CodeGenFunction &CGF,
1627 const ObjCMethodDecl *Method) override
John McCall882987f2013-02-28 19:01:20 +00001628 { return EmitSelector(CGF, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001629
Craig Topper4f12f102014-03-12 06:41:41 +00001630 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001631
Craig Topper4f12f102014-03-12 06:41:41 +00001632 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
David Chisnall92d436b2012-01-31 18:59:20 +00001633
Craig Topper4f12f102014-03-12 06:41:41 +00001634 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001635
Craig Topper4f12f102014-03-12 06:41:41 +00001636 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1637 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001638
Craig Topper4f12f102014-03-12 06:41:41 +00001639 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001640
James Y Knight9871db02019-02-05 16:42:33 +00001641 llvm::FunctionCallee GetPropertyGetFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001642 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001643 }
James Y Knight9871db02019-02-05 16:42:33 +00001644 llvm::FunctionCallee GetPropertySetFunction() override {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001645 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001646 }
Craig Topper4f12f102014-03-12 06:41:41 +00001647
James Y Knight9871db02019-02-05 16:42:33 +00001648 llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
1649 bool copy) override {
Ted Kremeneke65b0862012-03-06 20:05:56 +00001650 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1651 }
Craig Topper4f12f102014-03-12 06:41:41 +00001652
James Y Knight9871db02019-02-05 16:42:33 +00001653 llvm::FunctionCallee GetSetStructFunction() override {
David Chisnall168b80f2010-12-26 22:13:16 +00001654 return ObjCTypes.getCopyStructFn();
1655 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001656
James Y Knight9871db02019-02-05 16:42:33 +00001657 llvm::FunctionCallee GetGetStructFunction() override {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001658 return ObjCTypes.getCopyStructFn();
1659 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001660
James Y Knight9871db02019-02-05 16:42:33 +00001661 llvm::FunctionCallee GetCppAtomicObjectSetFunction() override {
David Chisnall0d75e062012-12-17 18:54:24 +00001662 return ObjCTypes.getCppAtomicObjectFunction();
1663 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001664
James Y Knight9871db02019-02-05 16:42:33 +00001665 llvm::FunctionCallee GetCppAtomicObjectGetFunction() override {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001666 return ObjCTypes.getCppAtomicObjectFunction();
1667 }
Craig Topper4f12f102014-03-12 06:41:41 +00001668
James Y Knight9871db02019-02-05 16:42:33 +00001669 llvm::FunctionCallee EnumerationMutationFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001670 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001671 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001672
Craig Topper4f12f102014-03-12 06:41:41 +00001673 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1674 const ObjCAtTryStmt &S) override;
1675 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1676 const ObjCAtSynchronizedStmt &S) override;
1677 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1678 bool ClearInsertionPoint=true) override;
1679 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001680 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001681 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001682 llvm::Value *src, Address edst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001683 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001684 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001685 bool threadlocal = false) override;
1686 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001687 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001688 llvm::Value *ivarOffset) override;
1689 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001690 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001691 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001692 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001693 llvm::Value *size) override;
1694 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1695 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1696 unsigned CVRQualifiers) override;
1697 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1698 const ObjCInterfaceDecl *Interface,
1699 const ObjCIvarDecl *Ivar) override;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001700};
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001701
1702/// A helper class for performing the null-initialization of a return
1703/// value.
1704struct NullReturnState {
1705 llvm::BasicBlock *NullBB;
Craig Topper8a13c412014-05-21 05:09:00 +00001706 NullReturnState() : NullBB(nullptr) {}
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001707
John McCall3d1e2c92013-02-12 05:53:35 +00001708 /// Perform a null-check of the given receiver.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001709 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
John McCall3d1e2c92013-02-12 05:53:35 +00001710 // Make blocks for the null-receiver and call edges.
1711 NullBB = CGF.createBasicBlock("msgSend.null-receiver");
1712 llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001713
1714 // Check for a null receiver and, if there is one, jump to the
John McCall3d1e2c92013-02-12 05:53:35 +00001715 // null-receiver block. There's no point in trying to avoid it:
1716 // we're always going to put *something* there, because otherwise
1717 // we shouldn't have done this null-check in the first place.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001718 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1719 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1720
1721 // Otherwise, start performing the call.
1722 CGF.EmitBlock(callBB);
1723 }
1724
John McCall3d1e2c92013-02-12 05:53:35 +00001725 /// Complete the null-return operation. It is valid to call this
1726 /// regardless of whether 'init' has been called.
Kuba Mracekbce5cea2017-06-30 16:28:15 +00001727 RValue complete(CodeGenFunction &CGF,
1728 ReturnValueSlot returnSlot,
1729 RValue result,
1730 QualType resultType,
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001731 const CallArgList &CallArgs,
1732 const ObjCMethodDecl *Method) {
John McCall3d1e2c92013-02-12 05:53:35 +00001733 // If we never had to do a null-check, just use the raw result.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001734 if (!NullBB) return result;
John McCall3d1e2c92013-02-12 05:53:35 +00001735
1736 // The continuation block. This will be left null if we don't have an
1737 // IP, which can happen if the method we're calling is marked noreturn.
Craig Topper8a13c412014-05-21 05:09:00 +00001738 llvm::BasicBlock *contBB = nullptr;
1739
John McCall3d1e2c92013-02-12 05:53:35 +00001740 // Finish the call path.
1741 llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
1742 if (callBB) {
1743 contBB = CGF.createBasicBlock("msgSend.cont");
1744 CGF.Builder.CreateBr(contBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001745 }
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001746
John McCall3d1e2c92013-02-12 05:53:35 +00001747 // Okay, start emitting the null-receiver block.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001748 CGF.EmitBlock(NullBB);
Fangrui Song6907ce22018-07-30 19:24:48 +00001749
John McCall3d1e2c92013-02-12 05:53:35 +00001750 // Release any consumed arguments we've got.
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001751 if (Method) {
1752 CallArgList::const_iterator I = CallArgs.begin();
1753 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1754 e = Method->param_end(); i != e; ++i, ++I) {
1755 const ParmVarDecl *ParamDecl = (*i);
1756 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
Yaxun Liu5b330e82018-03-15 15:25:19 +00001757 RValue RV = I->getRValue(CGF);
Fangrui Song6907ce22018-07-30 19:24:48 +00001758 assert(RV.isScalar() &&
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001759 "NullReturnState::complete - arg not on object");
John McCallcdda29c2013-03-13 03:10:54 +00001760 CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001761 }
1762 }
1763 }
John McCall3d1e2c92013-02-12 05:53:35 +00001764
1765 // The phi code below assumes that we haven't needed any control flow yet.
1766 assert(CGF.Builder.GetInsertBlock() == NullBB);
1767
1768 // If we've got a void return, just jump to the continuation block.
1769 if (result.isScalar() && resultType->isVoidType()) {
1770 // No jumps required if the message-send was noreturn.
1771 if (contBB) CGF.EmitBlock(contBB);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001772 return result;
1773 }
1774
John McCall3d1e2c92013-02-12 05:53:35 +00001775 // If we've got a scalar return, build a phi.
1776 if (result.isScalar()) {
1777 // Derive the null-initialization value.
1778 llvm::Constant *null = CGF.CGM.EmitNullConstant(resultType);
1779
1780 // If no join is necessary, just flow out.
1781 if (!contBB) return RValue::get(null);
1782
1783 // Otherwise, build a phi.
1784 CGF.EmitBlock(contBB);
1785 llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2);
1786 phi->addIncoming(result.getScalarVal(), callBB);
1787 phi->addIncoming(null, NullBB);
1788 return RValue::get(phi);
1789 }
1790
1791 // If we've got an aggregate return, null the buffer out.
1792 // FIXME: maybe we should be doing things differently for all the
1793 // cases where the ABI has us returning (1) non-agg values in
1794 // memory or (2) agg values in registers.
1795 if (result.isAggregate()) {
1796 assert(result.isAggregate() && "null init of non-aggregate result?");
Kuba Mracekbce5cea2017-06-30 16:28:15 +00001797 if (!returnSlot.isUnused())
1798 CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
John McCall3d1e2c92013-02-12 05:53:35 +00001799 if (contBB) CGF.EmitBlock(contBB);
1800 return result;
1801 }
1802
1803 // Complex types.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001804 CGF.EmitBlock(contBB);
John McCall3d1e2c92013-02-12 05:53:35 +00001805 CodeGenFunction::ComplexPairTy callResult = result.getComplexVal();
1806
1807 // Find the scalar type and its zero value.
1808 llvm::Type *scalarTy = callResult.first->getType();
1809 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1810
1811 // Build phis for both coordinates.
1812 llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2);
1813 real->addIncoming(callResult.first, callBB);
1814 real->addIncoming(scalarZero, NullBB);
1815 llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2);
1816 imag->addIncoming(callResult.second, callBB);
1817 imag->addIncoming(scalarZero, NullBB);
1818 return RValue::getComplex(real, imag);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001819 }
1820};
1821
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001822} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001823
1824/* *** Helper Functions *** */
1825
1826/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001827static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
David Blaikiee3b172a2015-04-02 18:55:21 +00001828 llvm::GlobalVariable *C, unsigned idx0,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001829 unsigned idx1) {
1830 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001831 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1832 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001833 };
David Blaikiee3b172a2015-04-02 18:55:21 +00001834 return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001835}
1836
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001837/// hasObjCExceptionAttribute - Return true if this class or any super
1838/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001839static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001840 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001841 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001842 return true;
1843 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001844 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001845 return false;
1846}
1847
Akira Hatanaka187770d2019-05-09 17:43:52 +00001848static llvm::GlobalValue::LinkageTypes
1849getLinkageTypeForObjCMetadata(CodeGenModule &CGM, StringRef Section) {
1850 if (CGM.getTriple().isOSBinFormatMachO() &&
1851 (Section.empty() || Section.startswith("__DATA")))
1852 return llvm::GlobalValue::InternalLinkage;
1853 return llvm::GlobalValue::PrivateLinkage;
1854}
1855
1856/// A helper function to create an internal or private global variable.
1857static llvm::GlobalVariable *
1858finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder,
1859 const llvm::Twine &Name, CodeGenModule &CGM) {
1860 std::string SectionName;
1861 if (CGM.getTriple().isOSBinFormatMachO())
1862 SectionName = "__DATA, __objc_const";
1863 auto *GV = Builder.finishAndCreateGlobal(
1864 Name, CGM.getPointerAlign(), /*constant*/ false,
1865 getLinkageTypeForObjCMetadata(CGM, SectionName));
1866 GV->setSection(SectionName);
1867 return GV;
1868}
1869
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001870/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001871
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001872CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001873 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001874 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001875 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001876}
1877
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001878/// GetClass - Return a reference to the class for the given interface
1879/// decl.
John McCall882987f2013-02-28 19:01:20 +00001880llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001881 const ObjCInterfaceDecl *ID) {
John McCall882987f2013-02-28 19:01:20 +00001882 return EmitClassRef(CGF, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001883}
1884
1885/// GetSelector - Return the pointer to the unique'd string for this selector.
John McCall7f416cc2015-09-08 08:05:57 +00001886llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
1887 return EmitSelector(CGF, Sel);
1888}
1889Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
1890 return EmitSelectorAddr(CGF, Sel);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001891}
John McCall882987f2013-02-28 19:01:20 +00001892llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001893 *Method) {
John McCall882987f2013-02-28 19:01:20 +00001894 return EmitSelector(CGF, Method->getSelector());
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001895}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001896
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001897llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001898 if (T->isObjCIdType() ||
1899 T->isObjCQualifiedIdType()) {
1900 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001901 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001902 }
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001903 if (T->isObjCClassType() ||
1904 T->isObjCQualifiedClassType()) {
1905 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001906 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001907 }
1908 if (T->isObjCObjectPointerType())
1909 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
Fangrui Song6907ce22018-07-30 19:24:48 +00001910
John McCall2ca705e2010-07-24 00:37:23 +00001911 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall2ca705e2010-07-24 00:37:23 +00001912}
1913
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001914/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001915/*
1916 struct __builtin_CFString {
1917 const int *isa; // point to __CFConstantStringClassReference
1918 int flags;
1919 const char *str;
1920 long length;
1921 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001922*/
1923
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001924/// or Generate a constant NSString object.
1925/*
1926 struct __builtin_NSString {
1927 const int *isa; // point to __NSConstantStringClassReference
1928 const char *str;
1929 unsigned int length;
1930 };
1931*/
1932
John McCallcd21d542016-11-30 23:15:55 +00001933ConstantAddress
1934CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) {
1935 return (!CGM.getLangOpts().NoConstantCFStrings
1936 ? CGM.GetAddrOfConstantCFString(SL)
1937 : GenerateConstantNSString(SL));
1938}
1939
1940static llvm::StringMapEntry<llvm::GlobalVariable *> &
1941GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
1942 const StringLiteral *Literal, unsigned &StringLength) {
1943 StringRef String = Literal->getString();
1944 StringLength = String.size();
1945 return *Map.insert(std::make_pair(String, nullptr)).first;
1946}
1947
1948llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1949 if (llvm::Value *V = ConstantStringClassRef)
1950 return cast<llvm::Constant>(V);
1951
1952 auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
1953 std::string str =
1954 StringClass.empty() ? "_NSConstantStringClassReference"
1955 : "_" + StringClass + "ClassReference";
1956
1957 llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0);
1958 auto GV = CGM.CreateRuntimeVariable(PTy, str);
1959 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1960 ConstantStringClassRef = V;
1961 return V;
1962}
1963
1964llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1965 if (llvm::Value *V = ConstantStringClassRef)
1966 return cast<llvm::Constant>(V);
1967
1968 auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
Fangrui Song6907ce22018-07-30 19:24:48 +00001969 std::string str =
1970 StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
John McCallcd21d542016-11-30 23:15:55 +00001971 : "OBJC_CLASS_$_" + StringClass;
John McCall2c91c3b2019-05-30 04:09:01 +00001972 llvm::Constant *GV = GetClassGlobal(str, NotForDefinition);
John McCallcd21d542016-11-30 23:15:55 +00001973
1974 // Make sure the result is of the correct type.
1975 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1976
1977 ConstantStringClassRef = V;
1978 return V;
1979}
1980
1981ConstantAddress
1982CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) {
1983 unsigned StringLength = 0;
1984 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
1985 GetConstantStringEntry(NSConstantStringMap, Literal, StringLength);
1986
1987 if (auto *C = Entry.second)
1988 return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
1989
1990 // If we don't already have it, get _NSConstantStringClassReference.
1991 llvm::Constant *Class = getNSConstantStringClassRef();
1992
1993 // If we don't already have it, construct the type for a constant NSString.
1994 if (!NSConstantStringType) {
1995 NSConstantStringType =
1996 llvm::StructType::create({
1997 CGM.Int32Ty->getPointerTo(),
1998 CGM.Int8PtrTy,
1999 CGM.IntTy
2000 }, "struct.__builtin_NSString");
2001 }
2002
2003 ConstantInitBuilder Builder(CGM);
2004 auto Fields = Builder.beginStruct(NSConstantStringType);
2005
2006 // Class pointer.
2007 Fields.add(Class);
2008
2009 // String pointer.
2010 llvm::Constant *C =
2011 llvm::ConstantDataArray::getString(VMContext, Entry.first());
2012
2013 llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
2014 bool isConstant = !CGM.getLangOpts().WritableStrings;
2015
2016 auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant,
2017 Linkage, C, ".str");
2018 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2019 // Don't enforce the target's minimum global alignment, since the only use
2020 // of the string is via this class initializer.
Guillaume Chateletc79099e2019-10-03 13:00:29 +00002021 GV->setAlignment(llvm::Align::None());
John McCallcd21d542016-11-30 23:15:55 +00002022 Fields.addBitCast(GV, CGM.Int8PtrTy);
2023
2024 // String length.
2025 Fields.addInt(CGM.IntTy, StringLength);
2026
2027 // The struct.
2028 CharUnits Alignment = CGM.getPointerAlign();
2029 GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
2030 /*constant*/ true,
2031 llvm::GlobalVariable::PrivateLinkage);
2032 const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
2033 const char *NSStringNonFragileABISection =
2034 "__DATA,__objc_stringobj,regular,no_dead_strip";
2035 // FIXME. Fix section.
2036 GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile()
2037 ? NSStringNonFragileABISection
2038 : NSStringSection);
2039 Entry.second = GV;
2040
2041 return ConstantAddress(GV, Alignment);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002042}
2043
Ted Kremeneke65b0862012-03-06 20:05:56 +00002044enum {
2045 kCFTaggedObjectID_Integer = (1 << 1) + 1
2046};
2047
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002048/// Generates a message send where the super is the receiver. This is
2049/// a message send to self with special delivery semantics indicating
2050/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00002051CodeGen::RValue
2052CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00002053 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00002054 QualType ResultType,
2055 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002056 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002057 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002058 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00002059 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00002060 const CodeGen::CallArgList &CallArgs,
2061 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002062 // Create and init a super structure; this is a (receiver, class)
2063 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00002064 Address ObjCSuper =
2065 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
2066 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002067 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002068 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
James Y Knight751fe282019-02-09 22:22:28 +00002069 CGF.Builder.CreateStore(ReceiverAsObject,
2070 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002071
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002072 // If this is a class message the metaclass is passed as the target.
2073 llvm::Value *Target;
2074 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002075 if (isCategoryImpl) {
2076 // Message sent to 'super' in a class method defined in a category
2077 // implementation requires an odd treatment.
2078 // If we are in a class method, we must retrieve the
2079 // _metaclass_ for the current class, pointed at by
2080 // the class's "isa" pointer. The following assumes that
2081 // isa" is the first ivar in a class (which it must be).
John McCall882987f2013-02-28 19:01:20 +00002082 Target = EmitClassRef(CGF, Class->getSuperClass());
David Blaikie1ed728c2015-04-05 22:45:47 +00002083 Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
John McCall7f416cc2015-09-08 08:05:57 +00002084 Target = CGF.Builder.CreateAlignedLoad(Target, CGF.getPointerAlign());
Mike Stump658fe022009-07-30 22:28:39 +00002085 } else {
David Blaikie1ed728c2015-04-05 22:45:47 +00002086 llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
2087 llvm::Value *SuperPtr =
2088 CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00002089 llvm::Value *Super =
2090 CGF.Builder.CreateAlignedLoad(SuperPtr, CGF.getPointerAlign());
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002091 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002092 }
David Blaikie1ed728c2015-04-05 22:45:47 +00002093 } else if (isCategoryImpl)
John McCall882987f2013-02-28 19:01:20 +00002094 Target = EmitClassRef(CGF, Class->getSuperClass());
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00002095 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002096 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
David Blaikie1ed728c2015-04-05 22:45:47 +00002097 ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00002098 Target = CGF.Builder.CreateAlignedLoad(ClassPtr, CGF.getPointerAlign());
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002099 }
Mike Stump18bb9282009-05-16 07:57:57 +00002100 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
2101 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00002102 llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00002103 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00002104 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
James Y Knight751fe282019-02-09 22:22:28 +00002105 CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall9e8bb002011-05-14 03:10:52 +00002106 return EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00002107 EmitSelector(CGF, Sel),
John McCall7f416cc2015-09-08 08:05:57 +00002108 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall1e3157b2015-09-10 22:27:50 +00002109 true, CallArgs, Method, Class, ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002110}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002111
2112/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00002113CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00002114 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00002115 QualType ResultType,
2116 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002117 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00002118 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00002119 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00002120 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00002121 return EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00002122 EmitSelector(CGF, Sel),
John McCall9e8bb002011-05-14 03:10:52 +00002123 Receiver, CGF.getContext().getObjCIdType(),
John McCall1e3157b2015-09-10 22:27:50 +00002124 false, CallArgs, Method, Class, ObjCTypes);
2125}
2126
2127static bool isWeakLinkedClass(const ObjCInterfaceDecl *ID) {
2128 do {
2129 if (ID->isWeakImported())
2130 return true;
2131 } while ((ID = ID->getSuperClass()));
2132
2133 return false;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00002134}
2135
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00002136CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00002137CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
2138 ReturnValueSlot Return,
2139 QualType ResultType,
2140 llvm::Value *Sel,
2141 llvm::Value *Arg0,
2142 QualType Arg0Ty,
2143 bool IsSuper,
2144 const CallArgList &CallArgs,
2145 const ObjCMethodDecl *Method,
John McCall1e3157b2015-09-10 22:27:50 +00002146 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00002147 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc722b852008-08-30 03:02:31 +00002148 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00002149 if (!IsSuper)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00002150 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman43dca6a2011-05-02 17:57:46 +00002151 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
2152 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCall31168b02011-06-15 23:02:42 +00002153 ActualArgs.addFrom(CallArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002154
John McCalla729c622012-02-17 03:33:10 +00002155 // If we're calling a method, use the formal signature.
2156 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002157
Anders Carlsson280e61f12010-06-21 20:59:55 +00002158 if (Method)
Alp Toker314cc812014-01-25 16:55:45 +00002159 assert(CGM.getContext().getCanonicalType(Method->getReturnType()) ==
2160 CGM.getContext().getCanonicalType(ResultType) &&
Anders Carlsson280e61f12010-06-21 20:59:55 +00002161 "Result type mismatch!");
2162
John McCall1e3157b2015-09-10 22:27:50 +00002163 bool ReceiverCanBeNull = true;
2164
2165 // Super dispatch assumes that self is non-null; even the messenger
2166 // doesn't have a null check internally.
2167 if (IsSuper) {
2168 ReceiverCanBeNull = false;
2169
2170 // If this is a direct dispatch of a class method, check whether the class,
2171 // or anything in its hierarchy, was weak-linked.
2172 } else if (ClassReceiver && Method && Method->isClassMethod()) {
2173 ReceiverCanBeNull = isWeakLinkedClass(ClassReceiver);
2174
2175 // If we're emitting a method, and self is const (meaning just ARC, for now),
2176 // and the receiver is a load of self, then self is a valid object.
2177 } else if (auto CurMethod =
2178 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) {
2179 auto Self = CurMethod->getSelfDecl();
2180 if (Self->getType().isConstQualified()) {
2181 if (auto LI = dyn_cast<llvm::LoadInst>(Arg0->stripPointerCasts())) {
2182 llvm::Value *SelfAddr = CGF.GetAddrOfLocalVar(Self).getPointer();
2183 if (SelfAddr == LI->getPointerOperand()) {
2184 ReceiverCanBeNull = false;
2185 }
2186 }
2187 }
2188 }
2189
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002190 bool RequiresNullCheck = false;
John McCall5880fb82011-05-14 21:12:11 +00002191
James Y Knight9871db02019-02-05 16:42:33 +00002192 llvm::FunctionCallee Fn = nullptr;
Tim Northovere77cc392014-03-29 13:28:05 +00002193 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002194 if (ReceiverCanBeNull) RequiresNullCheck = true;
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002195 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002196 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00002197 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
2198 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2199 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +00002200 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
2201 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2202 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002203 } else {
Tim Northovere77cc392014-03-29 13:28:05 +00002204 // arm64 uses objc_msgSend for stret methods and yet null receiver check
2205 // must be made for it.
Ahmed Bougachaa3df87b2015-10-02 22:41:59 +00002206 if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002207 RequiresNullCheck = true;
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002208 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002209 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002210 }
John McCall1e3157b2015-09-10 22:27:50 +00002211
James Y Knight9871db02019-02-05 16:42:33 +00002212 // Cast function to proper signature
2213 llvm::Constant *BitcastFn = cast<llvm::Constant>(
2214 CGF.Builder.CreateBitCast(Fn.getCallee(), MSI.MessengerType));
2215
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002216 // We don't need to emit a null check to zero out an indirect result if the
2217 // result is ignored.
2218 if (Return.isUnused())
2219 RequiresNullCheck = false;
2220
John McCall1e3157b2015-09-10 22:27:50 +00002221 // Emit a null-check if there's a consumed argument other than the receiver.
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002222 if (!RequiresNullCheck && CGM.getLangOpts().ObjCAutoRefCount && Method) {
David Majnemer59f77922016-06-24 04:05:48 +00002223 for (const auto *ParamDecl : Method->parameters()) {
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002224 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
John McCall1e3157b2015-09-10 22:27:50 +00002225 RequiresNullCheck = true;
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002226 break;
2227 }
2228 }
John McCall1e3157b2015-09-10 22:27:50 +00002229 }
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002230
2231 NullReturnState nullReturn;
2232 if (RequiresNullCheck) {
2233 nullReturn.init(CGF, Arg0);
2234 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002235
James Y Knight3933add2019-01-30 02:54:28 +00002236 llvm::CallBase *CallSite;
James Y Knight9871db02019-02-05 16:42:33 +00002237 CGCallee Callee = CGCallee::forDirect(BitcastFn);
John McCallb92ab1a2016-10-26 23:46:34 +00002238 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2239 &CallSite);
John McCall1e3157b2015-09-10 22:27:50 +00002240
2241 // Mark the call as noreturn if the method is marked noreturn and the
2242 // receiver cannot be null.
2243 if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
James Y Knight3933add2019-01-30 02:54:28 +00002244 CallSite->setDoesNotReturn();
John McCall1e3157b2015-09-10 22:27:50 +00002245 }
2246
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002247 return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
John McCall1e3157b2015-09-10 22:27:50 +00002248 RequiresNullCheck ? Method : nullptr);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002249}
2250
John McCall3fd13f062015-10-21 18:06:47 +00002251static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT,
2252 bool pointee = false) {
2253 // Note that GC qualification applies recursively to C pointer types
2254 // that aren't otherwise decorated. This is weird, but it's probably
2255 // an intentional workaround to the unreliable placement of GC qualifiers.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002256 if (FQT.isObjCGCStrong())
2257 return Qualifiers::Strong;
John McCall3fd13f062015-10-21 18:06:47 +00002258
2259 if (FQT.isObjCGCWeak())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002260 return Qualifiers::Weak;
John McCall3fd13f062015-10-21 18:06:47 +00002261
2262 if (auto ownership = FQT.getObjCLifetime()) {
2263 // Ownership does not apply recursively to C pointer types.
2264 if (pointee) return Qualifiers::GCNone;
2265 switch (ownership) {
2266 case Qualifiers::OCL_Weak: return Qualifiers::Weak;
2267 case Qualifiers::OCL_Strong: return Qualifiers::Strong;
2268 case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone;
2269 case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?");
2270 case Qualifiers::OCL_None: llvm_unreachable("known nonzero");
2271 }
2272 llvm_unreachable("bad objc ownership");
2273 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002274
John McCall3fd13f062015-10-21 18:06:47 +00002275 // Treat unqualified retainable pointers as strong.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002276 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
2277 return Qualifiers::Strong;
Fangrui Song6907ce22018-07-30 19:24:48 +00002278
John McCall3fd13f062015-10-21 18:06:47 +00002279 // Walk into C pointer types, but only in GC.
2280 if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) {
2281 if (const PointerType *PT = FQT->getAs<PointerType>())
2282 return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true);
2283 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002284
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002285 return Qualifiers::GCNone;
2286}
2287
John McCall3fd13f062015-10-21 18:06:47 +00002288namespace {
2289 struct IvarInfo {
2290 CharUnits Offset;
2291 uint64_t SizeInWords;
2292 IvarInfo(CharUnits offset, uint64_t sizeInWords)
2293 : Offset(offset), SizeInWords(sizeInWords) {}
2294
2295 // Allow sorting based on byte pos.
2296 bool operator<(const IvarInfo &other) const {
2297 return Offset < other.Offset;
2298 }
2299 };
2300
2301 /// A helper class for building GC layout strings.
2302 class IvarLayoutBuilder {
2303 CodeGenModule &CGM;
2304
2305 /// The start of the layout. Offsets will be relative to this value,
2306 /// and entries less than this value will be silently discarded.
2307 CharUnits InstanceBegin;
2308
2309 /// The end of the layout. Offsets will never exceed this value.
2310 CharUnits InstanceEnd;
2311
2312 /// Whether we're generating the strong layout or the weak layout.
2313 bool ForStrongLayout;
2314
2315 /// Whether the offsets in IvarsInfo might be out-of-order.
2316 bool IsDisordered = false;
2317
2318 llvm::SmallVector<IvarInfo, 8> IvarsInfo;
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002319
John McCall3fd13f062015-10-21 18:06:47 +00002320 public:
2321 IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
2322 CharUnits instanceEnd, bool forStrongLayout)
2323 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2324 ForStrongLayout(forStrongLayout) {
2325 }
2326
2327 void visitRecord(const RecordType *RT, CharUnits offset);
2328
2329 template <class Iterator, class GetOffsetFn>
Fangrui Song6907ce22018-07-30 19:24:48 +00002330 void visitAggregate(Iterator begin, Iterator end,
John McCall3fd13f062015-10-21 18:06:47 +00002331 CharUnits aggrOffset,
2332 const GetOffsetFn &getOffset);
2333
2334 void visitField(const FieldDecl *field, CharUnits offset);
2335
2336 /// Add the layout of a block implementation.
2337 void visitBlock(const CGBlockInfo &blockInfo);
2338
2339 /// Is there any information for an interesting bitmap?
2340 bool hasBitmapData() const { return !IvarsInfo.empty(); }
2341
2342 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2343 llvm::SmallVectorImpl<unsigned char> &buffer);
2344
2345 static void dump(ArrayRef<unsigned char> buffer) {
2346 const unsigned char *s = buffer.data();
2347 for (unsigned i = 0, e = buffer.size(); i < e; i++)
2348 if (!(s[i] & 0xf0))
2349 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
2350 else
2351 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
2352 printf("\n");
2353 }
2354 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002355} // end anonymous namespace
John McCall3fd13f062015-10-21 18:06:47 +00002356
John McCall351762c2011-02-07 10:33:21 +00002357llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
2358 const CGBlockInfo &blockInfo) {
Fangrui Song6907ce22018-07-30 19:24:48 +00002359
Chris Lattnerece04092012-02-07 00:39:47 +00002360 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
John McCall460ce582015-10-22 18:38:17 +00002361 if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
John McCall351762c2011-02-07 10:33:21 +00002362 return nullPtr;
2363
John McCall3fd13f062015-10-21 18:06:47 +00002364 IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize,
2365 /*for strong layout*/ true);
2366
2367 builder.visitBlock(blockInfo);
2368
2369 if (!builder.hasBitmapData())
2370 return nullPtr;
2371
2372 llvm::SmallVector<unsigned char, 32> buffer;
2373 llvm::Constant *C = builder.buildBitmap(*this, buffer);
John McCallf5ea0722015-10-29 23:36:14 +00002374 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
John McCall3fd13f062015-10-21 18:06:47 +00002375 printf("\n block variable layout for block: ");
2376 builder.dump(buffer);
2377 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002378
John McCall3fd13f062015-10-21 18:06:47 +00002379 return C;
2380}
2381
2382void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00002383 // __isa is the first field in block descriptor and must assume by runtime's
2384 // convention that it is GC'able.
John McCall3fd13f062015-10-21 18:06:47 +00002385 IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1));
John McCall351762c2011-02-07 10:33:21 +00002386
2387 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2388
John McCall351762c2011-02-07 10:33:21 +00002389 // Ignore the optional 'this' capture: C++ objects are not assumed
2390 // to be GC'ed.
2391
John McCall3fd13f062015-10-21 18:06:47 +00002392 CharUnits lastFieldOffset;
2393
John McCall351762c2011-02-07 10:33:21 +00002394 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002395 for (const auto &CI : blockDecl->captures()) {
2396 const VarDecl *variable = CI.getVariable();
John McCall351762c2011-02-07 10:33:21 +00002397 QualType type = variable->getType();
2398
2399 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2400
2401 // Ignore constant captures.
2402 if (capture.isConstant()) continue;
2403
John McCall3fd13f062015-10-21 18:06:47 +00002404 CharUnits fieldOffset = capture.getOffset();
2405
2406 // Block fields are not necessarily ordered; if we detect that we're
2407 // adding them out-of-order, make sure we sort later.
2408 if (fieldOffset < lastFieldOffset)
2409 IsDisordered = true;
2410 lastFieldOffset = fieldOffset;
John McCall351762c2011-02-07 10:33:21 +00002411
2412 // __block variables are passed by their descriptor address.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002413 if (CI.isByRef()) {
John McCall3fd13f062015-10-21 18:06:47 +00002414 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00002415 continue;
John McCall351762c2011-02-07 10:33:21 +00002416 }
2417
2418 assert(!type->isArrayType() && "array variable should not be caught");
2419 if (const RecordType *record = type->getAs<RecordType>()) {
John McCall3fd13f062015-10-21 18:06:47 +00002420 visitRecord(record, fieldOffset);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00002421 continue;
2422 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002423
John McCall351762c2011-02-07 10:33:21 +00002424 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
John McCall351762c2011-02-07 10:33:21 +00002425
John McCall3fd13f062015-10-21 18:06:47 +00002426 if (GCAttr == Qualifiers::Strong) {
2427 assert(CGM.getContext().getTypeSize(type)
2428 == CGM.getTarget().getPointerWidth(0));
2429 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
2430 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002431 }
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00002432}
2433
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00002434/// getBlockCaptureLifetime - This routine returns life time of the captured
2435/// block variable for the purpose of block layout meta-data generation. FQT is
2436/// the type of the variable captured in the block.
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002437Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
2438 bool ByrefLayout) {
John McCall460ce582015-10-22 18:38:17 +00002439 // If it has an ownership qualifier, we're done.
2440 if (auto lifetime = FQT.getObjCLifetime())
2441 return lifetime;
2442
2443 // If it doesn't, and this is ARC, it has no ownership.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002444 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCall460ce582015-10-22 18:38:17 +00002445 return Qualifiers::OCL_None;
Fangrui Song6907ce22018-07-30 19:24:48 +00002446
John McCall460ce582015-10-22 18:38:17 +00002447 // In MRC, retainable pointers are owned by non-__block variables.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002448 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002449 return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
Fangrui Song6907ce22018-07-30 19:24:48 +00002450
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002451 return Qualifiers::OCL_None;
2452}
2453
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002454void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
2455 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002456 CharUnits FieldOffset,
2457 CharUnits FieldSize) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002458 // __block variables are passed by their descriptor address.
2459 if (IsByref)
2460 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002461 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002462 else if (LifeTime == Qualifiers::OCL_Strong)
2463 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002464 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002465 else if (LifeTime == Qualifiers::OCL_Weak)
2466 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002467 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002468 else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2469 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002470 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002471 else
2472 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2473 FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002474 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002475}
2476
2477void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2478 const RecordDecl *RD,
2479 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002480 CharUnits BytePos, bool &HasUnion,
2481 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002482 bool IsUnion = (RD && RD->isUnion());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002483 CharUnits MaxUnionSize = CharUnits::Zero();
Craig Topper8a13c412014-05-21 05:09:00 +00002484 const FieldDecl *MaxField = nullptr;
2485 const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002486 CharUnits MaxFieldOffset = CharUnits::Zero();
2487 CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
Fangrui Song6907ce22018-07-30 19:24:48 +00002488
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002489 if (RecFields.empty())
2490 return;
John McCallc8e01702013-04-16 22:48:15 +00002491 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fangrui Song6907ce22018-07-30 19:24:48 +00002492
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002493 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2494 const FieldDecl *Field = RecFields[i];
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002495 // Note that 'i' here is actually the field index inside RD of Field,
2496 // although this dependency is hidden.
2497 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002498 CharUnits FieldOffset =
2499 CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
Fangrui Song6907ce22018-07-30 19:24:48 +00002500
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002501 // Skip over unnamed or bitfields
2502 if (!Field->getIdentifier() || Field->isBitField()) {
2503 LastFieldBitfieldOrUnnamed = Field;
2504 LastBitfieldOrUnnamedOffset = FieldOffset;
2505 continue;
2506 }
Craig Topper8a13c412014-05-21 05:09:00 +00002507
2508 LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002509 QualType FQT = Field->getType();
2510 if (FQT->isRecordType() || FQT->isUnionType()) {
2511 if (FQT->isUnionType())
2512 HasUnion = true;
Fangrui Song6907ce22018-07-30 19:24:48 +00002513
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002514 BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
2515 BytePos + FieldOffset, HasUnion);
2516 continue;
2517 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002518
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002519 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00002520 auto *CArray = cast<ConstantArrayType>(Array);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002521 uint64_t ElCount = CArray->getSize().getZExtValue();
2522 assert(CArray && "only array with known element size is supported");
2523 FQT = CArray->getElementType();
2524 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00002525 auto *CArray = cast<ConstantArrayType>(Array);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002526 ElCount *= CArray->getSize().getZExtValue();
2527 FQT = CArray->getElementType();
2528 }
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002529 if (FQT->isRecordType() && ElCount) {
2530 int OldIndex = RunSkipBlockVars.size() - 1;
2531 const RecordType *RT = FQT->getAs<RecordType>();
2532 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
2533 HasUnion);
Fangrui Song6907ce22018-07-30 19:24:48 +00002534
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002535 // Replicate layout information for each array element. Note that
2536 // one element is already done.
2537 uint64_t ElIx = 1;
2538 for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002539 CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002540 for (int i = OldIndex+1; i <= FirstIndex; ++i)
2541 RunSkipBlockVars.push_back(
2542 RUN_SKIP(RunSkipBlockVars[i].opcode,
2543 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2544 RunSkipBlockVars[i].block_var_size));
2545 }
2546 continue;
2547 }
2548 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002549 CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002550 if (IsUnion) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002551 CharUnits UnionIvarSize = FieldSize;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002552 if (UnionIvarSize > MaxUnionSize) {
2553 MaxUnionSize = UnionIvarSize;
2554 MaxField = Field;
2555 MaxFieldOffset = FieldOffset;
2556 }
2557 } else {
2558 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002559 getBlockCaptureLifetime(FQT, ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002560 BytePos + FieldOffset,
2561 FieldSize);
2562 }
2563 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002564
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002565 if (LastFieldBitfieldOrUnnamed) {
2566 if (LastFieldBitfieldOrUnnamed->isBitField()) {
2567 // Last field was a bitfield. Must update the info.
2568 uint64_t BitFieldSize
2569 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002570 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
Eli Friedman8cbca202012-11-06 22:15:52 +00002571 ((BitFieldSize % ByteSizeInBits) != 0);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002572 CharUnits Size = CharUnits::fromQuantity(UnsSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002573 Size += LastBitfieldOrUnnamedOffset;
2574 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002575 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2576 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002577 BytePos + LastBitfieldOrUnnamedOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002578 Size);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002579 } else {
2580 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2581 // Last field was unnamed. Must update skip info.
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002582 CharUnits FieldSize
2583 = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002584 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002585 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2586 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002587 BytePos + LastBitfieldOrUnnamedOffset,
2588 FieldSize);
2589 }
2590 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002591
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002592 if (MaxField)
2593 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002594 getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002595 BytePos + MaxFieldOffset,
2596 MaxUnionSize);
2597}
2598
2599void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002600 CharUnits BytePos,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002601 bool &HasUnion,
2602 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002603 const RecordDecl *RD = RT->getDecl();
Aaron Ballman62e47c42014-03-10 13:43:55 +00002604 SmallVector<const FieldDecl*, 16> Fields(RD->fields());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002605 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
2606 const llvm::StructLayout *RecLayout =
2607 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
Fangrui Song6907ce22018-07-30 19:24:48 +00002608
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002609 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002610}
2611
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002612/// InlineLayoutInstruction - This routine produce an inline instruction for the
2613/// block variable layout if it can. If not, it returns 0. Rules are as follow:
2614/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
2615/// an inline layout of value 0x0000000000000xyz is interpreted as follows:
2616/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
2617/// y captured object of BLOCK_LAYOUT_BYREF. Followed by
2618/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
2619/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
2620/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
2621uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2622 SmallVectorImpl<unsigned char> &Layout) {
2623 uint64_t Result = 0;
2624 if (Layout.size() <= 3) {
2625 unsigned size = Layout.size();
2626 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2627 unsigned char inst;
2628 enum BLOCK_LAYOUT_OPCODE opcode ;
2629 switch (size) {
2630 case 3:
2631 inst = Layout[0];
2632 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2633 if (opcode == BLOCK_LAYOUT_STRONG)
2634 strong_word_count = (inst & 0xF)+1;
2635 else
2636 return 0;
2637 inst = Layout[1];
2638 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2639 if (opcode == BLOCK_LAYOUT_BYREF)
2640 byref_word_count = (inst & 0xF)+1;
2641 else
2642 return 0;
2643 inst = Layout[2];
2644 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2645 if (opcode == BLOCK_LAYOUT_WEAK)
2646 weak_word_count = (inst & 0xF)+1;
2647 else
2648 return 0;
2649 break;
Fangrui Song6907ce22018-07-30 19:24:48 +00002650
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002651 case 2:
2652 inst = Layout[0];
2653 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2654 if (opcode == BLOCK_LAYOUT_STRONG) {
2655 strong_word_count = (inst & 0xF)+1;
2656 inst = Layout[1];
2657 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2658 if (opcode == BLOCK_LAYOUT_BYREF)
2659 byref_word_count = (inst & 0xF)+1;
2660 else if (opcode == BLOCK_LAYOUT_WEAK)
2661 weak_word_count = (inst & 0xF)+1;
2662 else
2663 return 0;
2664 }
2665 else if (opcode == BLOCK_LAYOUT_BYREF) {
2666 byref_word_count = (inst & 0xF)+1;
2667 inst = Layout[1];
2668 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2669 if (opcode == BLOCK_LAYOUT_WEAK)
2670 weak_word_count = (inst & 0xF)+1;
2671 else
2672 return 0;
2673 }
2674 else
2675 return 0;
2676 break;
Fangrui Song6907ce22018-07-30 19:24:48 +00002677
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002678 case 1:
2679 inst = Layout[0];
2680 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2681 if (opcode == BLOCK_LAYOUT_STRONG)
2682 strong_word_count = (inst & 0xF)+1;
2683 else if (opcode == BLOCK_LAYOUT_BYREF)
2684 byref_word_count = (inst & 0xF)+1;
2685 else if (opcode == BLOCK_LAYOUT_WEAK)
2686 weak_word_count = (inst & 0xF)+1;
2687 else
2688 return 0;
2689 break;
Fangrui Song6907ce22018-07-30 19:24:48 +00002690
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002691 default:
2692 return 0;
2693 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002694
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002695 // Cannot inline when any of the word counts is 15. Because this is one less
2696 // than the actual work count (so 15 means 16 actual word counts),
2697 // and we can only display 0 thru 15 word counts.
2698 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2699 return 0;
Fangrui Song6907ce22018-07-30 19:24:48 +00002700
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002701 unsigned count =
2702 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
Fangrui Song6907ce22018-07-30 19:24:48 +00002703
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002704 if (size == count) {
2705 if (strong_word_count)
2706 Result = strong_word_count;
2707 Result <<= 4;
2708 if (byref_word_count)
2709 Result += byref_word_count;
2710 Result <<= 4;
2711 if (weak_word_count)
2712 Result += weak_word_count;
2713 }
2714 }
2715 return Result;
2716}
2717
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002718llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
2719 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2720 if (RunSkipBlockVars.empty())
2721 return nullPtr;
John McCallc8e01702013-04-16 22:48:15 +00002722 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2723 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002724 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
Fangrui Song6907ce22018-07-30 19:24:48 +00002725
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002726 // Sort on byte position; captures might not be allocated in order,
2727 // and unions can do funny things.
2728 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2729 SmallVector<unsigned char, 16> Layout;
Fangrui Song6907ce22018-07-30 19:24:48 +00002730
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002731 unsigned size = RunSkipBlockVars.size();
2732 for (unsigned i = 0; i < size; i++) {
2733 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2734 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2735 CharUnits end_byte_pos = start_byte_pos;
2736 unsigned j = i+1;
2737 while (j < size) {
2738 if (opcode == RunSkipBlockVars[j].opcode) {
2739 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2740 i++;
2741 }
2742 else
2743 break;
2744 }
2745 CharUnits size_in_bytes =
2746 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2747 if (j < size) {
2748 CharUnits gap =
2749 RunSkipBlockVars[j].block_var_bytepos -
2750 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2751 size_in_bytes += gap;
2752 }
2753 CharUnits residue_in_bytes = CharUnits::Zero();
2754 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2755 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2756 size_in_bytes -= residue_in_bytes;
2757 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2758 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002759
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002760 unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
2761 while (size_in_words >= 16) {
2762 // Note that value in imm. is one less that the actual
2763 // value. So, 0xf means 16 words follow!
2764 unsigned char inst = (opcode << 4) | 0xf;
2765 Layout.push_back(inst);
2766 size_in_words -= 16;
2767 }
2768 if (size_in_words > 0) {
2769 // Note that value in imm. is one less that the actual
2770 // value. So, we subtract 1 away!
2771 unsigned char inst = (opcode << 4) | (size_in_words-1);
2772 Layout.push_back(inst);
2773 }
2774 if (residue_in_bytes > CharUnits::Zero()) {
2775 unsigned char inst =
2776 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
2777 Layout.push_back(inst);
2778 }
2779 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002780
John McCall7f416cc2015-09-08 08:05:57 +00002781 while (!Layout.empty()) {
2782 unsigned char inst = Layout.back();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002783 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2784 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2785 Layout.pop_back();
2786 else
2787 break;
2788 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002789
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002790 uint64_t Result = InlineLayoutInstruction(Layout);
2791 if (Result != 0) {
2792 // Block variable layout instruction has been inlined.
2793 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2794 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002795 printf("\n Inline BYREF variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002796 else
John McCall7f416cc2015-09-08 08:05:57 +00002797 printf("\n Inline block variable layout: ");
2798 printf("0x0%" PRIx64 "", Result);
2799 if (auto numStrong = (Result & 0xF00) >> 8)
2800 printf(", BL_STRONG:%d", (int) numStrong);
2801 if (auto numByref = (Result & 0x0F0) >> 4)
2802 printf(", BL_BYREF:%d", (int) numByref);
2803 if (auto numWeak = (Result & 0x00F) >> 0)
2804 printf(", BL_WEAK:%d", (int) numWeak);
2805 printf(", BL_OPERATOR:0\n");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002806 }
Vedant Kumar3ed0df02015-12-21 19:43:25 +00002807 return llvm::ConstantInt::get(CGM.IntPtrTy, Result);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002808 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002809
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002810 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2811 Layout.push_back(inst);
2812 std::string BitMap;
2813 for (unsigned i = 0, e = Layout.size(); i != e; i++)
2814 BitMap += Layout[i];
Fangrui Song6907ce22018-07-30 19:24:48 +00002815
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002816 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2817 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002818 printf("\n Byref variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002819 else
John McCall7f416cc2015-09-08 08:05:57 +00002820 printf("\n Block variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002821 for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
2822 unsigned char inst = BitMap[i];
2823 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2824 unsigned delta = 1;
2825 switch (opcode) {
2826 case BLOCK_LAYOUT_OPERATOR:
2827 printf("BL_OPERATOR:");
2828 delta = 0;
2829 break;
2830 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2831 printf("BL_NON_OBJECT_BYTES:");
2832 break;
2833 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2834 printf("BL_NON_OBJECT_WORD:");
2835 break;
2836 case BLOCK_LAYOUT_STRONG:
2837 printf("BL_STRONG:");
2838 break;
2839 case BLOCK_LAYOUT_BYREF:
2840 printf("BL_BYREF:");
2841 break;
2842 case BLOCK_LAYOUT_WEAK:
2843 printf("BL_WEAK:");
2844 break;
2845 case BLOCK_LAYOUT_UNRETAINED:
2846 printf("BL_UNRETAINED:");
2847 break;
2848 }
2849 // Actual value of word count is one more that what is in the imm.
2850 // field of the instruction
2851 printf("%d", (inst & 0xf) + delta);
2852 if (i < e-1)
2853 printf(", ");
2854 else
2855 printf("\n");
2856 }
2857 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00002858
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00002859 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2860 /*ForceNonFragileABI=*/true,
2861 /*NullTerminate=*/false);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002862 return getConstantGEP(VMContext, Entry, 0, 0);
2863}
2864
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00002865static std::string getBlockLayoutInfoString(
2866 const SmallVectorImpl<CGObjCCommonMac::RUN_SKIP> &RunSkipBlockVars,
2867 bool HasCopyDisposeHelpers) {
2868 std::string Str;
2869 for (const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
2870 if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
2871 // Copy/dispose helpers don't have any information about
2872 // __unsafe_unretained captures, so unconditionally concatenate a string.
2873 Str += "u";
2874 } else if (HasCopyDisposeHelpers) {
2875 // Information about __strong, __weak, or byref captures has already been
2876 // encoded into the names of the copy/dispose helpers. We have to add a
2877 // string here only when the copy/dispose helpers aren't generated (which
2878 // happens when the block is non-escaping).
2879 continue;
2880 } else {
2881 switch (R.opcode) {
2882 case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
2883 Str += "s";
2884 break;
2885 case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
2886 Str += "r";
2887 break;
2888 case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
2889 Str += "w";
2890 break;
2891 default:
2892 continue;
2893 }
2894 }
2895 Str += llvm::to_string(R.block_var_bytepos.getQuantity());
2896 Str += "l" + llvm::to_string(R.block_var_size.getQuantity());
2897 }
2898 return Str;
2899}
2900
2901void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM,
2902 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002903 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
Fangrui Song6907ce22018-07-30 19:24:48 +00002904
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002905 RunSkipBlockVars.clear();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002906 bool hasUnion = false;
Fangrui Song6907ce22018-07-30 19:24:48 +00002907
John McCallc8e01702013-04-16 22:48:15 +00002908 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2909 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002910 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
Fangrui Song6907ce22018-07-30 19:24:48 +00002911
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002912 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
Fangrui Song6907ce22018-07-30 19:24:48 +00002913
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002914 // Calculate the basic layout of the block structure.
2915 const llvm::StructLayout *layout =
2916 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
Fangrui Song6907ce22018-07-30 19:24:48 +00002917
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002918 // Ignore the optional 'this' capture: C++ objects are not assumed
2919 // to be GC'ed.
Fariborz Jahanian4cf177e2012-12-04 17:20:57 +00002920 if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
2921 UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
2922 blockInfo.BlockHeaderForcedGapOffset,
2923 blockInfo.BlockHeaderForcedGapSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002924 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002925 for (const auto &CI : blockDecl->captures()) {
2926 const VarDecl *variable = CI.getVariable();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002927 QualType type = variable->getType();
Fangrui Song6907ce22018-07-30 19:24:48 +00002928
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002929 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
Fangrui Song6907ce22018-07-30 19:24:48 +00002930
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002931 // Ignore constant captures.
2932 if (capture.isConstant()) continue;
Fangrui Song6907ce22018-07-30 19:24:48 +00002933
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002934 CharUnits fieldOffset =
2935 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fangrui Song6907ce22018-07-30 19:24:48 +00002936
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002937 assert(!type->isArrayType() && "array variable should not be caught");
Aaron Ballman9371dd22014-03-14 18:34:04 +00002938 if (!CI.isByRef())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002939 if (const RecordType *record = type->getAs<RecordType>()) {
2940 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2941 continue;
2942 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002943 CharUnits fieldSize;
Aaron Ballman9371dd22014-03-14 18:34:04 +00002944 if (CI.isByRef())
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002945 fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2946 else
2947 fieldSize = CGM.getContext().getTypeSizeInChars(type);
Aaron Ballman9371dd22014-03-14 18:34:04 +00002948 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002949 fieldOffset, fieldSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002950 }
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00002951}
2952
2953llvm::Constant *
2954CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2955 const CGBlockInfo &blockInfo) {
2956 fillRunSkipBlockVars(CGM, blockInfo);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002957 return getBitmapBlockLayout(false);
2958}
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002959
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00002960std::string CGObjCCommonMac::getRCBlockLayoutStr(CodeGenModule &CGM,
2961 const CGBlockInfo &blockInfo) {
2962 fillRunSkipBlockVars(CGM, blockInfo);
2963 return getBlockLayoutInfoString(RunSkipBlockVars,
2964 blockInfo.needsCopyDisposeHelpers());
2965}
2966
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002967llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2968 QualType T) {
2969 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2970 assert(!T->isArrayType() && "__block array variable should not be caught");
2971 CharUnits fieldOffset;
2972 RunSkipBlockVars.clear();
2973 bool hasUnion = false;
2974 if (const RecordType *record = T->getAs<RecordType>()) {
2975 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
2976 llvm::Constant *Result = getBitmapBlockLayout(true);
Vedant Kumar2f5bb1152015-12-21 20:21:15 +00002977 if (isa<llvm::ConstantInt>(Result))
2978 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002979 return Result;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002980 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002981 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2982 return nullPtr;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002983}
2984
John McCall882987f2013-02-28 19:01:20 +00002985llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00002986 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00002987 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002988 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00002989 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2990
Owen Andersonade90fd2009-07-29 18:54:39 +00002991 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00002992 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002993}
2994
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002995void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00002996 // FIXME: We shouldn't need this, the protocol decl should contain enough
2997 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00002998 DefinedProtocols.insert(PD->getIdentifier());
2999
3000 // If we have generated a forward reference to this protocol, emit
3001 // it now. Otherwise do nothing, the protocol objects are lazily
3002 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003003 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00003004 GetOrEmitProtocol(PD);
3005}
3006
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00003007llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00003008 if (DefinedProtocols.count(PD->getIdentifier()))
3009 return GetOrEmitProtocol(PD);
Fangrui Song6907ce22018-07-30 19:24:48 +00003010
Daniel Dunbarc475d422008-10-29 22:36:39 +00003011 return GetOrEmitProtocolRef(PD);
3012}
3013
Douglas Gregor24ae22c2016-04-01 23:23:52 +00003014llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
3015 CodeGenFunction &CGF,
3016 const ObjCInterfaceDecl *ID,
3017 ObjCCommonTypesHelper &ObjCTypes) {
James Y Knight9871db02019-02-05 16:42:33 +00003018 llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
Douglas Gregor24ae22c2016-04-01 23:23:52 +00003019
3020 llvm::Value *className =
3021 CGF.CGM.GetAddrOfConstantCString(ID->getObjCRuntimeNameAsString())
3022 .getPointer();
3023 ASTContext &ctx = CGF.CGM.getContext();
3024 className =
3025 CGF.Builder.CreateBitCast(className,
3026 CGF.ConvertType(
3027 ctx.getPointerType(ctx.CharTy.withConst())));
3028 llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className);
3029 call->setDoesNotThrow();
3030 return call;
3031}
3032
Daniel Dunbarb036db82008-08-13 03:21:16 +00003033/*
Rafael Espindolaf9e1e5e2014-02-20 14:09:04 +00003034// Objective-C 1.0 extensions
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003035struct _objc_protocol {
3036struct _objc_protocol_extension *isa;
3037char *protocol_name;
3038struct _objc_protocol_list *protocol_list;
3039struct _objc__method_prototype_list *instance_methods;
3040struct _objc__method_prototype_list *class_methods
3041};
Daniel Dunbarb036db82008-08-13 03:21:16 +00003042
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003043See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00003044*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00003045llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00003046 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbarc475d422008-10-29 22:36:39 +00003047
3048 // Early exit if a defining object has already been generated.
3049 if (Entry && Entry->hasInitializer())
3050 return Entry;
3051
Douglas Gregora715bff2012-01-01 19:51:50 +00003052 // Use the protocol definition, if there is one.
3053 if (const ObjCProtocolDecl *Def = PD->getDefinition())
3054 PD = Def;
3055
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003056 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00003057 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003058 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
3059
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003060 // Construct method lists.
John McCall176f8922016-11-30 02:39:18 +00003061 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003062
John McCall176f8922016-11-30 02:39:18 +00003063 ConstantInitBuilder builder(CGM);
3064 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
3065 values.add(EmitProtocolExtension(PD, methodLists));
3066 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
3067 values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
3068 PD->protocol_begin(), PD->protocol_end()));
3069 values.add(methodLists.emitMethodList(this, PD,
3070 ProtocolMethodLists::RequiredInstanceMethods));
3071 values.add(methodLists.emitMethodList(this, PD,
3072 ProtocolMethodLists::RequiredClassMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003073
Daniel Dunbarb036db82008-08-13 03:21:16 +00003074 if (Entry) {
Rafael Espindola5d117f32014-03-06 01:10:46 +00003075 // Already created, update the initializer.
Rafael Espindolab3262952014-05-09 00:43:37 +00003076 assert(Entry->hasPrivateLinkage());
John McCall176f8922016-11-30 02:39:18 +00003077 values.finishAndSetAsInitializer(Entry);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003078 } else {
John McCall176f8922016-11-30 02:39:18 +00003079 Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(),
3080 CGM.getPointerAlign(),
3081 /*constant*/ false,
3082 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003083 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
John McCallf9582a72012-03-30 21:29:05 +00003084
3085 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00003086 }
Rafael Espindola060062a2014-03-06 22:15:10 +00003087 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00003088
3089 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00003090}
3091
Daniel Dunbarc475d422008-10-29 22:36:39 +00003092llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003093 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
3094
3095 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00003096 // We use the initializer as a marker of whether this is a forward
3097 // reference or not. At module finalization we add the empty
3098 // contents for protocols which were referenced but never defined.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003099 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
3100 false, llvm::GlobalValue::PrivateLinkage,
3101 nullptr, "OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00003102 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00003103 // FIXME: Is this necessary? Why only for protocol?
Guillaume Chateletc79099e2019-10-03 13:00:29 +00003104 Entry->setAlignment(llvm::Align(4));
Daniel Dunbarb036db82008-08-13 03:21:16 +00003105 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003106
Daniel Dunbarb036db82008-08-13 03:21:16 +00003107 return Entry;
3108}
3109
3110/*
3111 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003112 uint32_t size;
3113 struct objc_method_description_list *optional_instance_methods;
3114 struct objc_method_description_list *optional_class_methods;
3115 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003116 const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00003117 struct objc_property_list *class_properties;
Daniel Dunbarb036db82008-08-13 03:21:16 +00003118 };
3119*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003120llvm::Constant *
3121CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00003122 const ProtocolMethodLists &methodLists) {
3123 auto optInstanceMethods =
3124 methodLists.emitMethodList(this, PD,
3125 ProtocolMethodLists::OptionalInstanceMethods);
3126 auto optClassMethods =
3127 methodLists.emitMethodList(this, PD,
3128 ProtocolMethodLists::OptionalClassMethods);
3129
3130 auto extendedMethodTypes =
3131 EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
3132 methodLists.emitExtendedTypesArray(this),
3133 ObjCTypes);
3134
3135 auto instanceProperties =
3136 EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD,
3137 ObjCTypes, false);
3138 auto classProperties =
3139 EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr,
3140 PD, ObjCTypes, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003141
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003142 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00003143 if (optInstanceMethods->isNullValue() &&
3144 optClassMethods->isNullValue() &&
3145 extendedMethodTypes->isNullValue() &&
3146 instanceProperties->isNullValue() &&
3147 classProperties->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003148 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003149 }
Daniel Dunbarb036db82008-08-13 03:21:16 +00003150
John McCall176f8922016-11-30 02:39:18 +00003151 uint64_t size =
3152 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3153
3154 ConstantInitBuilder builder(CGM);
3155 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3156 values.addInt(ObjCTypes.IntTy, size);
3157 values.add(optInstanceMethods);
3158 values.add(optClassMethods);
3159 values.add(instanceProperties);
3160 values.add(extendedMethodTypes);
3161 values.add(classProperties);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003162
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003163 // No special section, but goes in llvm.used
Akira Hatanaka187770d2019-05-09 17:43:52 +00003164 return CreateMetadataVar("_OBJC_PROTOCOLEXT_" + PD->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00003165 StringRef(), CGM.getPointerAlign(), true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003166}
3167
3168/*
3169 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00003170 struct objc_protocol_list *next;
3171 long count;
3172 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00003173 };
3174*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00003175llvm::Constant *
Zachary Turner41a9ee92017-10-11 23:54:34 +00003176CGObjCMac::EmitProtocolList(Twine name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00003177 ObjCProtocolDecl::protocol_iterator begin,
3178 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003179 // Just return null for empty protocol lists
John McCall176f8922016-11-30 02:39:18 +00003180 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00003181 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003182
John McCall176f8922016-11-30 02:39:18 +00003183 ConstantInitBuilder builder(CGM);
3184 auto values = builder.beginStruct();
Daniel Dunbarb036db82008-08-13 03:21:16 +00003185
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003186 // This field is only used by the runtime.
John McCall176f8922016-11-30 02:39:18 +00003187 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003188
John McCall176f8922016-11-30 02:39:18 +00003189 // Reserve a slot for the count.
3190 auto countSlot = values.addPlaceholder();
3191
3192 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3193 for (; begin != end; ++begin) {
3194 refsArray.add(GetProtocolRef(*begin));
3195 }
3196 auto count = refsArray.size();
3197
3198 // This list is null terminated.
3199 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3200
3201 refsArray.finishAndAddTo(values);
3202 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3203
3204 StringRef section;
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003205 if (CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00003206 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003207
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003208 llvm::GlobalVariable *GV =
Zachary Turner41a9ee92017-10-11 23:54:34 +00003209 CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false);
Owen Andersonade90fd2009-07-29 18:54:39 +00003210 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003211}
3212
Fangrui Song6907ce22018-07-30 19:24:48 +00003213static void
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003214PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
John McCall176f8922016-11-30 02:39:18 +00003215 SmallVectorImpl<const ObjCPropertyDecl *> &Properties,
Aaron Ballmandc4bea42014-03-13 18:47:37 +00003216 const ObjCProtocolDecl *Proto,
Manman Renad0e7912016-01-29 19:22:54 +00003217 bool IsClassProperty) {
Fangrui Song6907ce22018-07-30 19:24:48 +00003218 for (const auto *P : Proto->protocols())
John McCall176f8922016-11-30 02:39:18 +00003219 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Manman Renad0e7912016-01-29 19:22:54 +00003220
3221 for (const auto *PD : Proto->properties()) {
3222 if (IsClassProperty != PD->isClassProperty())
3223 continue;
David Blaikie82e95a32014-11-19 07:49:47 +00003224 if (!PropertySet.insert(PD->getIdentifier()).second)
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003225 continue;
John McCall176f8922016-11-30 02:39:18 +00003226 Properties.push_back(PD);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003227 }
3228}
3229
Daniel Dunbarb036db82008-08-13 03:21:16 +00003230/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003231 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00003232 const char * const name;
3233 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003234 };
3235
3236 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00003237 uint32_t entsize; // sizeof (struct _objc_property)
3238 uint32_t prop_count;
3239 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003240 };
3241*/
Zachary Turner41a9ee92017-10-11 23:54:34 +00003242llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
3243 const Decl *Container,
3244 const ObjCContainerDecl *OCD,
3245 const ObjCCommonTypesHelper &ObjCTypes,
3246 bool IsClassProperty) {
Manman Ren01b705e2016-04-19 19:05:03 +00003247 if (IsClassProperty) {
3248 // Make this entry NULL for OS X with deployment target < 10.11, for iOS
3249 // with deployment target < 9.0.
3250 const llvm::Triple &Triple = CGM.getTarget().getTriple();
3251 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3252 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3253 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3254 }
3255
John McCall176f8922016-11-30 02:39:18 +00003256 SmallVector<const ObjCPropertyDecl *, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003257 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Nico Weber08c93332015-12-03 17:44:51 +00003258
Nico Weber08c93332015-12-03 17:44:51 +00003259 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3260 for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
Manman Renad0e7912016-01-29 19:22:54 +00003261 for (auto *PD : ClassExt->properties()) {
3262 if (IsClassProperty != PD->isClassProperty())
3263 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003264 PropertySet.insert(PD->getIdentifier());
John McCall176f8922016-11-30 02:39:18 +00003265 Properties.push_back(PD);
Nico Weber08c93332015-12-03 17:44:51 +00003266 }
Manman Renad0e7912016-01-29 19:22:54 +00003267
3268 for (const auto *PD : OCD->properties()) {
3269 if (IsClassProperty != PD->isClassProperty())
3270 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003271 // Don't emit duplicate metadata for properties that were already in a
3272 // class extension.
3273 if (!PropertySet.insert(PD->getIdentifier()).second)
3274 continue;
John McCall176f8922016-11-30 02:39:18 +00003275 Properties.push_back(PD);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003276 }
Nico Weber08c93332015-12-03 17:44:51 +00003277
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003278 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003279 for (const auto *P : OID->all_referenced_protocols())
John McCall176f8922016-11-30 02:39:18 +00003280 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003281 }
3282 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
Aaron Ballman19a41762014-03-14 12:55:57 +00003283 for (const auto *P : CD->protocols())
John McCall176f8922016-11-30 02:39:18 +00003284 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003285 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003286
3287 // Return null for empty list.
3288 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003289 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003290
John McCall176f8922016-11-30 02:39:18 +00003291 unsigned propertySize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00003292 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
John McCall176f8922016-11-30 02:39:18 +00003293
3294 ConstantInitBuilder builder(CGM);
3295 auto values = builder.beginStruct();
3296 values.addInt(ObjCTypes.IntTy, propertySize);
3297 values.addInt(ObjCTypes.IntTy, Properties.size());
3298 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3299 for (auto PD : Properties) {
3300 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3301 property.add(GetPropertyName(PD->getIdentifier()));
3302 property.add(GetPropertyTypeString(PD, Container));
3303 property.finishAndAddTo(propertiesArray);
3304 }
3305 propertiesArray.finishAndAddTo(values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003306
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003307 StringRef Section;
3308 if (CGM.getTriple().isOSBinFormatMachO())
3309 Section = (ObjCABI == 2) ? "__DATA, __objc_const"
3310 : "__OBJC,__property,regular,no_dead_strip";
3311
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003312 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003313 CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003314 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003315}
3316
Zachary Turner41a9ee92017-10-11 23:54:34 +00003317llvm::Constant *
3318CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
3319 ArrayRef<llvm::Constant*> MethodTypes,
3320 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003321 // Return null for empty list.
3322 if (MethodTypes.empty())
3323 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3324
3325 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3326 MethodTypes.size());
3327 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
3328
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003329 StringRef Section;
3330 if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3331 Section = "__DATA, __objc_const";
3332
3333 llvm::GlobalVariable *GV =
3334 CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003335 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
3336}
3337
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003338/*
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003339 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003340 char *category_name;
3341 char *class_name;
3342 struct _objc_method_list *instance_methods;
3343 struct _objc_method_list *class_methods;
3344 struct _objc_protocol_list *protocols;
3345 uint32_t size; // <rdar://4585769>
3346 struct _objc_property_list *instance_properties;
Manman Ren96df0b32016-01-29 23:45:01 +00003347 struct _objc_property_list *class_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003348 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003349*/
Daniel Dunbar92992502008-08-15 22:20:32 +00003350void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00003351 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003352
Mike Stump18bb9282009-05-16 07:57:57 +00003353 // FIXME: This is poor design, the OCD should have a pointer to the category
3354 // decl. Additionally, note that Category can be null for the @implementation
3355 // w/o an @interface case. Sema should just create one for us as it does for
3356 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003357 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003358 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003359 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003360
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003361 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003362 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
3363 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003364
John McCall176f8922016-11-30 02:39:18 +00003365 ConstantInitBuilder Builder(CGM);
3366 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
Aaron Ballmanf26acce2014-03-13 19:50:17 +00003367
John McCall176f8922016-11-30 02:39:18 +00003368 enum {
3369 InstanceMethods,
3370 ClassMethods,
3371 NumMethodLists
3372 };
3373 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3374 for (const auto *MD : OCD->methods()) {
3375 Methods[unsigned(MD->isClassMethod())].push_back(MD);
3376 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003377
John McCall176f8922016-11-30 02:39:18 +00003378 Values.add(GetClassName(OCD->getName()));
3379 Values.add(GetClassName(Interface->getObjCRuntimeNameAsString()));
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00003380 LazySymbols.insert(Interface->getIdentifier());
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003381
John McCall176f8922016-11-30 02:39:18 +00003382 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3383 Methods[InstanceMethods]));
3384 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3385 Methods[ClassMethods]));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003386 if (Category) {
John McCall176f8922016-11-30 02:39:18 +00003387 Values.add(
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003388 EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003389 Category->protocol_begin(), Category->protocol_end()));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003390 } else {
John McCall176f8922016-11-30 02:39:18 +00003391 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003392 }
John McCall176f8922016-11-30 02:39:18 +00003393 Values.addInt(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003394
3395 // If there is no category @interface then there can be no properties.
3396 if (Category) {
Akira Hatanaka187770d2019-05-09 17:43:52 +00003397 Values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003398 OCD, Category, ObjCTypes, false));
Akira Hatanaka187770d2019-05-09 17:43:52 +00003399 Values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003400 OCD, Category, ObjCTypes, true));
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003401 } else {
John McCall176f8922016-11-30 02:39:18 +00003402 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3403 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003404 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003405
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003406 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003407 CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values,
John McCall7f416cc2015-09-08 08:05:57 +00003408 "__OBJC,__category,regular,no_dead_strip",
3409 CGM.getPointerAlign(), true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003410 DefinedCategories.push_back(GV);
Justin Lebar5e83dfe2016-10-21 21:45:01 +00003411 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003412 // method definition entries must be clear for next implementation.
3413 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003414}
3415
John McCallef19dbb2012-10-17 04:53:23 +00003416enum FragileClassFlags {
John McCall460ce582015-10-22 18:38:17 +00003417 /// Apparently: is not a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003418 FragileABI_Class_Factory = 0x00001,
John McCall460ce582015-10-22 18:38:17 +00003419
3420 /// Is a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003421 FragileABI_Class_Meta = 0x00002,
John McCall460ce582015-10-22 18:38:17 +00003422
3423 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003424 FragileABI_Class_HasCXXStructors = 0x02000,
John McCall460ce582015-10-22 18:38:17 +00003425
3426 /// Has hidden visibility.
John McCall09ec1ec2015-10-21 22:06:03 +00003427 FragileABI_Class_Hidden = 0x20000,
John McCall460ce582015-10-22 18:38:17 +00003428
3429 /// Class implementation was compiled under ARC.
3430 FragileABI_Class_CompiledByARC = 0x04000000,
3431
3432 /// Class implementation was compiled under MRC and has MRC weak ivars.
3433 /// Exclusive with CompiledByARC.
3434 FragileABI_Class_HasMRCWeakIvars = 0x08000000,
John McCallef19dbb2012-10-17 04:53:23 +00003435};
3436
3437enum NonFragileClassFlags {
3438 /// Is a meta-class.
3439 NonFragileABI_Class_Meta = 0x00001,
3440
3441 /// Is a root class.
3442 NonFragileABI_Class_Root = 0x00002,
3443
John McCall460ce582015-10-22 18:38:17 +00003444 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003445 NonFragileABI_Class_HasCXXStructors = 0x00004,
3446
3447 /// Has hidden visibility.
3448 NonFragileABI_Class_Hidden = 0x00010,
3449
3450 /// Has the exception attribute.
3451 NonFragileABI_Class_Exception = 0x00020,
3452
3453 /// (Obsolete) ARC-specific: this class has a .release_ivars method
3454 NonFragileABI_Class_HasIvarReleaser = 0x00040,
3455
3456 /// Class implementation was compiled under ARC.
John McCall0d54a172012-10-17 04:53:31 +00003457 NonFragileABI_Class_CompiledByARC = 0x00080,
3458
3459 /// Class has non-trivial destructors, but zero-initialization is okay.
John McCall460ce582015-10-22 18:38:17 +00003460 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100,
3461
3462 /// Class implementation was compiled under MRC and has MRC weak ivars.
3463 /// Exclusive with CompiledByARC.
3464 NonFragileABI_Class_HasMRCWeakIvars = 0x00200,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003465};
3466
John McCall460ce582015-10-22 18:38:17 +00003467static bool hasWeakMember(QualType type) {
3468 if (type.getObjCLifetime() == Qualifiers::OCL_Weak) {
3469 return true;
3470 }
3471
3472 if (auto recType = type->getAs<RecordType>()) {
3473 for (auto field : recType->getDecl()->fields()) {
3474 if (hasWeakMember(field->getType()))
3475 return true;
3476 }
3477 }
3478
3479 return false;
3480}
3481
3482/// For compatibility, we only want to set the "HasMRCWeakIvars" flag
3483/// (and actually fill in a layout string) if we really do have any
3484/// __weak ivars.
3485static bool hasMRCWeakIvars(CodeGenModule &CGM,
3486 const ObjCImplementationDecl *ID) {
3487 if (!CGM.getLangOpts().ObjCWeak) return false;
3488 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
3489
3490 for (const ObjCIvarDecl *ivar =
3491 ID->getClassInterface()->all_declared_ivar_begin();
3492 ivar; ivar = ivar->getNextIvar()) {
3493 if (hasWeakMember(ivar->getType()))
3494 return true;
3495 }
3496
3497 return false;
3498}
3499
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003500/*
3501 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003502 Class isa;
3503 Class super_class;
3504 const char *name;
3505 long version;
3506 long info;
3507 long instance_size;
3508 struct _objc_ivar_list *ivars;
3509 struct _objc_method_list *methods;
3510 struct _objc_cache *cache;
3511 struct _objc_protocol_list *protocols;
3512 // Objective-C 1.0 extensions (<rdr://4585769>)
3513 const char *ivar_layout;
3514 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003515 };
3516
3517 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003518*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003519void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Akira Hatanaka0c194462018-04-03 22:50:16 +00003520 IdentifierInfo *RuntimeName =
3521 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
3522 DefinedSymbols.insert(RuntimeName);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003523
Chris Lattner86d7d912008-11-24 03:54:41 +00003524 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003525 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003526 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003527 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003528 llvm::Constant *Protocols =
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003529 EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(),
3530 Interface->all_referenced_protocol_begin(),
3531 Interface->all_referenced_protocol_end());
John McCallef19dbb2012-10-17 04:53:23 +00003532 unsigned Flags = FragileABI_Class_Factory;
John McCall0d54a172012-10-17 04:53:31 +00003533 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCallef19dbb2012-10-17 04:53:23 +00003534 Flags |= FragileABI_Class_HasCXXStructors;
John McCall09ec1ec2015-10-21 22:06:03 +00003535
John McCall460ce582015-10-22 18:38:17 +00003536 bool hasMRCWeak = false;
3537
John McCall09ec1ec2015-10-21 22:06:03 +00003538 if (CGM.getLangOpts().ObjCAutoRefCount)
3539 Flags |= FragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00003540 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
3541 Flags |= FragileABI_Class_HasMRCWeakIvars;
John McCall09ec1ec2015-10-21 22:06:03 +00003542
John McCall3fd13f062015-10-21 18:06:47 +00003543 CharUnits Size =
3544 CGM.getContext().getASTObjCImplementationLayout(ID).getSize();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003545
3546 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00003547 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003548 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003549
John McCall176f8922016-11-30 02:39:18 +00003550 enum {
3551 InstanceMethods,
3552 ClassMethods,
3553 NumMethodLists
3554 };
3555 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3556 for (const auto *MD : ID->methods()) {
3557 Methods[unsigned(MD->isClassMethod())].push_back(MD);
3558 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003559
Aaron Ballmand85eff42014-03-14 15:02:45 +00003560 for (const auto *PID : ID->property_impls()) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003561 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3562 ObjCPropertyDecl *PD = PID->getPropertyDecl();
3563
3564 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003565 if (GetMethodDefinition(MD))
3566 Methods[InstanceMethods].push_back(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003567 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003568 if (GetMethodDefinition(MD))
3569 Methods[InstanceMethods].push_back(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003570 }
3571 }
3572
John McCall176f8922016-11-30 02:39:18 +00003573 ConstantInitBuilder builder(CGM);
3574 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3575 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003576 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003577 // Record a reference to the super class.
3578 LazySymbols.insert(Super->getIdentifier());
3579
John McCall176f8922016-11-30 02:39:18 +00003580 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3581 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003582 } else {
John McCall176f8922016-11-30 02:39:18 +00003583 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003584 }
John McCall176f8922016-11-30 02:39:18 +00003585 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003586 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003587 values.addInt(ObjCTypes.LongTy, 0);
3588 values.addInt(ObjCTypes.LongTy, Flags);
3589 values.addInt(ObjCTypes.LongTy, Size.getQuantity());
3590 values.add(EmitIvarList(ID, false));
3591 values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods,
3592 Methods[InstanceMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003593 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003594 values.addNullPointer(ObjCTypes.CachePtrTy);
3595 values.add(Protocols);
3596 values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size));
3597 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3598 /*isMetaclass*/ false));
3599
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003600 std::string Name("OBJC_CLASS_");
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003601 Name += ClassName;
3602 const char *Section = "__OBJC,__class,regular,no_dead_strip";
3603 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003604 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003605 if (GV) {
3606 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3607 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003608 values.finishAndSetAsInitializer(GV);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003609 GV->setSection(Section);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00003610 GV->setAlignment(CGM.getPointerAlign().getAsAlign());
Rafael Espindola060062a2014-03-06 22:15:10 +00003611 CGM.addCompilerUsedGlobal(GV);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003612 } else
John McCall176f8922016-11-30 02:39:18 +00003613 GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003614 DefinedClasses.push_back(GV);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00003615 ImplementedClasses.push_back(Interface);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003616 // method definition entries must be clear for next implementation.
3617 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003618}
3619
3620llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3621 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00003622 ArrayRef<const ObjCMethodDecl*> Methods) {
John McCallef19dbb2012-10-17 04:53:23 +00003623 unsigned Flags = FragileABI_Class_Meta;
Micah Villmowdd31ca12012-10-08 16:25:52 +00003624 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003625
John McCall457a04e2010-10-22 21:05:15 +00003626 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003627 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003628
John McCall176f8922016-11-30 02:39:18 +00003629 ConstantInitBuilder builder(CGM);
3630 auto values = builder.beginStruct(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003631 // The isa for the metaclass is the root of the hierarchy.
3632 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3633 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3634 Root = Super;
John McCall176f8922016-11-30 02:39:18 +00003635 values.addBitCast(GetClassName(Root->getObjCRuntimeNameAsString()),
3636 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003637 // The super class for the metaclass is emitted as the name of the
3638 // super class. The runtime fixes this up to point to the
3639 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003640 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
John McCall176f8922016-11-30 02:39:18 +00003641 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3642 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003643 } else {
John McCall176f8922016-11-30 02:39:18 +00003644 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003645 }
John McCall176f8922016-11-30 02:39:18 +00003646 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003647 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003648 values.addInt(ObjCTypes.LongTy, 0);
3649 values.addInt(ObjCTypes.LongTy, Flags);
3650 values.addInt(ObjCTypes.LongTy, Size);
3651 values.add(EmitIvarList(ID, true));
3652 values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods,
3653 Methods));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003654 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003655 values.addNullPointer(ObjCTypes.CachePtrTy);
3656 values.add(Protocols);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003657 // ivar_layout for metaclass is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003658 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Renad0e7912016-01-29 19:22:54 +00003659 // The class extension is used to store class properties for metaclasses.
John McCall176f8922016-11-30 02:39:18 +00003660 values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/,
3661 /*isMetaclass*/true));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003662
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003663 std::string Name("OBJC_METACLASS_");
Benjamin Kramer1bbcbd02012-07-31 11:45:39 +00003664 Name += ID->getName();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003665
3666 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003667 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003668 if (GV) {
3669 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3670 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003671 values.finishAndSetAsInitializer(GV);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003672 } else {
John McCall176f8922016-11-30 02:39:18 +00003673 GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
3674 /*constant*/ false,
3675 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003676 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003677 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00003678 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003679
3680 return GV;
3681}
3682
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003683llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003684 std::string Name = "OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003685
Mike Stump18bb9282009-05-16 07:57:57 +00003686 // FIXME: Should we look these up somewhere other than the module. Its a bit
3687 // silly since we only generate these while processing an implementation, so
3688 // exactly one pointer would work if know when we entered/exitted an
3689 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003690
3691 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00003692 // Previously, metaclass with internal linkage may have been defined.
3693 // pass 'true' as 2nd argument so it is returned.
Rafael Espindola21039aa2014-02-27 16:26:32 +00003694 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3695 if (!GV)
3696 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003697 llvm::GlobalValue::PrivateLinkage, nullptr,
3698 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003699
3700 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3701 "Forward metaclass reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003702 return GV;
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003703}
3704
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003705llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003706 std::string Name = "OBJC_CLASS_" + ID->getNameAsString();
Rafael Espindola21039aa2014-02-27 16:26:32 +00003707 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3708
3709 if (!GV)
3710 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003711 llvm::GlobalValue::PrivateLinkage, nullptr,
3712 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003713
3714 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3715 "Forward class metadata reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003716 return GV;
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003717}
3718
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003719/*
John McCall3fd13f062015-10-21 18:06:47 +00003720 Emit a "class extension", which in this specific context means extra
3721 data that doesn't fit in the normal fragile-ABI class structure, and
3722 has nothing to do with the language concept of a class extension.
3723
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003724 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003725 uint32_t size;
3726 const char *weak_ivar_layout;
3727 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003728 };
3729*/
3730llvm::Constant *
John McCall3fd13f062015-10-21 18:06:47 +00003731CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
Manman Renad0e7912016-01-29 19:22:54 +00003732 CharUnits InstanceSize, bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00003733 bool isMetaclass) {
3734 // Weak ivar layout.
3735 llvm::Constant *layout;
3736 if (isMetaclass) {
3737 layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
3738 } else {
3739 layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
3740 hasMRCWeakIvars);
3741 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003742
John McCall176f8922016-11-30 02:39:18 +00003743 // Properties.
3744 llvm::Constant *propertyList =
Akira Hatanaka187770d2019-05-09 17:43:52 +00003745 EmitPropertyList((isMetaclass ? Twine("_OBJC_$_CLASS_PROP_LIST_")
3746 : Twine("_OBJC_$_PROP_LIST_"))
John McCall176f8922016-11-30 02:39:18 +00003747 + ID->getName(),
3748 ID, ID->getClassInterface(), ObjCTypes, isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003749
3750 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00003751 if (layout->isNullValue() && propertyList->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003752 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003753 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003754
John McCall176f8922016-11-30 02:39:18 +00003755 uint64_t size =
3756 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3757
3758 ConstantInitBuilder builder(CGM);
3759 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3760 values.addInt(ObjCTypes.IntTy, size);
3761 values.add(layout);
3762 values.add(propertyList);
3763
3764 return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00003765 "__OBJC,__class_ext,regular,no_dead_strip",
3766 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003767}
3768
3769/*
3770 struct objc_ivar {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003771 char *ivar_name;
3772 char *ivar_type;
3773 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003774 };
3775
3776 struct objc_ivar_list {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003777 int ivar_count;
3778 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003779 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003780*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003781llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003782 bool ForClass) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003783 // When emitting the root class GCC emits ivar entries for the
3784 // actual class structure. It is not clear if we need to follow this
3785 // behavior; for now lets try and get away with not doing it. If so,
3786 // the cleanest solution would be to make up an ObjCInterfaceDecl
3787 // for the class.
3788 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00003789 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003790
Jordy Rosea91768e2011-07-22 02:08:32 +00003791 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003792
John McCall176f8922016-11-30 02:39:18 +00003793 ConstantInitBuilder builder(CGM);
3794 auto ivarList = builder.beginStruct();
3795 auto countSlot = ivarList.addPlaceholder();
3796 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3797
Fangrui Song6907ce22018-07-30 19:24:48 +00003798 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00003799 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00003800 // Ignore unnamed bit-fields.
3801 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003802 continue;
John McCall176f8922016-11-30 02:39:18 +00003803
3804 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3805 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3806 ivar.add(GetMethodVarType(IVD));
3807 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3808 ivar.finishAndAddTo(ivars);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003809 }
3810
3811 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00003812 auto count = ivars.size();
3813 if (count == 0) {
3814 ivars.abandon();
3815 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00003816 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003817 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003818
John McCall176f8922016-11-30 02:39:18 +00003819 ivars.finishAndAddTo(ivarList);
3820 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003821
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003822 llvm::GlobalVariable *GV;
3823 if (ForClass)
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003824 GV =
John McCall176f8922016-11-30 02:39:18 +00003825 CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003826 "__OBJC,__class_vars,regular,no_dead_strip",
3827 CGM.getPointerAlign(), true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003828 else
John McCall176f8922016-11-30 02:39:18 +00003829 GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003830 "__OBJC,__instance_vars,regular,no_dead_strip",
3831 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003832 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003833}
3834
John McCall176f8922016-11-30 02:39:18 +00003835/// Build a struct objc_method_description constant for the given method.
3836///
3837/// struct objc_method_description {
3838/// SEL method_name;
3839/// char *method_types;
3840/// };
3841void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
3842 const ObjCMethodDecl *MD) {
3843 auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy);
3844 description.addBitCast(GetMethodVarName(MD->getSelector()),
3845 ObjCTypes.SelectorPtrTy);
3846 description.add(GetMethodVarType(MD));
3847 description.finishAndAddTo(builder);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003848}
3849
John McCall176f8922016-11-30 02:39:18 +00003850/// Build a struct objc_method constant for the given method.
3851///
3852/// struct objc_method {
3853/// SEL method_name;
3854/// char *method_types;
3855/// void *method;
3856/// };
3857void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
3858 const ObjCMethodDecl *MD) {
3859 llvm::Function *fn = GetMethodDefinition(MD);
3860 assert(fn && "no definition registered for method");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003861
John McCall176f8922016-11-30 02:39:18 +00003862 auto method = builder.beginStruct(ObjCTypes.MethodTy);
3863 method.addBitCast(GetMethodVarName(MD->getSelector()),
3864 ObjCTypes.SelectorPtrTy);
3865 method.add(GetMethodVarType(MD));
3866 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
3867 method.finishAndAddTo(builder);
3868}
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003869
John McCall176f8922016-11-30 02:39:18 +00003870/// Build a struct objc_method_list or struct objc_method_description_list,
3871/// as appropriate.
3872///
3873/// struct objc_method_list {
3874/// struct objc_method_list *obsolete;
3875/// int count;
3876/// struct objc_method methods_list[count];
3877/// };
3878///
3879/// struct objc_method_description_list {
3880/// int count;
3881/// struct objc_method_description list[count];
3882/// };
Zachary Turner41a9ee92017-10-11 23:54:34 +00003883llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3884 ArrayRef<const ObjCMethodDecl *> methods) {
John McCall176f8922016-11-30 02:39:18 +00003885 StringRef prefix;
3886 StringRef section;
3887 bool forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003888 switch (MLT) {
3889 case MethodListType::CategoryInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003890 prefix = "OBJC_CATEGORY_INSTANCE_METHODS_";
3891 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3892 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003893 break;
3894 case MethodListType::CategoryClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003895 prefix = "OBJC_CATEGORY_CLASS_METHODS_";
3896 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3897 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003898 break;
3899 case MethodListType::InstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003900 prefix = "OBJC_INSTANCE_METHODS_";
3901 section = "__OBJC,__inst_meth,regular,no_dead_strip";
3902 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003903 break;
3904 case MethodListType::ClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003905 prefix = "OBJC_CLASS_METHODS_";
3906 section = "__OBJC,__cls_meth,regular,no_dead_strip";
3907 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003908 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003909 case MethodListType::ProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003910 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_";
3911 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3912 forProtocol = true;
3913 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003914 case MethodListType::ProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003915 prefix = "OBJC_PROTOCOL_CLASS_METHODS_";
3916 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3917 forProtocol = true;
3918 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003919 case MethodListType::OptionalProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003920 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3921 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3922 forProtocol = true;
3923 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003924 case MethodListType::OptionalProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003925 prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3926 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3927 forProtocol = true;
3928 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003929 }
3930
John McCall176f8922016-11-30 02:39:18 +00003931 // Return null for empty list.
3932 if (methods.empty())
3933 return llvm::Constant::getNullValue(forProtocol
3934 ? ObjCTypes.MethodDescriptionListPtrTy
3935 : ObjCTypes.MethodListPtrTy);
3936
3937 // For protocols, this is an objc_method_description_list, which has
3938 // a slightly different structure.
3939 if (forProtocol) {
3940 ConstantInitBuilder builder(CGM);
3941 auto values = builder.beginStruct();
3942 values.addInt(ObjCTypes.IntTy, methods.size());
3943 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3944 for (auto MD : methods) {
3945 emitMethodDescriptionConstant(methodArray, MD);
3946 }
3947 methodArray.finishAndAddTo(values);
3948
Zachary Turner41a9ee92017-10-11 23:54:34 +00003949 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
John McCall176f8922016-11-30 02:39:18 +00003950 CGM.getPointerAlign(), true);
3951 return llvm::ConstantExpr::getBitCast(GV,
3952 ObjCTypes.MethodDescriptionListPtrTy);
3953 }
3954
3955 // Otherwise, it's an objc_method_list.
3956 ConstantInitBuilder builder(CGM);
3957 auto values = builder.beginStruct();
3958 values.addNullPointer(ObjCTypes.Int8PtrTy);
3959 values.addInt(ObjCTypes.IntTy, methods.size());
3960 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3961 for (auto MD : methods) {
3962 emitMethodConstant(methodArray, MD);
3963 }
3964 methodArray.finishAndAddTo(values);
3965
Zachary Turner41a9ee92017-10-11 23:54:34 +00003966 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003967 CGM.getPointerAlign(), true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003968 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003969}
3970
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00003971llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003972 const ObjCContainerDecl *CD) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003973 SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00003974 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003975
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00003976 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00003977 llvm::FunctionType *MethodTy =
John McCalla729c622012-02-17 03:33:10 +00003978 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003979 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00003980 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003981 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00003982 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003983 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003984 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003985
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003986 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003987}
3988
Zachary Turner41a9ee92017-10-11 23:54:34 +00003989llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
3990 ConstantStructBuilder &Init,
3991 StringRef Section,
3992 CharUnits Align,
3993 bool AddToUsed) {
Akira Hatanaka187770d2019-05-09 17:43:52 +00003994 llvm::GlobalValue::LinkageTypes LT =
3995 getLinkageTypeForObjCMetadata(CGM, Section);
John McCall176f8922016-11-30 02:39:18 +00003996 llvm::GlobalVariable *GV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00003997 Init.finishAndCreateGlobal(Name, Align, /*constant*/ false, LT);
John McCall176f8922016-11-30 02:39:18 +00003998 if (!Section.empty())
3999 GV->setSection(Section);
4000 if (AddToUsed)
4001 CGM.addCompilerUsedGlobal(GV);
4002 return GV;
4003}
4004
Zachary Turner41a9ee92017-10-11 23:54:34 +00004005llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
Alp Toker541d5072014-06-07 23:30:53 +00004006 llvm::Constant *Init,
4007 StringRef Section,
John McCall7f416cc2015-09-08 08:05:57 +00004008 CharUnits Align,
Alp Toker541d5072014-06-07 23:30:53 +00004009 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004010 llvm::Type *Ty = Init->getType();
Akira Hatanaka187770d2019-05-09 17:43:52 +00004011 llvm::GlobalValue::LinkageTypes LT =
4012 getLinkageTypeForObjCMetadata(CGM, Section);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004013 llvm::GlobalVariable *GV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00004014 new llvm::GlobalVariable(CGM.getModule(), Ty, false, LT, Init, Name);
Alp Toker541d5072014-06-07 23:30:53 +00004015 if (!Section.empty())
Daniel Dunbar30c65362009-03-09 20:09:19 +00004016 GV->setSection(Section);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00004017 GV->setAlignment(Align.getAsAlign());
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00004018 if (AddToUsed)
Rafael Espindola060062a2014-03-06 22:15:10 +00004019 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00004020 return GV;
4021}
4022
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004023llvm::GlobalVariable *
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004024CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type,
4025 bool ForceNonFragileABI,
4026 bool NullTerminate) {
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004027 StringRef Label;
4028 switch (Type) {
4029 case ObjCLabelType::ClassName: Label = "OBJC_CLASS_NAME_"; break;
4030 case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break;
4031 case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break;
4032 case ObjCLabelType::PropertyName: Label = "OBJC_PROP_NAME_ATTR_"; break;
4033 }
4034
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004035 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
4036
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004037 StringRef Section;
4038 switch (Type) {
4039 case ObjCLabelType::ClassName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004040 Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals"
4041 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004042 break;
4043 case ObjCLabelType::MethodVarName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004044 Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
4045 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004046 break;
4047 case ObjCLabelType::MethodVarType:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004048 Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals"
4049 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004050 break;
4051 case ObjCLabelType::PropertyName:
4052 Section = "__TEXT,__cstring,cstring_literals";
4053 break;
4054 }
4055
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004056 llvm::Constant *Value =
4057 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004058 llvm::GlobalVariable *GV =
Saleem Abdulrasool0c54dc82016-09-18 16:12:04 +00004059 new llvm::GlobalVariable(CGM.getModule(), Value->getType(),
4060 /*isConstant=*/true,
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004061 llvm::GlobalValue::PrivateLinkage, Value, Label);
Saleem Abdulrasool3f307512016-09-18 16:12:14 +00004062 if (CGM.getTriple().isOSBinFormatMachO())
4063 GV->setSection(Section);
4064 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00004065 GV->setAlignment(CharUnits::One().getAsAlign());
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004066 CGM.addCompilerUsedGlobal(GV);
4067
4068 return GV;
4069}
4070
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004071llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004072 // Abuse this interface function as a place to finalize.
4073 FinishModule();
Craig Topper8a13c412014-05-21 05:09:00 +00004074 return nullptr;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00004075}
4076
James Y Knight9871db02019-02-05 16:42:33 +00004077llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00004078 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00004079}
4080
James Y Knight9871db02019-02-05 16:42:33 +00004081llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00004082 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00004083}
4084
James Y Knight9871db02019-02-05 16:42:33 +00004085llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
4086 bool copy) {
Ted Kremeneke65b0862012-03-06 20:05:56 +00004087 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
4088}
4089
James Y Knight9871db02019-02-05 16:42:33 +00004090llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
David Chisnall168b80f2010-12-26 22:13:16 +00004091 return ObjCTypes.getCopyStructFn();
4092}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004093
James Y Knight9871db02019-02-05 16:42:33 +00004094llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00004095 return ObjCTypes.getCopyStructFn();
4096}
4097
James Y Knight9871db02019-02-05 16:42:33 +00004098llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
David Chisnall0d75e062012-12-17 18:54:24 +00004099 return ObjCTypes.getCppAtomicObjectFunction();
4100}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004101
James Y Knight9871db02019-02-05 16:42:33 +00004102llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00004103 return ObjCTypes.getCppAtomicObjectFunction();
4104}
4105
James Y Knight9871db02019-02-05 16:42:33 +00004106llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00004107 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00004108}
4109
John McCallbd309292010-07-06 01:34:17 +00004110void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
4111 return EmitTryOrSynchronizedStmt(CGF, S);
4112}
4113
4114void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
4115 const ObjCAtSynchronizedStmt &S) {
4116 return EmitTryOrSynchronizedStmt(CGF, S);
4117}
4118
John McCall65bea082010-07-21 06:59:36 +00004119namespace {
David Blaikie7e70d682015-08-18 22:40:54 +00004120 struct PerformFragileFinally final : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00004121 const Stmt &S;
John McCall7f416cc2015-09-08 08:05:57 +00004122 Address SyncArgSlot;
4123 Address CallTryExitVar;
4124 Address ExceptionData;
John McCall65bea082010-07-21 06:59:36 +00004125 ObjCTypesHelper &ObjCTypes;
4126 PerformFragileFinally(const Stmt *S,
John McCall7f416cc2015-09-08 08:05:57 +00004127 Address SyncArgSlot,
4128 Address CallTryExitVar,
4129 Address ExceptionData,
John McCall65bea082010-07-21 06:59:36 +00004130 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00004131 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00004132 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4133
Craig Topper4f12f102014-03-12 06:41:41 +00004134 void Emit(CodeGenFunction &CGF, Flags flags) override {
John McCall65bea082010-07-21 06:59:36 +00004135 // Check whether we need to call objc_exception_try_exit.
4136 // In optimized code, this branch will always be folded.
4137 llvm::BasicBlock *FinallyCallExit =
4138 CGF.createBasicBlock("finally.call_exit");
4139 llvm::BasicBlock *FinallyNoCallExit =
4140 CGF.createBasicBlock("finally.no_call_exit");
4141 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
4142 FinallyCallExit, FinallyNoCallExit);
4143
4144 CGF.EmitBlock(FinallyCallExit);
John McCall882987f2013-02-28 19:01:20 +00004145 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004146 ExceptionData.getPointer());
John McCall65bea082010-07-21 06:59:36 +00004147
4148 CGF.EmitBlock(FinallyNoCallExit);
4149
4150 if (isa<ObjCAtTryStmt>(S)) {
4151 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00004152 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
John McCall638d4f52013-04-03 00:56:07 +00004153 // Don't try to do the @finally if this is an EH cleanup.
4154 if (flags.isForEHCleanup()) return;
4155
John McCallcebe0ca2010-08-11 00:16:14 +00004156 // Save the current cleanup destination in case there's
4157 // control flow inside the finally statement.
4158 llvm::Value *CurCleanupDest =
4159 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
4160
John McCall65bea082010-07-21 06:59:36 +00004161 CGF.EmitStmt(FinallyStmt->getFinallyBody());
4162
John McCallcebe0ca2010-08-11 00:16:14 +00004163 if (CGF.HaveInsertPoint()) {
4164 CGF.Builder.CreateStore(CurCleanupDest,
4165 CGF.getNormalCleanupDestSlot());
4166 } else {
4167 // Currently, the end of the cleanup must always exist.
4168 CGF.EnsureInsertPoint();
4169 }
4170 }
John McCall65bea082010-07-21 06:59:36 +00004171 } else {
4172 // Emit objc_sync_exit(expr); as finally's sole statement for
4173 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00004174 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall882987f2013-02-28 19:01:20 +00004175 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg);
John McCall65bea082010-07-21 06:59:36 +00004176 }
4177 }
4178 };
John McCall42227ed2010-07-31 23:20:56 +00004179
4180 class FragileHazards {
4181 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004182 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00004183 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
4184
4185 llvm::InlineAsm *ReadHazard;
4186 llvm::InlineAsm *WriteHazard;
4187
4188 llvm::FunctionType *GetAsmFnType();
4189
4190 void collectLocals();
4191 void emitReadHazard(CGBuilderTy &Builder);
4192
4193 public:
4194 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00004195
John McCall42227ed2010-07-31 23:20:56 +00004196 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00004197 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004198 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004199} // end anonymous namespace
John McCall42227ed2010-07-31 23:20:56 +00004200
4201/// Create the fragile-ABI read and write hazards based on the current
4202/// state of the function, which is presumed to be immediately prior
4203/// to a @try block. These hazards are used to maintain correct
4204/// semantics in the face of optimization and the fragile ABI's
4205/// cavalier use of setjmp/longjmp.
4206FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
4207 collectLocals();
4208
4209 if (Locals.empty()) return;
4210
4211 // Collect all the blocks in the function.
4212 for (llvm::Function::iterator
4213 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
4214 BlocksBeforeTry.insert(&*I);
4215
4216 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4217
4218 // Create a read hazard for the allocas. This inhibits dead-store
4219 // optimizations and forces the values to memory. This hazard is
4220 // inserted before any 'throwing' calls in the protected scope to
4221 // reflect the possibility that the variables might be read from the
4222 // catch block if the call throws.
4223 {
4224 std::string Constraint;
4225 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
4226 if (I) Constraint += ',';
4227 Constraint += "*m";
4228 }
4229
4230 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
4231 }
4232
4233 // Create a write hazard for the allocas. This inhibits folding
4234 // loads across the hazard. This hazard is inserted at the
4235 // beginning of the catch path to reflect the possibility that the
4236 // variables might have been written within the protected scope.
4237 {
4238 std::string Constraint;
4239 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
4240 if (I) Constraint += ',';
4241 Constraint += "=*m";
4242 }
4243
4244 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
4245 }
4246}
4247
4248/// Emit a write hazard at the current location.
4249void FragileHazards::emitWriteHazard() {
4250 if (Locals.empty()) return;
4251
John McCall882987f2013-02-28 19:01:20 +00004252 CGF.EmitNounwindRuntimeCall(WriteHazard, Locals);
John McCall42227ed2010-07-31 23:20:56 +00004253}
4254
John McCall42227ed2010-07-31 23:20:56 +00004255void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
4256 assert(!Locals.empty());
John McCall882987f2013-02-28 19:01:20 +00004257 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4258 call->setDoesNotThrow();
4259 call->setCallingConv(CGF.getRuntimeCC());
John McCall42227ed2010-07-31 23:20:56 +00004260}
4261
4262/// Emit read hazards in all the protected blocks, i.e. all the blocks
4263/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00004264void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00004265 if (Locals.empty()) return;
4266
John McCall7f416cc2015-09-08 08:05:57 +00004267 CGBuilderTy Builder(CGF, CGF.getLLVMContext());
John McCall42227ed2010-07-31 23:20:56 +00004268
4269 // Iterate through all blocks, skipping those prior to the try.
4270 for (llvm::Function::iterator
4271 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
4272 llvm::BasicBlock &BB = *FI;
4273 if (BlocksBeforeTry.count(&BB)) continue;
4274
4275 // Walk through all the calls in the block.
4276 for (llvm::BasicBlock::iterator
4277 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
4278 llvm::Instruction &I = *BI;
4279
4280 // Ignore instructions that aren't non-intrinsic calls.
4281 // These are the only calls that can possibly call longjmp.
James Y Knight3933add2019-01-30 02:54:28 +00004282 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
4283 continue;
John McCall42227ed2010-07-31 23:20:56 +00004284 if (isa<llvm::IntrinsicInst>(I))
4285 continue;
4286
4287 // Ignore call sites marked nounwind. This may be questionable,
4288 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
James Y Knight3933add2019-01-30 02:54:28 +00004289 if (cast<llvm::CallBase>(I).doesNotThrow())
4290 continue;
John McCall42227ed2010-07-31 23:20:56 +00004291
John McCall2dd7d442010-08-04 05:59:32 +00004292 // Insert a read hazard before the call. This will ensure that
4293 // any writes to the locals are performed before making the
4294 // call. If the call throws, then this is sufficient to
4295 // guarantee correctness as long as it doesn't also write to any
4296 // locals.
John McCall42227ed2010-07-31 23:20:56 +00004297 Builder.SetInsertPoint(&BB, BI);
4298 emitReadHazard(Builder);
4299 }
4300 }
4301}
4302
John McCall7f416cc2015-09-08 08:05:57 +00004303static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) {
4304 if (V.isValid()) S.insert(V.getPointer());
4305}
4306
John McCall42227ed2010-07-31 23:20:56 +00004307void FragileHazards::collectLocals() {
4308 // Compute a set of allocas to ignore.
4309 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
4310 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
4311 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00004312
4313 // Collect all the allocas currently in the function. This is
4314 // probably way too aggressive.
4315 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
4316 for (llvm::BasicBlock::iterator
4317 I = Entry.begin(), E = Entry.end(); I != E; ++I)
4318 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
4319 Locals.push_back(&*I);
4320}
4321
4322llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004323 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00004324 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
4325 tys[i] = Locals[i]->getType();
4326 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00004327}
4328
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004329/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004330
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004331 Objective-C setjmp-longjmp (sjlj) Exception Handling
4332 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004333
John McCallbd309292010-07-06 01:34:17 +00004334 A catch buffer is a setjmp buffer plus:
4335 - a pointer to the exception that was caught
4336 - a pointer to the previous exception data buffer
4337 - two pointers of reserved storage
4338 Therefore catch buffers form a stack, with a pointer to the top
4339 of the stack kept in thread-local storage.
4340
4341 objc_exception_try_enter pushes a catch buffer onto the EH stack.
4342 objc_exception_try_exit pops the given catch buffer, which is
4343 required to be the top of the EH stack.
4344 objc_exception_throw pops the top of the EH stack, writes the
4345 thrown exception into the appropriate field, and longjmps
4346 to the setjmp buffer. It crashes the process (with a printf
4347 and an abort()) if there are no catch buffers on the stack.
4348 objc_exception_extract just reads the exception pointer out of the
4349 catch buffer.
4350
4351 There's no reason an implementation couldn't use a light-weight
4352 setjmp here --- something like __builtin_setjmp, but API-compatible
4353 with the heavyweight setjmp. This will be more important if we ever
4354 want to implement correct ObjC/C++ exception interactions for the
4355 fragile ABI.
4356
4357 Note that for this use of setjmp/longjmp to be correct, we may need
4358 to mark some local variables volatile: if a non-volatile local
4359 variable is modified between the setjmp and the longjmp, it has
4360 indeterminate value. For the purposes of LLVM IR, it may be
4361 sufficient to make loads and stores within the @try (to variables
4362 declared outside the @try) volatile. This is necessary for
4363 optimized correctness, but is not currently being done; this is
4364 being tracked as rdar://problem/8160285
4365
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004366 The basic framework for a @try-catch-finally is as follows:
4367 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004368 objc_exception_data d;
4369 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00004370 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004371
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004372 objc_exception_try_enter(&d);
4373 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004374 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004375 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004376 // exception path
4377 id _caught = objc_exception_extract(&d);
4378
4379 // enter new try scope for handlers
4380 if (!setjmp(d.jmp_buf)) {
4381 ... match exception and execute catch blocks ...
4382
4383 // fell off end, rethrow.
4384 _rethrow = _caught;
4385 ... jump-through-finally to finally_rethrow ...
4386 } else {
4387 // exception in catch block
4388 _rethrow = objc_exception_extract(&d);
4389 _call_try_exit = false;
4390 ... jump-through-finally to finally_rethrow ...
4391 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004392 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004393 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004394
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004395 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00004396 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004397 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00004398
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004399 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004400 ... dispatch to finally destination ...
4401
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004402 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004403 objc_exception_throw(_rethrow);
4404
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004405 finally_end:
4406 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004407
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004408 This framework differs slightly from the one gcc uses, in that gcc
4409 uses _rethrow to determine if objc_exception_try_exit should be called
4410 and if the object should be rethrown. This breaks in the face of
4411 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004412
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004413 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004414
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004415 - If there are no catch blocks, then we avoid emitting the second
4416 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004417
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004418 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
4419 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004420
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004421 - FIXME: If there is no @finally block we can do a few more
4422 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004423
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004424 Rethrows and Jumps-Through-Finally
4425 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004426
John McCallbd309292010-07-06 01:34:17 +00004427 '@throw;' is supported by pushing the currently-caught exception
4428 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004429
John McCallbd309292010-07-06 01:34:17 +00004430 Branches through the @finally block are handled with an ordinary
4431 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
4432 exceptions are not compatible with C++ exceptions, and this is
4433 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004434
John McCallbd309292010-07-06 01:34:17 +00004435 @synchronized(expr) { stmt; } is emitted as if it were:
4436 id synch_value = expr;
4437 objc_sync_enter(synch_value);
4438 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004439*/
4440
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00004441void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
4442 const Stmt &S) {
4443 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00004444
4445 // A destination for the fall-through edges of the catch handlers to
4446 // jump to.
4447 CodeGenFunction::JumpDest FinallyEnd =
4448 CGF.getJumpDestInCurrentScope("finally.end");
4449
4450 // A destination for the rethrow edge of the catch handlers to jump
4451 // to.
4452 CodeGenFunction::JumpDest FinallyRethrow =
4453 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004454
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004455 // For @synchronized, call objc_sync_enter(sync.expr). The
4456 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00004457 // @synchronized. We can't avoid a temp here because we need the
4458 // value to be preserved. If the backend ever does liveness
4459 // correctly after setjmp, this will be unnecessary.
John McCall7f416cc2015-09-08 08:05:57 +00004460 Address SyncArgSlot = Address::invalid();
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004461 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00004462 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004463 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4464 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004465 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);
John McCall2dd7d442010-08-04 05:59:32 +00004466
John McCall7f416cc2015-09-08 08:05:57 +00004467 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(),
4468 CGF.getPointerAlign(), "sync.arg");
John McCall2dd7d442010-08-04 05:59:32 +00004469 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004470 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004471
John McCall2dd7d442010-08-04 05:59:32 +00004472 // Allocate memory for the setjmp buffer. This needs to be kept
4473 // live throughout the try and catch blocks.
John McCall7f416cc2015-09-08 08:05:57 +00004474 Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
4475 CGF.getPointerAlign(),
4476 "exceptiondata.ptr");
John McCall2dd7d442010-08-04 05:59:32 +00004477
John McCall42227ed2010-07-31 23:20:56 +00004478 // Create the fragile hazards. Note that this will not capture any
4479 // of the allocas required for exception processing, but will
4480 // capture the current basic block (which extends all the way to the
4481 // setjmp call) as "before the @try".
4482 FragileHazards Hazards(CGF);
4483
John McCallbd309292010-07-06 01:34:17 +00004484 // Create a flag indicating whether the cleanup needs to call
4485 // objc_exception_try_exit. This is true except when
4486 // - no catches match and we're branching through the cleanup
4487 // just to rethrow the exception, or
4488 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00004489 // The setjmp-safety rule here is that we should always store to this
4490 // variable in a place that dominates the branch through the cleanup
4491 // without passing through any setjmps.
John McCall7f416cc2015-09-08 08:05:57 +00004492 Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
4493 CharUnits::One(),
4494 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004495
John McCall9916e3f2010-10-04 23:42:51 +00004496 // A slot containing the exception to rethrow. Only needed when we
4497 // have both a @catch and a @finally.
John McCall7f416cc2015-09-08 08:05:57 +00004498 Address PropagatingExnVar = Address::invalid();
John McCall9916e3f2010-10-04 23:42:51 +00004499
John McCallbd309292010-07-06 01:34:17 +00004500 // Push a normal cleanup to leave the try scope.
John McCall638d4f52013-04-03 00:56:07 +00004501 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00004502 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00004503 CallTryExitVar,
4504 ExceptionData,
4505 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00004506
4507 // Enter a try block:
4508 // - Call objc_exception_try_enter to push ExceptionData on top of
4509 // the EH stack.
Nico Weber6307cf02015-02-26 20:43:00 +00004510 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004511 ExceptionData.getPointer());
John McCallbd309292010-07-06 01:34:17 +00004512
4513 // - Call setjmp on the exception data buffer.
4514 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
4515 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
David Blaikie6b2a8302015-04-03 17:47:16 +00004516 llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
John McCall7f416cc2015-09-08 08:05:57 +00004517 ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes,
4518 "setjmp_buffer");
Nico Weber6307cf02015-02-26 20:43:00 +00004519 llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
4520 ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004521 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00004522
4523 // If setjmp returned 0, enter the protected block; otherwise,
4524 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00004525 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
4526 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00004527 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00004528 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4529 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004530
John McCallbd309292010-07-06 01:34:17 +00004531 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004532 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00004533 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004534 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00004535 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00004536
4537 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004538
John McCallbd309292010-07-06 01:34:17 +00004539 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00004540 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004541
John McCall42227ed2010-07-31 23:20:56 +00004542 // Don't optimize loads of the in-scope locals across this point.
4543 Hazards.emitWriteHazard();
4544
John McCallbd309292010-07-06 01:34:17 +00004545 // For a @synchronized (or a @try with no catches), just branch
4546 // through the cleanup to the rethrow block.
4547 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4548 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00004549 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004550 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00004551
4552 // Otherwise, we have to match against the caught exceptions.
4553 } else {
John McCall2dd7d442010-08-04 05:59:32 +00004554 // Retrieve the exception object. We may emit multiple blocks but
4555 // nothing can cross this so the value is already in SSA form.
4556 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004557 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004558 ExceptionData.getPointer(), "caught");
John McCall2dd7d442010-08-04 05:59:32 +00004559
John McCallbd309292010-07-06 01:34:17 +00004560 // Push the exception to rethrow onto the EH value stack for the
4561 // benefit of any @throws in the handlers.
4562 CGF.ObjCEHValueStack.push_back(Caught);
4563
Douglas Gregor96c79492010-04-23 22:50:49 +00004564 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004565
Craig Topper8a13c412014-05-21 05:09:00 +00004566 bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr);
John McCallbd309292010-07-06 01:34:17 +00004567
Craig Topper8a13c412014-05-21 05:09:00 +00004568 llvm::BasicBlock *CatchBlock = nullptr;
4569 llvm::BasicBlock *CatchHandler = nullptr;
John McCall2dd7d442010-08-04 05:59:32 +00004570 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00004571 // Save the currently-propagating exception before
4572 // objc_exception_try_enter clears the exception slot.
4573 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
John McCall7f416cc2015-09-08 08:05:57 +00004574 CGF.getPointerAlign(),
John McCall9916e3f2010-10-04 23:42:51 +00004575 "propagating_exception");
4576 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
4577
John McCall2dd7d442010-08-04 05:59:32 +00004578 // Enter a new exception try block (in case a @catch block
4579 // throws an exception).
John McCall882987f2013-02-28 19:01:20 +00004580 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004581 ExceptionData.getPointer());
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004582
John McCall2dd7d442010-08-04 05:59:32 +00004583 llvm::CallInst *SetJmpResult =
John McCall882987f2013-02-28 19:01:20 +00004584 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(),
4585 SetJmpBuffer, "setjmp.result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004586 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004587
John McCall2dd7d442010-08-04 05:59:32 +00004588 llvm::Value *Threw =
4589 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4590
4591 CatchBlock = CGF.createBasicBlock("catch");
4592 CatchHandler = CGF.createBasicBlock("catch_for_catch");
4593 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4594
4595 CGF.EmitBlock(CatchBlock);
4596 }
4597
4598 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004599
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004600 // Handle catch list. As a special case we check if everything is
4601 // matched and avoid generating code for falling off the end if
4602 // so.
4603 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00004604 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
4605 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004606
Douglas Gregor46a572b2010-04-26 16:46:50 +00004607 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Craig Topper8a13c412014-05-21 05:09:00 +00004608 const ObjCObjectPointerType *OPT = nullptr;
Daniel Dunbar523208f2008-09-27 07:36:24 +00004609
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004610 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004611 if (!CatchParam) {
4612 AllMatched = true;
4613 } else {
John McCall9dd450b2009-09-21 23:43:11 +00004614 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004615
John McCallbd309292010-07-06 01:34:17 +00004616 // catch(id e) always matches under this ABI, since only
4617 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00004618 // FIXME: For the time being we also match id<X>; this should
4619 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00004620 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004621 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004622 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004623
John McCallbd309292010-07-06 01:34:17 +00004624 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004625 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00004626 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4627
Anders Carlsson9396a892008-09-11 09:15:33 +00004628 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00004629 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004630 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00004631
4632 // These types work out because ConvertType(id) == i8*.
John McCall17f02752015-10-30 00:56:02 +00004633 EmitInitOfCatchParam(CGF, Caught, CatchParam);
Anders Carlsson9396a892008-09-11 09:15:33 +00004634 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004635
Anders Carlsson9396a892008-09-11 09:15:33 +00004636 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004637
4638 // The scope of the catch variable ends right here.
4639 CatchVarCleanups.ForceCleanup();
4640
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004641 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004642 break;
4643 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004644
Steve Naroff7cae42b2009-07-10 23:34:53 +00004645 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00004646 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00004647
4648 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00004649 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
4650 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004651
4652 // Check if the @catch block matches the exception object.
John McCall882987f2013-02-28 19:01:20 +00004653 llvm::Value *Class = EmitClassRef(CGF, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004654
John McCall882987f2013-02-28 19:01:20 +00004655 llvm::Value *matchArgs[] = { Class, Caught };
John McCallbd309292010-07-06 01:34:17 +00004656 llvm::CallInst *Match =
John McCall882987f2013-02-28 19:01:20 +00004657 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(),
4658 matchArgs, "match");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004659
John McCallbd309292010-07-06 01:34:17 +00004660 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
4661 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004662
4663 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00004664 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004665
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004666 // Emit the @catch block.
4667 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00004668
4669 // Collect any cleanups for the catch variable. The scope lasts until
4670 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00004671 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00004672
John McCall1c9c3fd2010-10-15 04:57:14 +00004673 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004674 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004675
John McCallbd309292010-07-06 01:34:17 +00004676 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004677 llvm::Value *Tmp =
4678 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004679 CGF.ConvertType(CatchParam->getType()));
John McCall17f02752015-10-30 00:56:02 +00004680 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004681
Anders Carlsson9396a892008-09-11 09:15:33 +00004682 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004683
4684 // We're done with the catch variable.
4685 CatchVarCleanups.ForceCleanup();
4686
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004687 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004688
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004689 CGF.EmitBlock(NextCatchBlock);
4690 }
4691
John McCallbd309292010-07-06 01:34:17 +00004692 CGF.ObjCEHValueStack.pop_back();
4693
John McCall2dd7d442010-08-04 05:59:32 +00004694 // If nothing wanted anything to do with the caught exception,
4695 // kill the extract call.
4696 if (Caught->use_empty())
4697 Caught->eraseFromParent();
4698
4699 if (!AllMatched)
4700 CGF.EmitBranchThroughCleanup(FinallyRethrow);
4701
4702 if (HasFinally) {
4703 // Emit the exception handler for the @catch blocks.
4704 CGF.EmitBlock(CatchHandler);
4705
4706 // In theory we might now need a write hazard, but actually it's
4707 // unnecessary because there's no local-accessing code between
4708 // the try's write hazard and here.
4709 //Hazards.emitWriteHazard();
4710
John McCall9916e3f2010-10-04 23:42:51 +00004711 // Extract the new exception and save it to the
4712 // propagating-exception slot.
John McCall7f416cc2015-09-08 08:05:57 +00004713 assert(PropagatingExnVar.isValid());
John McCall9916e3f2010-10-04 23:42:51 +00004714 llvm::CallInst *NewCaught =
John McCall882987f2013-02-28 19:01:20 +00004715 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004716 ExceptionData.getPointer(), "caught");
John McCall9916e3f2010-10-04 23:42:51 +00004717 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4718
John McCall2dd7d442010-08-04 05:59:32 +00004719 // Don't pop the catch handler; the throw already did.
4720 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004721 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004722 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004723 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004724
John McCall42227ed2010-07-31 23:20:56 +00004725 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00004726 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004727
John McCallbd309292010-07-06 01:34:17 +00004728 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00004729 CGF.Builder.restoreIP(TryFallthroughIP);
4730 if (CGF.HaveInsertPoint())
4731 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00004732 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00004733 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004734
John McCallbd309292010-07-06 01:34:17 +00004735 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00004736 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00004737 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00004738 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00004739 // If we have a propagating-exception variable, check it.
4740 llvm::Value *PropagatingExn;
John McCall7f416cc2015-09-08 08:05:57 +00004741 if (PropagatingExnVar.isValid()) {
John McCall9916e3f2010-10-04 23:42:51 +00004742 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00004743
John McCall9916e3f2010-10-04 23:42:51 +00004744 // Otherwise, just look in the buffer for the exception to throw.
4745 } else {
4746 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004747 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004748 ExceptionData.getPointer());
John McCall9916e3f2010-10-04 23:42:51 +00004749 PropagatingExn = Caught;
4750 }
4751
John McCall882987f2013-02-28 19:01:20 +00004752 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(),
4753 PropagatingExn);
John McCallbd309292010-07-06 01:34:17 +00004754 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00004755 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004756
John McCall42227ed2010-07-31 23:20:56 +00004757 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004758}
4759
4760void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004761 const ObjCAtThrowStmt &S,
4762 bool ClearInsertionPoint) {
Anders Carlssone005aa12008-09-09 16:16:55 +00004763 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004764
Anders Carlssone005aa12008-09-09 16:16:55 +00004765 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00004766 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004767 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004768 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00004769 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004770 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004771 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00004772 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00004773 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004774
John McCall882987f2013-02-28 19:01:20 +00004775 CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
John McCallbd309292010-07-06 01:34:17 +00004776 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004777 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004778
4779 // Clear the insertion point to indicate we are in unreachable code.
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004780 if (ClearInsertionPoint)
4781 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004782}
4783
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004784/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004785/// object: objc_read_weak (id *src)
4786///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004787llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004788 Address AddrWeakObj) {
4789 llvm::Type* DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004790 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4791 ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004792 llvm::Value *read_weak =
4793 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004794 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00004795 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004796 return read_weak;
4797}
4798
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004799/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4800/// objc_assign_weak (id src, id *dst)
4801///
4802void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004803 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004804 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004805 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004806 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004807 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004808 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4809 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004810 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4811 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004812 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4813 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004814 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00004815 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4816 args, "weakassign");
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004817}
4818
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004819/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4820/// objc_assign_global (id src, id *dst)
4821///
4822void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004823 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00004824 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004825 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004826 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004827 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004828 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004829 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4830 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004831 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4832 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004833 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4834 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004835 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00004836 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00004837 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4838 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00004839 else
John McCall882987f2013-02-28 19:01:20 +00004840 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4841 args, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004842}
4843
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004844/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004845/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004846///
4847void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004848 llvm::Value *src, Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004849 llvm::Value *ivarOffset) {
4850 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00004851 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004852 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004853 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004854 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004855 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4856 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004857 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4858 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004859 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4860 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004861 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00004862 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004863}
4864
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004865/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
4866/// objc_assign_strongCast (id src, id *dst)
4867///
4868void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004869 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004870 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004871 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004872 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004873 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004874 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4875 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004876 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4877 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004878 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4879 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004880 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00004881 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004882 args, "strongassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004883}
4884
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004885void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004886 Address DestPtr,
4887 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00004888 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004889 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
4890 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004891 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size };
John McCall882987f2013-02-28 19:01:20 +00004892 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004893}
4894
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004895/// EmitObjCValueForIvar - Code Gen for ivar reference.
4896///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004897LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4898 QualType ObjectTy,
4899 llvm::Value *BaseValue,
4900 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004901 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00004902 const ObjCInterfaceDecl *ID =
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00004903 ObjectTy->castAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00004904 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4905 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004906}
4907
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004908llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00004909 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004910 const ObjCIvarDecl *Ivar) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004911 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4912 return llvm::ConstantInt::get(
4913 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
4914 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004915}
4916
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004917/* *** Private Interface *** */
4918
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00004919std::string CGObjCCommonMac::GetSectionName(StringRef Section,
4920 StringRef MachOAttributes) {
4921 switch (CGM.getTriple().getObjectFormat()) {
Hubert Tong53a83b72019-07-04 21:40:28 +00004922 case llvm::Triple::UnknownObjectFormat:
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00004923 llvm_unreachable("unexpected object file format");
4924 case llvm::Triple::MachO: {
4925 if (MachOAttributes.empty())
4926 return ("__DATA," + Section).str();
4927 return ("__DATA," + Section + "," + MachOAttributes).str();
4928 }
4929 case llvm::Triple::ELF:
4930 assert(Section.substr(0, 2) == "__" &&
4931 "expected the name to begin with __");
4932 return Section.substr(2).str();
4933 case llvm::Triple::COFF:
4934 assert(Section.substr(0, 2) == "__" &&
4935 "expected the name to begin with __");
4936 return ("." + Section.substr(2) + "$B").str();
Hubert Tong53a83b72019-07-04 21:40:28 +00004937 case llvm::Triple::Wasm:
4938 case llvm::Triple::XCOFF:
4939 llvm::report_fatal_error(
4940 "Objective-C support is unimplemented for object file format.");
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00004941 }
Mikael Holmenc72cb1f2019-07-05 06:12:24 +00004942
4943 llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType enum");
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00004944}
4945
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004946/// EmitImageInfo - Emit the image info marker used to encode some module
4947/// level information.
4948///
4949/// See: <rdr://4810609&4810587&4810587>
4950/// struct IMAGE_INFO {
4951/// unsigned version;
4952/// unsigned flags;
4953/// };
4954enum ImageInfoFlags {
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004955 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004956 eImageInfo_GarbageCollected = (1 << 1),
4957 eImageInfo_GCOnly = (1 << 2),
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004958 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
Daniel Dunbar75e909f2009-04-20 07:11:47 +00004959
Daniel Dunbar5e639272010-04-25 20:39:01 +00004960 // A flag indicating that the module has no instances of a @synthesize of a
4961 // superclass variable. <rdar://problem/6803242>
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00004962 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
Manman Ren96df0b32016-01-29 23:45:01 +00004963 eImageInfo_ImageIsSimulated = (1 << 5),
4964 eImageInfo_ClassProperties = (1 << 6)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004965};
4966
Daniel Dunbar5e639272010-04-25 20:39:01 +00004967void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004968 unsigned version = 0; // Version is unused?
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00004969 std::string Section =
4970 (ObjCABI == 1)
4971 ? "__OBJC,__image_info,regular"
4972 : GetSectionName("__objc_imageinfo", "regular,no_dead_strip");
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004973
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004974 // Generate module-level named metadata to convey this information to the
4975 // linker and code-gen.
4976 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004977
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004978 // Add the ObjC ABI version to the module flags.
4979 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
4980 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
4981 version);
4982 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00004983 llvm::MDString::get(VMContext, Section));
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004984
David Blaikiebbafb8a2012-03-11 07:00:24 +00004985 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004986 // Non-GC overrides those files which specify GC.
4987 Mod.addModuleFlag(llvm::Module::Override,
4988 "Objective-C Garbage Collection", (uint32_t)0);
4989 } else {
4990 // Add the ObjC garbage collection value.
4991 Mod.addModuleFlag(llvm::Module::Error,
4992 "Objective-C Garbage Collection",
4993 eImageInfo_GarbageCollected);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004994
David Blaikiebbafb8a2012-03-11 07:00:24 +00004995 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004996 // Add the ObjC GC Only value.
4997 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
4998 eImageInfo_GCOnly);
4999
5000 // Require that GC be specified and set to eImageInfo_GarbageCollected.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +00005001 llvm::Metadata *Ops[2] = {
5002 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
5003 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
5004 llvm::Type::getInt32Ty(VMContext), eImageInfo_GarbageCollected))};
Bill Wendlingb6f795e2012-02-16 01:13:30 +00005005 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
5006 llvm::MDNode::get(VMContext, Ops));
5007 }
5008 }
Bill Wendling1e60a2c2012-04-24 11:04:57 +00005009
5010 // Indicate whether we're compiling this to run on a simulator.
Alex Lorenz6cdef0e2017-12-07 19:04:10 +00005011 if (CGM.getTarget().getTriple().isSimulatorEnvironment())
Bill Wendling1e60a2c2012-04-24 11:04:57 +00005012 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
5013 eImageInfo_ImageIsSimulated);
Manman Ren96df0b32016-01-29 23:45:01 +00005014
5015 // Indicate whether we are generating class properties.
5016 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Class Properties",
5017 eImageInfo_ClassProperties);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005018}
5019
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005020// struct objc_module {
5021// unsigned long version;
5022// unsigned long size;
5023// const char *name;
5024// Symtab symtab;
5025// };
5026
5027// FIXME: Get from somewhere
5028static const int ModuleVersion = 7;
5029
5030void CGObjCMac::EmitModuleInfo() {
Micah Villmowdd31ca12012-10-08 16:25:52 +00005031 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005032
John McCall176f8922016-11-30 02:39:18 +00005033 ConstantInitBuilder builder(CGM);
5034 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
5035 values.addInt(ObjCTypes.LongTy, ModuleVersion);
5036 values.addInt(ObjCTypes.LongTy, Size);
5037 // This used to be the filename, now it is unused. <rdr://4327263>
5038 values.add(GetClassName(StringRef("")));
5039 values.add(EmitModuleSymbols());
5040 CreateMetadataVar("OBJC_MODULES", values,
John McCall7f416cc2015-09-08 08:05:57 +00005041 "__OBJC,__module_info,regular,no_dead_strip",
5042 CGM.getPointerAlign(), true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005043}
5044
5045llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005046 unsigned NumClasses = DefinedClasses.size();
5047 unsigned NumCategories = DefinedCategories.size();
5048
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005049 // Return null if no symbols were defined.
5050 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00005051 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005052
John McCall176f8922016-11-30 02:39:18 +00005053 ConstantInitBuilder builder(CGM);
5054 auto values = builder.beginStruct();
5055 values.addInt(ObjCTypes.LongTy, 0);
5056 values.addNullPointer(ObjCTypes.SelectorPtrTy);
5057 values.addInt(ObjCTypes.ShortTy, NumClasses);
5058 values.addInt(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005059
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005060 // The runtime expects exactly the list of defined classes followed
5061 // by the list of defined categories, in a single array.
John McCall176f8922016-11-30 02:39:18 +00005062 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005063 for (unsigned i=0; i<NumClasses; i++) {
5064 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5065 assert(ID);
5066 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5067 // We are implementing a weak imported interface. Give it external linkage
5068 if (ID->isWeakImported() && !IMP->isWeakImported())
5069 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
John McCall176f8922016-11-30 02:39:18 +00005070
5071 array.addBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005072 }
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005073 for (unsigned i=0; i<NumCategories; i++)
John McCall176f8922016-11-30 02:39:18 +00005074 array.addBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005075
John McCall176f8922016-11-30 02:39:18 +00005076 array.finishAndAddTo(values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005077
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005078 llvm::GlobalVariable *GV = CreateMetadataVar(
John McCall176f8922016-11-30 02:39:18 +00005079 "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip",
John McCall7f416cc2015-09-08 08:05:57 +00005080 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00005081 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005082}
5083
John McCall882987f2013-02-28 19:01:20 +00005084llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
5085 IdentifierInfo *II) {
John McCall31168b02011-06-15 23:02:42 +00005086 LazySymbols.insert(II);
Fangrui Song6907ce22018-07-30 19:24:48 +00005087
John McCall31168b02011-06-15 23:02:42 +00005088 llvm::GlobalVariable *&Entry = ClassReferences[II];
Fangrui Song6907ce22018-07-30 19:24:48 +00005089
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005090 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005091 llvm::Constant *Casted =
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00005092 llvm::ConstantExpr::getBitCast(GetClassName(II->getName()),
John McCall31168b02011-06-15 23:02:42 +00005093 ObjCTypes.ClassPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005094 Entry = CreateMetadataVar(
5095 "OBJC_CLASS_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00005096 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
5097 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005098 }
Fangrui Song6907ce22018-07-30 19:24:48 +00005099
John McCall7f416cc2015-09-08 08:05:57 +00005100 return CGF.Builder.CreateAlignedLoad(Entry, CGF.getPointerAlign());
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005101}
5102
John McCall882987f2013-02-28 19:01:20 +00005103llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00005104 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00005105 // If the class has the objc_runtime_visible attribute, we need to
5106 // use the Objective-C runtime to get the class.
5107 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
5108 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
5109
Akira Hatanaka0c194462018-04-03 22:50:16 +00005110 IdentifierInfo *RuntimeName =
5111 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
5112 return EmitClassRefFromId(CGF, RuntimeName);
John McCall31168b02011-06-15 23:02:42 +00005113}
5114
John McCall882987f2013-02-28 19:01:20 +00005115llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00005116 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
John McCall882987f2013-02-28 19:01:20 +00005117 return EmitClassRefFromId(CGF, II);
John McCall31168b02011-06-15 23:02:42 +00005118}
5119
John McCall7f416cc2015-09-08 08:05:57 +00005120llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5121 return CGF.Builder.CreateLoad(EmitSelectorAddr(CGF, Sel));
5122}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005123
John McCall7f416cc2015-09-08 08:05:57 +00005124Address CGObjCMac::EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel) {
5125 CharUnits Align = CGF.getPointerAlign();
5126
5127 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005128 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005129 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00005130 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005131 ObjCTypes.SelectorPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005132 Entry = CreateMetadataVar(
5133 "OBJC_SELECTOR_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00005134 "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true);
Michael Gottesman5c205962013-02-05 23:08:45 +00005135 Entry->setExternallyInitialized(true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005136 }
5137
John McCall7f416cc2015-09-08 08:05:57 +00005138 return Address(Entry, Align);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005139}
5140
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00005141llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
5142 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
5143 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005144 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00005145 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005146}
5147
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005148llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
5149 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
5150 I = MethodDefinitions.find(MD);
5151 if (I != MethodDefinitions.end())
5152 return I->second;
5153
Craig Topper8a13c412014-05-21 05:09:00 +00005154 return nullptr;
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005155}
5156
Fariborz Jahanian01dff422009-03-05 19:17:31 +00005157/// GetIvarLayoutName - Returns a unique constant for the given
5158/// ivar layout bitmap.
5159llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005160 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00005161 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00005162}
5163
John McCall3fd13f062015-10-21 18:06:47 +00005164void IvarLayoutBuilder::visitRecord(const RecordType *RT,
5165 CharUnits offset) {
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005166 const RecordDecl *RD = RT->getDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005167
John McCall3fd13f062015-10-21 18:06:47 +00005168 // If this is a union, remember that we had one, because it might mess
5169 // up the ordering of layout entries.
5170 if (RD->isUnion())
5171 IsDisordered = true;
5172
5173 const ASTRecordLayout *recLayout = nullptr;
5174 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5175 [&](const FieldDecl *field) -> CharUnits {
5176 if (!recLayout)
5177 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5178 auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
5179 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5180 });
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005181}
5182
John McCall3fd13f062015-10-21 18:06:47 +00005183template <class Iterator, class GetOffsetFn>
Fangrui Song6907ce22018-07-30 19:24:48 +00005184void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
John McCall3fd13f062015-10-21 18:06:47 +00005185 CharUnits aggregateOffset,
5186 const GetOffsetFn &getOffset) {
5187 for (; begin != end; ++begin) {
5188 auto field = *begin;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005189
John McCall3fd13f062015-10-21 18:06:47 +00005190 // Skip over bitfields.
5191 if (field->isBitField()) {
5192 continue;
5193 }
5194
5195 // Compute the offset of the field within the aggregate.
5196 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5197
5198 visitField(field, fieldOffset);
5199 }
5200}
5201
5202/// Collect layout information for the given fields into IvarsInfo.
5203void IvarLayoutBuilder::visitField(const FieldDecl *field,
5204 CharUnits fieldOffset) {
5205 QualType fieldType = field->getType();
5206
5207 // Drill down into arrays.
5208 uint64_t numElts = 1;
Volodymyr Sapsai636ed472017-10-27 00:56:23 +00005209 if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
5210 numElts = 0;
5211 fieldType = arrayType->getElementType();
5212 }
5213 // Unlike incomplete arrays, constant arrays can be nested.
John McCall3fd13f062015-10-21 18:06:47 +00005214 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5215 numElts *= arrayType->getSize().getZExtValue();
5216 fieldType = arrayType->getElementType();
5217 }
5218
5219 assert(!fieldType->isArrayType() && "ivar of non-constant array type?");
5220
5221 // If we ended up with a zero-sized array, we've done what we can do within
5222 // the limits of this layout encoding.
5223 if (numElts == 0) return;
5224
5225 // Recurse if the base element type is a record type.
5226 if (auto recType = fieldType->getAs<RecordType>()) {
5227 size_t oldEnd = IvarsInfo.size();
5228
5229 visitRecord(recType, fieldOffset);
5230
5231 // If we have an array, replicate the first entry's layout information.
5232 auto numEltEntries = IvarsInfo.size() - oldEnd;
5233 if (numElts != 1 && numEltEntries != 0) {
5234 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5235 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5236 // Copy the last numEltEntries onto the end of the array, adjusting
5237 // each for the element size.
5238 for (size_t i = 0; i != numEltEntries; ++i) {
5239 auto firstEntry = IvarsInfo[oldEnd + i];
5240 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5241 firstEntry.SizeInWords));
5242 }
5243 }
5244 }
5245
Fariborz Jahanian524bb202009-03-10 16:22:08 +00005246 return;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00005247 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005248
John McCall3fd13f062015-10-21 18:06:47 +00005249 // Classify the element type.
5250 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005251
John McCall3fd13f062015-10-21 18:06:47 +00005252 // If it matches what we're looking for, add an entry.
5253 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
5254 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5255 assert(CGM.getContext().getTypeSizeInChars(fieldType)
5256 == CGM.getPointerSize());
5257 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5258 }
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00005259}
5260
John McCall3fd13f062015-10-21 18:06:47 +00005261/// buildBitmap - This routine does the horsework of taking the offsets of
5262/// strong/weak references and creating a bitmap. The bitmap is also
5263/// returned in the given buffer, suitable for being passed to \c dump().
5264llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5265 llvm::SmallVectorImpl<unsigned char> &buffer) {
5266 // The bitmap is a series of skip/scan instructions, aligned to word
5267 // boundaries. The skip is performed first.
5268 const unsigned char MaxNibble = 0xF;
5269 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5270 const unsigned char ScanMask = 0x0F, ScanShift = 0;
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005271
John McCall3fd13f062015-10-21 18:06:47 +00005272 assert(!IvarsInfo.empty() && "generating bitmap for no data");
5273
5274 // Sort the ivar info on byte position in case we encounterred a
5275 // union nested in the ivar list.
5276 if (IsDisordered) {
5277 // This isn't a stable sort, but our algorithm should handle it fine.
5278 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5279 } else {
Craig Toppera3467052016-01-03 19:43:20 +00005280 assert(std::is_sorted(IvarsInfo.begin(), IvarsInfo.end()));
John McCall3fd13f062015-10-21 18:06:47 +00005281 }
5282 assert(IvarsInfo.back().Offset < InstanceEnd);
5283
5284 assert(buffer.empty());
5285
5286 // Skip the next N words.
5287 auto skip = [&](unsigned numWords) {
5288 assert(numWords > 0);
5289
5290 // Try to merge into the previous byte. Since scans happen second, we
5291 // can't do this if it includes a scan.
5292 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5293 unsigned lastSkip = buffer.back() >> SkipShift;
5294 if (lastSkip < MaxNibble) {
5295 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5296 numWords -= claimed;
5297 lastSkip += claimed;
5298 buffer.back() = (lastSkip << SkipShift);
5299 }
5300 }
5301
5302 while (numWords >= MaxNibble) {
5303 buffer.push_back(MaxNibble << SkipShift);
5304 numWords -= MaxNibble;
5305 }
5306 if (numWords) {
5307 buffer.push_back(numWords << SkipShift);
5308 }
5309 };
5310
5311 // Scan the next N words.
5312 auto scan = [&](unsigned numWords) {
5313 assert(numWords > 0);
5314
5315 // Try to merge into the previous byte. Since scans happen second, we can
5316 // do this even if it includes a skip.
5317 if (!buffer.empty()) {
5318 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5319 if (lastScan < MaxNibble) {
5320 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5321 numWords -= claimed;
5322 lastScan += claimed;
5323 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5324 }
5325 }
5326
5327 while (numWords >= MaxNibble) {
5328 buffer.push_back(MaxNibble << ScanShift);
5329 numWords -= MaxNibble;
5330 }
5331 if (numWords) {
5332 buffer.push_back(numWords << ScanShift);
5333 }
5334 };
5335
5336 // One past the end of the last scan.
5337 unsigned endOfLastScanInWords = 0;
5338 const CharUnits WordSize = CGM.getPointerSize();
5339
5340 // Consider all the scan requests.
5341 for (auto &request : IvarsInfo) {
5342 CharUnits beginOfScan = request.Offset - InstanceBegin;
5343
5344 // Ignore scan requests that don't start at an even multiple of the
5345 // word size. We can't encode them.
5346 if ((beginOfScan % WordSize) != 0) continue;
5347
5348 // Ignore scan requests that start before the instance start.
5349 // This assumes that scans never span that boundary. The boundary
5350 // isn't the true start of the ivars, because in the fragile-ARC case
5351 // it's rounded up to word alignment, but the test above should leave
5352 // us ignoring that possibility.
5353 if (beginOfScan.isNegative()) {
5354 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5355 continue;
5356 }
5357
5358 unsigned beginOfScanInWords = beginOfScan / WordSize;
5359 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5360
5361 // If the scan starts some number of words after the last one ended,
5362 // skip forward.
5363 if (beginOfScanInWords > endOfLastScanInWords) {
5364 skip(beginOfScanInWords - endOfLastScanInWords);
5365
5366 // Otherwise, start scanning where the last left off.
5367 } else {
5368 beginOfScanInWords = endOfLastScanInWords;
5369
5370 // If that leaves us with nothing to scan, ignore this request.
5371 if (beginOfScanInWords >= endOfScanInWords) continue;
5372 }
5373
5374 // Scan to the end of the request.
5375 assert(beginOfScanInWords < endOfScanInWords);
5376 scan(endOfScanInWords - beginOfScanInWords);
5377 endOfLastScanInWords = endOfScanInWords;
5378 }
5379
John McCallf5ea0722015-10-29 23:36:14 +00005380 if (buffer.empty())
5381 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5382
John McCall3fd13f062015-10-21 18:06:47 +00005383 // For GC layouts, emit a skip to the end of the allocation so that we
5384 // have precise information about the entire thing. This isn't useful
5385 // or necessary for the ARC-style layout strings.
5386 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5387 unsigned lastOffsetInWords =
5388 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5389 if (lastOffsetInWords > endOfLastScanInWords) {
5390 skip(lastOffsetInWords - endOfLastScanInWords);
5391 }
5392 }
5393
5394 // Null terminate the string.
5395 buffer.push_back(0);
5396
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005397 auto *Entry = CGObjC.CreateCStringLiteral(
5398 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
John McCall3fd13f062015-10-21 18:06:47 +00005399 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005400}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005401
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005402/// BuildIvarLayout - Builds ivar layout bitmap for the class
5403/// implementation for the __strong or __weak case.
5404/// The layout map displays which words in ivar list must be skipped
5405/// and which must be scanned by GC (see below). String is built of bytes.
5406/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
5407/// of words to skip and right nibble is count of words to scan. So, each
5408/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
5409/// represented by a 0x00 byte which also ends the string.
5410/// 1. when ForStrongLayout is true, following ivars are scanned:
5411/// - id, Class
5412/// - object *
5413/// - __strong anything
5414///
5415/// 2. When ForStrongLayout is false, following ivars are scanned:
5416/// - __weak anything
5417///
John McCall3fd13f062015-10-21 18:06:47 +00005418llvm::Constant *
5419CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5420 CharUnits beginOffset, CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +00005421 bool ForStrongLayout, bool HasMRCWeakIvars) {
5422 // If this is MRC, and we're either building a strong layout or there
5423 // are no weak ivars, bail out early.
Chris Lattnerece04092012-02-07 00:39:47 +00005424 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikiebbafb8a2012-03-11 07:00:24 +00005425 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
John McCall460ce582015-10-22 18:38:17 +00005426 !CGM.getLangOpts().ObjCAutoRefCount &&
5427 (ForStrongLayout || !HasMRCWeakIvars))
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005428 return llvm::Constant::getNullValue(PtrTy);
5429
Jordy Rosea91768e2011-07-22 02:08:32 +00005430 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
John McCall3fd13f062015-10-21 18:06:47 +00005431 SmallVector<const ObjCIvarDecl*, 32> ivars;
5432
5433 // GC layout strings include the complete object layout, possibly
5434 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5435 // up.
5436 //
5437 // ARC layout strings only include the class's ivars. In non-fragile
John McCallf5ea0722015-10-29 23:36:14 +00005438 // runtimes, that means starting at InstanceStart, rounded up to word
5439 // alignment. In fragile runtimes, there's no InstanceStart, so it means
John McCalld80218f2015-11-19 02:27:55 +00005440 // starting at the offset of the first ivar, rounded up to word alignment.
John McCall460ce582015-10-22 18:38:17 +00005441 //
5442 // MRC weak layout strings follow the ARC style.
John McCall3fd13f062015-10-21 18:06:47 +00005443 CharUnits baseOffset;
John McCall460ce582015-10-22 18:38:17 +00005444 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Fangrui Song6907ce22018-07-30 19:24:48 +00005445 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005446 IVD; IVD = IVD->getNextIvar())
John McCall3fd13f062015-10-21 18:06:47 +00005447 ivars.push_back(IVD);
5448
5449 if (isNonFragileABI()) {
5450 baseOffset = beginOffset; // InstanceStart
John McCalld80218f2015-11-19 02:27:55 +00005451 } else if (!ivars.empty()) {
5452 baseOffset =
5453 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
John McCall3fd13f062015-10-21 18:06:47 +00005454 } else {
5455 baseOffset = CharUnits::Zero();
5456 }
John McCallf5ea0722015-10-29 23:36:14 +00005457
Rui Ueyama83aa9792016-01-14 21:00:27 +00005458 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005459 }
5460 else {
John McCall3fd13f062015-10-21 18:06:47 +00005461 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005462
John McCall3fd13f062015-10-21 18:06:47 +00005463 baseOffset = CharUnits::Zero();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005464 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005465
John McCall3fd13f062015-10-21 18:06:47 +00005466 if (ivars.empty())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005467 return llvm::Constant::getNullValue(PtrTy);
5468
John McCall3fd13f062015-10-21 18:06:47 +00005469 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005470
John McCall3fd13f062015-10-21 18:06:47 +00005471 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5472 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5473 return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
5474 });
5475
5476 if (!builder.hasBitmapData())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005477 return llvm::Constant::getNullValue(PtrTy);
John McCall3fd13f062015-10-21 18:06:47 +00005478
5479 llvm::SmallVector<unsigned char, 4> buffer;
5480 llvm::Constant *C = builder.buildBitmap(*this, buffer);
Fangrui Song6907ce22018-07-30 19:24:48 +00005481
John McCallf5ea0722015-10-29 23:36:14 +00005482 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005483 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005484 ForStrongLayout ? "strong" : "weak",
Ben Langmuire013bdc2014-07-11 00:43:47 +00005485 OMD->getClassInterface()->getName().str().c_str());
John McCall3fd13f062015-10-21 18:06:47 +00005486 builder.dump(buffer);
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005487 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005488 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00005489}
5490
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005491llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005492 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
Chris Lattner3def9ae2012-02-06 22:16:34 +00005493 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005494 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005495 Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
Owen Anderson170229f2009-07-14 23:10:40 +00005496 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005497}
5498
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005499// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005500llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005501 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5502}
5503
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005504llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005505 std::string TypeStr;
5506 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5507
5508 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005509 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005510 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005511 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005512}
5513
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005514llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5515 bool Extended) {
John McCall843dfcc2016-11-29 21:57:00 +00005516 std::string TypeStr =
5517 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005518
5519 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbar3241fae2009-04-14 23:14:47 +00005520 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005521 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005522 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005523}
5524
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005525// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005526llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005527 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005528 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005529 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
Owen Anderson170229f2009-07-14 23:10:40 +00005530 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005531}
5532
5533// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00005534// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005535llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005536CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5537 const Decl *Container) {
John McCall843dfcc2016-11-29 21:57:00 +00005538 std::string TypeStr =
5539 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005540 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5541}
5542
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005543void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005544 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005545 SmallVectorImpl<char> &Name) {
Daniel Dunbard2386812009-10-19 01:21:19 +00005546 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00005547 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00005548 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
5549 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005550 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00005551 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer2f569922012-02-07 11:57:45 +00005552 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00005553 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00005554}
5555
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005556void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005557 EmitModuleInfo();
5558
Daniel Dunbarc475d422008-10-29 22:36:39 +00005559 // Emit the dummy bodies for any protocols which were referenced but
5560 // never defined.
John McCall176f8922016-11-30 02:39:18 +00005561 for (auto &entry : Protocols) {
5562 llvm::GlobalVariable *global = entry.second;
5563 if (global->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00005564 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005565
John McCall176f8922016-11-30 02:39:18 +00005566 ConstantInitBuilder builder(CGM);
5567 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5568 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5569 values.add(GetClassName(entry.first->getName()));
5570 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5571 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5572 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5573 values.finishAndSetAsInitializer(global);
5574 CGM.addCompilerUsedGlobal(global);
Daniel Dunbarc475d422008-10-29 22:36:39 +00005575 }
5576
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005577 // Add assembler directives to add lazy undefined symbol references
5578 // for classes which are referenced but not defined. This is
5579 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00005580 //
5581 // FIXME: It would be nice if we had an LLVM construct for this.
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005582 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5583 CGM.getTriple().isOSBinFormatMachO()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005584 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00005585 Asm += CGM.getModule().getModuleInlineAsm();
5586 if (!Asm.empty() && Asm.back() != '\n')
5587 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005588
Daniel Dunbard027a922009-09-07 00:20:42 +00005589 llvm::raw_svector_ostream OS(Asm);
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005590 for (const auto *Sym : DefinedSymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005591 OS << "\t.objc_class_name_" << Sym->getName() << "=0\n"
5592 << "\t.globl .objc_class_name_" << Sym->getName() << "\n";
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005593 for (const auto *Sym : LazySymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005594 OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n";
5595 for (const auto &Category : DefinedCategoryNames)
5596 OS << "\t.objc_category_name_" << Category << "=0\n"
5597 << "\t.globl .objc_category_name_" << Category << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00005598
Daniel Dunbard027a922009-09-07 00:20:42 +00005599 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005600 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005601}
5602
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005603CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00005604 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5605 ObjCEmptyVtableVar(nullptr) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005606 ObjCABI = 2;
5607}
5608
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005609/* *** */
5610
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005611ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Craig Topper8a13c412014-05-21 05:09:00 +00005612 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00005613{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005614 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5615 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005616
John McCall176f8922016-11-30 02:39:18 +00005617 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5618 IntTy = CGM.IntTy;
5619 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
Chris Lattnerece04092012-02-07 00:39:47 +00005620 Int8PtrTy = CGM.Int8PtrTy;
5621 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005622
Tim Northover238b5082014-03-29 13:42:40 +00005623 // arm64 targets use "int" ivar offset variables. All others,
5624 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
Tim Northover40956e62014-07-23 12:32:58 +00005625 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
Tim Northover238b5082014-03-29 13:42:40 +00005626 IvarOffsetVarTy = IntTy;
5627 else
5628 IvarOffsetVarTy = LongTy;
5629
John McCall176f8922016-11-30 02:39:18 +00005630 ObjectPtrTy =
5631 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5632 PtrObjectPtrTy =
5633 llvm::PointerType::getUnqual(ObjectPtrTy);
5634 SelectorPtrTy =
5635 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005636
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005637 // I'm not sure I like this. The implicit coordination is a bit
5638 // gross. We should solve this in a reasonable fashion because this
5639 // is a pretty common task (match some runtime data structure with
5640 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005641
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005642 // FIXME: This is leaked.
5643 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005644
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005645 // struct _objc_super {
5646 // id self;
5647 // Class cls;
5648 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00005649 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005650 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005651 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005652 &Ctx.Idents.get("_objc_super"));
Craig Topper8a13c412014-05-21 05:09:00 +00005653 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5654 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5655 false, ICIS_NoInit));
5656 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5657 nullptr, Ctx.getObjCClassType(), nullptr,
5658 nullptr, false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005659 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005660
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005661 SuperCTy = Ctx.getTagDeclType(RD);
5662 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005663
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005664 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005665 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5666
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005667 // struct _prop_t {
5668 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005669 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005670 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005671 PropertyTy = llvm::StructType::create("struct._prop_t", Int8PtrTy, Int8PtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005672
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005673 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005674 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005675 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005676 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005677 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005678 PropertyListTy = llvm::StructType::create(
5679 "struct._prop_list_t", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0));
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005680 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005681 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005682
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005683 // struct _objc_method {
5684 // SEL _cmd;
5685 // char *method_type;
5686 // char *_imp;
5687 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005688 MethodTy = llvm::StructType::create("struct._objc_method", SelectorPtrTy,
5689 Int8PtrTy, Int8PtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005690
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005691 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00005692 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005693 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005694}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005695
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005696ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005697 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005698 // struct _objc_method_description {
5699 // SEL name;
5700 // char *types;
5701 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005702 MethodDescriptionTy = llvm::StructType::create(
5703 "struct._objc_method_description", SelectorPtrTy, Int8PtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005704
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005705 // struct _objc_method_description_list {
5706 // int count;
5707 // struct _objc_method_description[1];
5708 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005709 MethodDescriptionListTy =
5710 llvm::StructType::create("struct._objc_method_description_list", IntTy,
5711 llvm::ArrayType::get(MethodDescriptionTy, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005712
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005713 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005714 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005715 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005716
Daniel Dunbarb036db82008-08-13 03:21:16 +00005717 // Protocol description structures
5718
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005719 // struct _objc_protocol_extension {
5720 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5721 // struct _objc_method_description_list *optional_instance_methods;
5722 // struct _objc_method_description_list *optional_class_methods;
5723 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005724 // const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00005725 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005726 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005727 ProtocolExtensionTy = llvm::StructType::create(
5728 "struct._objc_protocol_extension", IntTy, MethodDescriptionListPtrTy,
5729 MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy,
5730 PropertyListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005731
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005732 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005733 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005734
Daniel Dunbarc475d422008-10-29 22:36:39 +00005735 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00005736
Chris Lattnera5f58b02011-07-09 17:41:47 +00005737 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005738 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00005739
Chris Lattnera5f58b02011-07-09 17:41:47 +00005740 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005741 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Serge Guelton1d993272017-05-09 19:31:30 +00005742 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), LongTy,
5743 llvm::ArrayType::get(ProtocolTy, 0));
Daniel Dunbarb036db82008-08-13 03:21:16 +00005744
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005745 // struct _objc_protocol {
5746 // struct _objc_protocol_extension *isa;
5747 // char *protocol_name;
5748 // struct _objc_protocol **_objc_protocol_list;
5749 // struct _objc_method_description_list *instance_methods;
5750 // struct _objc_method_description_list *class_methods;
5751 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005752 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5753 llvm::PointerType::getUnqual(ProtocolListTy),
Serge Guelton1d993272017-05-09 19:31:30 +00005754 MethodDescriptionListPtrTy, MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005755
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005756 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005757 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005758
Owen Anderson9793f0e2009-07-29 22:16:19 +00005759 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005760
5761 // Class description structures
5762
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005763 // struct _objc_ivar {
5764 // char *ivar_name;
5765 // char *ivar_type;
5766 // int ivar_offset;
5767 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005768 IvarTy = llvm::StructType::create("struct._objc_ivar", Int8PtrTy, Int8PtrTy,
5769 IntTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005770
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005771 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005772 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005773 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005774 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005775
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005776 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005777 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005778 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005779 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005780
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005781 // struct _objc_class_extension *
Serge Guelton1d993272017-05-09 19:31:30 +00005782 ClassExtensionTy = llvm::StructType::create(
5783 "struct._objc_class_extension", IntTy, Int8PtrTy, PropertyListPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005784 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005785
Chris Lattner5ec04a52011-08-12 17:43:31 +00005786 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005787
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005788 // struct _objc_class {
5789 // Class isa;
5790 // Class super_class;
5791 // char *name;
5792 // long version;
5793 // long info;
5794 // long instance_size;
5795 // struct _objc_ivar_list *ivars;
5796 // struct _objc_method_list *methods;
5797 // struct _objc_cache *cache;
5798 // struct _objc_protocol_list *protocols;
5799 // char *ivar_layout;
5800 // struct _objc_class_ext *ext;
5801 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005802 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
Serge Guelton1d993272017-05-09 19:31:30 +00005803 llvm::PointerType::getUnqual(ClassTy), Int8PtrTy, LongTy,
5804 LongTy, LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy,
5805 ProtocolListPtrTy, Int8PtrTy, ClassExtensionPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005806
Owen Anderson9793f0e2009-07-29 22:16:19 +00005807 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005808
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005809 // struct _objc_category {
5810 // char *category_name;
5811 // char *class_name;
5812 // struct _objc_method_list *instance_method;
5813 // struct _objc_method_list *class_method;
Manman Renb3736772016-01-25 22:37:47 +00005814 // struct _objc_protocol_list *protocols;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005815 // uint32_t size; // sizeof(struct _objc_category)
5816 // struct _objc_property_list *instance_properties;// category's @property
Manman Ren96df0b32016-01-29 23:45:01 +00005817 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005818 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005819 CategoryTy = llvm::StructType::create(
5820 "struct._objc_category", Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5821 MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy,
5822 PropertyListPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005823
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005824 // Global metadata structures
5825
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005826 // struct _objc_symtab {
5827 // long sel_ref_cnt;
5828 // SEL *refs;
5829 // short cls_def_cnt;
5830 // short cat_def_cnt;
5831 // char *defs[cls_def_cnt + cat_def_cnt];
5832 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005833 SymtabTy = llvm::StructType::create("struct._objc_symtab", LongTy,
5834 SelectorPtrTy, ShortTy, ShortTy,
5835 llvm::ArrayType::get(Int8PtrTy, 0));
Owen Anderson9793f0e2009-07-29 22:16:19 +00005836 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005837
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00005838 // struct _objc_module {
5839 // long version;
5840 // long size; // sizeof(struct _objc_module)
5841 // char *name;
5842 // struct _objc_symtab* symtab;
5843 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005844 ModuleTy = llvm::StructType::create("struct._objc_module", LongTy, LongTy,
5845 Int8PtrTy, SymtabPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005846
Mike Stump18bb9282009-05-16 07:57:57 +00005847 // FIXME: This is the size of the setjmp buffer and should be target
5848 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00005849 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005850
Anders Carlsson9ff22482008-09-09 10:10:21 +00005851 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00005852 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005853
Serge Guelton1d993272017-05-09 19:31:30 +00005854 ExceptionDataTy = llvm::StructType::create(
5855 "struct._objc_exception_data",
5856 llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005857}
5858
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005859ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005860 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005861 // struct _method_list_t {
5862 // uint32_t entsize; // sizeof(struct _objc_method)
5863 // uint32_t method_count;
5864 // struct _objc_method method_list[method_count];
5865 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005866 MethodListnfABITy =
Serge Guelton1d993272017-05-09 19:31:30 +00005867 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
5868 llvm::ArrayType::get(MethodTy, 0));
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005869 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005870 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005871
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005872 // struct _protocol_t {
5873 // id isa; // NULL
5874 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005875 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005876 // const struct method_list_t * const instance_methods;
5877 // const struct method_list_t * const class_methods;
5878 // const struct method_list_t *optionalInstanceMethods;
5879 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005880 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005881 // const uint32_t size; // sizeof(struct _protocol_t)
5882 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005883 // const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00005884 // const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00005885 // const struct _prop_list_t * class_properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005886 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005887
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005888 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005889 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005890 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005891
Serge Guelton1d993272017-05-09 19:31:30 +00005892 ProtocolnfABITy = llvm::StructType::create(
5893 "struct._protocol_t", ObjectPtrTy, Int8PtrTy,
5894 llvm::PointerType::getUnqual(ProtocolListnfABITy), MethodListnfABIPtrTy,
5895 MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5896 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy,
5897 PropertyListPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005898
5899 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005900 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005901
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005902 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005903 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005904 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005905 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005906 ProtocolListnfABITy->setBody(LongTy,
Serge Guelton1d993272017-05-09 19:31:30 +00005907 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005908
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005909 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005910 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005911
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005912 // struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00005913 // unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005914 // char *name;
5915 // char *type;
5916 // uint32_t alignment;
5917 // uint32_t size;
5918 // }
Tim Northover238b5082014-03-29 13:42:40 +00005919 IvarnfABITy = llvm::StructType::create(
5920 "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy),
Serge Guelton1d993272017-05-09 19:31:30 +00005921 Int8PtrTy, Int8PtrTy, IntTy, IntTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005922
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005923 // struct _ivar_list_t {
5924 // uint32 entsize; // sizeof(struct _ivar_t)
5925 // uint32 count;
5926 // struct _iver_t list[count];
5927 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005928 IvarListnfABITy =
Serge Guelton1d993272017-05-09 19:31:30 +00005929 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
5930 llvm::ArrayType::get(IvarnfABITy, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005931
Owen Anderson9793f0e2009-07-29 22:16:19 +00005932 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005933
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005934 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005935 // uint32_t const flags;
5936 // uint32_t const instanceStart;
5937 // uint32_t const instanceSize;
5938 // uint32_t const reserved; // only when building for 64bit targets
5939 // const uint8_t * const ivarLayout;
5940 // const char *const name;
5941 // const struct _method_list_t * const baseMethods;
5942 // const struct _objc_protocol_list *const baseProtocols;
5943 // const struct _ivar_list_t *const ivars;
5944 // const uint8_t * const weakIvarLayout;
5945 // const struct _prop_list_t * const properties;
5946 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005947
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005948 // FIXME. Add 'reserved' field in 64bit abi mode!
Serge Guelton1d993272017-05-09 19:31:30 +00005949 ClassRonfABITy = llvm::StructType::create(
5950 "struct._class_ro_t", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy,
5951 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy,
5952 Int8PtrTy, PropertyListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005953
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005954 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00005955 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00005956 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
5957 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005958
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005959 // struct _class_t {
5960 // struct _class_t *isa;
5961 // struct _class_t * const superclass;
5962 // void *cache;
5963 // IMP *vtable;
5964 // struct class_ro_t *ro;
5965 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005966
Chris Lattner5ec04a52011-08-12 17:43:31 +00005967 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005968 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
Serge Guelton1d993272017-05-09 19:31:30 +00005969 llvm::PointerType::getUnqual(ClassnfABITy), CachePtrTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00005970 llvm::PointerType::getUnqual(ImpnfABITy),
Serge Guelton1d993272017-05-09 19:31:30 +00005971 llvm::PointerType::getUnqual(ClassRonfABITy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005972
Fariborz Jahanian71394042009-01-23 23:53:38 +00005973 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005974 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005975
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005976 // struct _category_t {
5977 // const char * const name;
5978 // struct _class_t *const cls;
5979 // const struct _method_list_t * const instance_methods;
5980 // const struct _method_list_t * const class_methods;
5981 // const struct _protocol_list_t * const protocols;
5982 // const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00005983 // const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00005984 // const uint32_t size;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00005985 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005986 CategorynfABITy = llvm::StructType::create(
5987 "struct._category_t", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy,
5988 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy,
5989 PropertyListPtrTy, IntTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005990
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005991 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005992 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5993 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005994
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005995 // MessageRefTy - LLVM for:
5996 // struct _message_ref_t {
5997 // IMP messenger;
5998 // SEL name;
5999 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006000
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006001 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00006002 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00006003 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00006004 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006005 &Ctx.Idents.get("_message_ref_t"));
Craig Topper8a13c412014-05-21 05:09:00 +00006006 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6007 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
Richard Smith2b013182012-06-10 03:12:00 +00006008 ICIS_NoInit));
Craig Topper8a13c412014-05-21 05:09:00 +00006009 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6010 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
6011 false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00006012 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006013
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006014 MessageRefCTy = Ctx.getTagDeclType(RD);
6015 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
6016 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006017
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006018 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00006019 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006020
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006021 // SuperMessageRefTy - LLVM for:
6022 // struct _super_message_ref_t {
6023 // SUPER_IMP messenger;
6024 // SEL name;
6025 // };
Serge Guelton1d993272017-05-09 19:31:30 +00006026 SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t",
6027 ImpnfABITy, SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006028
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006029 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006030 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fangrui Song6907ce22018-07-30 19:24:48 +00006031
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006032
6033 // struct objc_typeinfo {
6034 // const void** vtable; // objc_ehtype_vtable + 2
6035 // const char* name; // c++ typeinfo string
6036 // Class cls;
6037 // };
Serge Guelton1d993272017-05-09 19:31:30 +00006038 EHTypeTy = llvm::StructType::create("struct._objc_typeinfo",
6039 llvm::PointerType::getUnqual(Int8PtrTy),
6040 Int8PtrTy, ClassnfABIPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00006041 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00006042}
6043
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006044llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00006045 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006046
Craig Topper8a13c412014-05-21 05:09:00 +00006047 return nullptr;
Fariborz Jahanian71394042009-01-23 23:53:38 +00006048}
6049
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00006050void CGObjCNonFragileABIMac::AddModuleClassList(
6051 ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
6052 StringRef SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00006053 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006054
Daniel Dunbar19573e72009-05-15 21:48:48 +00006055 if (!NumClasses)
6056 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006057
Chris Lattner3def9ae2012-02-06 22:16:34 +00006058 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00006059 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00006060 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00006061 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00006062 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00006063 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00006064 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00006065 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006066
Akira Hatanaka187770d2019-05-09 17:43:52 +00006067 // Section name is obtained by calling GetSectionName, which returns
6068 // sections in the __DATA segment on MachO.
6069 assert((!CGM.getTriple().isOSBinFormatMachO() ||
6070 SectionName.startswith("__DATA")) &&
6071 "SectionName expected to start with __DATA on MachO");
6072 llvm::GlobalValue::LinkageTypes LT =
6073 getLinkageTypeForObjCMetadata(CGM, SectionName);
Daniel Dunbar19573e72009-05-15 21:48:48 +00006074 llvm::GlobalVariable *GV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00006075 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, LT, Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006076 SymbolName);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006077 GV->setAlignment(
6078 llvm::Align(CGM.getDataLayout().getABITypeAlignment(Init->getType())));
Daniel Dunbar19573e72009-05-15 21:48:48 +00006079 GV->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00006080 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00006081}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006082
Fariborz Jahanian71394042009-01-23 23:53:38 +00006083void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
6084 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006085
Daniel Dunbar19573e72009-05-15 21:48:48 +00006086 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006087 // L_OBJC_LABEL_CLASS_$.
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00006088
6089 for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) {
6090 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
6091 assert(ID);
6092 if (ObjCImplementationDecl *IMP = ID->getImplementation())
6093 // We are implementing a weak imported interface. Give it external linkage
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00006094 if (ID->isWeakImported() && !IMP->isWeakImported()) {
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00006095 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00006096 DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
6097 }
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00006098 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006099
6100 AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006101 GetSectionName("__objc_classlist",
6102 "regular,no_dead_strip"));
Rafael Espindola554256c2014-02-26 22:25:45 +00006103
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006104 AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006105 GetSectionName("__objc_nlclslist",
6106 "regular,no_dead_strip"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006107
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006108 // Build list of all implemented category addresses in array
6109 // L_OBJC_LABEL_CATEGORY_$.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006110 AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006111 GetSectionName("__objc_catlist",
6112 "regular,no_dead_strip"));
John McCall2c91c3b2019-05-30 04:09:01 +00006113 AddModuleClassList(DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$",
6114 GetSectionName("__objc_catlist2",
6115 "regular,no_dead_strip"));
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006116 AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006117 GetSectionName("__objc_nlcatlist",
6118 "regular,no_dead_strip"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006119
Daniel Dunbar5e639272010-04-25 20:39:01 +00006120 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00006121}
6122
John McCall9e8bb002011-05-14 03:10:52 +00006123/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
6124/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006125/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006126/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00006127bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
6128 // At various points we've experimented with using vtable-based
6129 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006130 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006131 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00006132 return false;
John McCall9e8bb002011-05-14 03:10:52 +00006133 case CodeGenOptions::NonLegacy:
6134 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006135 case CodeGenOptions::Mixed:
6136 break;
6137 }
6138
6139 // If so, see whether this selector is in the white-list of things which must
6140 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00006141 if (VTableDispatchMethods.empty()) {
6142 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
6143 VTableDispatchMethods.insert(GetNullarySelector("class"));
6144 VTableDispatchMethods.insert(GetNullarySelector("self"));
6145 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
6146 VTableDispatchMethods.insert(GetNullarySelector("length"));
6147 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006148
John McCall9e8bb002011-05-14 03:10:52 +00006149 // These are vtable-based if GC is disabled.
6150 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006151 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00006152 VTableDispatchMethods.insert(GetNullarySelector("retain"));
6153 VTableDispatchMethods.insert(GetNullarySelector("release"));
6154 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
6155 }
6156
6157 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
6158 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
6159 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
6160 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
6161 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
6162 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
6163 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
6164
6165 // These are vtable-based if GC is enabled.
6166 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006167 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00006168 VTableDispatchMethods.insert(GetNullarySelector("hash"));
6169 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
Fangrui Song6907ce22018-07-30 19:24:48 +00006170
John McCall9e8bb002011-05-14 03:10:52 +00006171 // "countByEnumeratingWithState:objects:count"
6172 IdentifierInfo *KeyIdents[] = {
6173 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
6174 &CGM.getContext().Idents.get("objects"),
6175 &CGM.getContext().Idents.get("count")
6176 };
6177 VTableDispatchMethods.insert(
6178 CGM.getContext().Selectors.getSelector(3, KeyIdents));
6179 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006180 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006181
John McCall9e8bb002011-05-14 03:10:52 +00006182 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006183}
6184
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006185/// BuildClassRoTInitializer - generate meta-data for:
6186/// struct _class_ro_t {
6187/// uint32_t const flags;
6188/// uint32_t const instanceStart;
6189/// uint32_t const instanceSize;
6190/// uint32_t const reserved; // only when building for 64bit targets
6191/// const uint8_t * const ivarLayout;
6192/// const char *const name;
6193/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006194/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006195/// const struct _ivar_list_t *const ivars;
6196/// const uint8_t * const weakIvarLayout;
6197/// const struct _prop_list_t * const properties;
6198/// }
6199///
6200llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006201 unsigned flags,
6202 unsigned InstanceStart,
6203 unsigned InstanceSize,
6204 const ObjCImplementationDecl *ID) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006205 std::string ClassName = ID->getObjCRuntimeNameAsString();
John McCall31168b02011-06-15 23:02:42 +00006206
John McCall3fd13f062015-10-21 18:06:47 +00006207 CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
6208 CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
6209
John McCall460ce582015-10-22 18:38:17 +00006210 bool hasMRCWeak = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00006211 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCallef19dbb2012-10-17 04:53:23 +00006212 flags |= NonFragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00006213 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
6214 flags |= NonFragileABI_Class_HasMRCWeakIvars;
John McCall31168b02011-06-15 23:02:42 +00006215
John McCall176f8922016-11-30 02:39:18 +00006216 ConstantInitBuilder builder(CGM);
6217 auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
6218
6219 values.addInt(ObjCTypes.IntTy, flags);
6220 values.addInt(ObjCTypes.IntTy, InstanceStart);
6221 values.addInt(ObjCTypes.IntTy, InstanceSize);
6222 values.add((flags & NonFragileABI_Class_Meta)
6223 ? GetIvarLayoutName(nullptr, ObjCTypes)
6224 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
6225 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
6226
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006227 // const struct _method_list_t * const baseMethods;
John McCall176f8922016-11-30 02:39:18 +00006228 SmallVector<const ObjCMethodDecl*, 16> methods;
John McCallef19dbb2012-10-17 04:53:23 +00006229 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00006230 for (const auto *MD : ID->class_methods())
6231 methods.push_back(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006232 } else {
John McCall176f8922016-11-30 02:39:18 +00006233 for (const auto *MD : ID->instance_methods())
6234 methods.push_back(MD);
Aaron Ballmanf26acce2014-03-13 19:50:17 +00006235
Aaron Ballmand85eff42014-03-14 15:02:45 +00006236 for (const auto *PID : ID->property_impls()) {
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00006237 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
6238 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006239
John McCall176f8922016-11-30 02:39:18 +00006240 if (auto MD = PD->getGetterMethodDecl())
6241 if (GetMethodDefinition(MD))
6242 methods.push_back(MD);
6243 if (auto MD = PD->getSetterMethodDecl())
6244 if (GetMethodDefinition(MD))
6245 methods.push_back(MD);
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00006246 }
6247 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006248 }
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006249
John McCall176f8922016-11-30 02:39:18 +00006250 values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
6251 (flags & NonFragileABI_Class_Meta)
6252 ? MethodListType::ClassMethods
6253 : MethodListType::InstanceMethods,
6254 methods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006255
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006256 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6257 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Akira Hatanaka187770d2019-05-09 17:43:52 +00006258 values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006259 + OID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006260 OID->all_referenced_protocol_begin(),
6261 OID->all_referenced_protocol_end()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006262
John McCallef19dbb2012-10-17 04:53:23 +00006263 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00006264 values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
6265 values.add(GetIvarLayoutName(nullptr, ObjCTypes));
6266 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00006267 "_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006268 ID, ID->getClassInterface(), ObjCTypes, true));
John McCallef19dbb2012-10-17 04:53:23 +00006269 } else {
John McCall176f8922016-11-30 02:39:18 +00006270 values.add(EmitIvarList(ID));
6271 values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
6272 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00006273 "_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006274 ID, ID->getClassInterface(), ObjCTypes, false));
John McCallef19dbb2012-10-17 04:53:23 +00006275 }
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006276
John McCall176f8922016-11-30 02:39:18 +00006277 llvm::SmallString<64> roLabel;
6278 llvm::raw_svector_ostream(roLabel)
Akira Hatanaka187770d2019-05-09 17:43:52 +00006279 << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_"
6280 : "_OBJC_CLASS_RO_$_")
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006281 << ClassName;
6282
Akira Hatanaka187770d2019-05-09 17:43:52 +00006283 return finishAndCreateGlobal(values, roLabel, CGM);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006284}
6285
John McCalldba63a72016-11-30 23:54:50 +00006286/// Build the metaclass object for a class.
6287///
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006288/// struct _class_t {
6289/// struct _class_t *isa;
6290/// struct _class_t * const superclass;
6291/// void *cache;
6292/// IMP *vtable;
6293/// struct class_ro_t *ro;
6294/// }
6295///
John McCalldba63a72016-11-30 23:54:50 +00006296llvm::GlobalVariable *
6297CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI,
6298 bool isMetaclass,
6299 llvm::Constant *IsAGV,
6300 llvm::Constant *SuperClassGV,
6301 llvm::Constant *ClassRoGV,
6302 bool HiddenVisibility) {
John McCall176f8922016-11-30 02:39:18 +00006303 ConstantInitBuilder builder(CGM);
6304 auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
6305 values.add(IsAGV);
6306 if (SuperClassGV) {
6307 values.add(SuperClassGV);
6308 } else {
6309 values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
6310 }
6311 values.add(ObjCEmptyCacheVar);
6312 values.add(ObjCEmptyVtableVar);
6313 values.add(ClassRoGV);
6314
John McCalldba63a72016-11-30 23:54:50 +00006315 llvm::GlobalVariable *GV =
6316 cast<llvm::GlobalVariable>(GetClassGlobal(CI, isMetaclass, ForDefinition));
John McCall176f8922016-11-30 02:39:18 +00006317 values.finishAndSetAsInitializer(GV);
6318
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006319 if (CGM.getTriple().isOSBinFormatMachO())
6320 GV->setSection("__DATA, __objc_data");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006321 GV->setAlignment(llvm::Align(
6322 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy)));
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006323 if (!CGM.getTriple().isOSBinFormatCOFF())
6324 if (HiddenVisibility)
6325 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006326 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006327}
6328
Joe Danielsf7393d22019-02-04 23:32:55 +00006329bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(
6330 const ObjCImplDecl *OD) const {
6331 return OD->getClassMethod(GetNullarySelector("load")) != nullptr ||
Erik Pilkington1138d8c2019-04-11 17:55:34 +00006332 OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() ||
6333 OD->hasAttr<ObjCNonLazyClassAttr>();
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006334}
6335
Daniel Dunbar961202372009-05-03 12:57:56 +00006336void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00006337 uint32_t &InstanceStart,
6338 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006339 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00006340 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006341
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006342 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00006343 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006344
6345 // If there are no fields, the start is the same as the end.
6346 if (!RL.getFieldCount())
6347 InstanceStart = InstanceSize;
6348 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00006349 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00006350}
6351
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006352static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
6353 StringRef Name) {
6354 IdentifierInfo &II = CGM.getContext().Idents.get(Name);
6355 TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
6356 DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
6357
6358 const VarDecl *VD = nullptr;
6359 for (const auto &Result : DC->lookup(&II))
6360 if ((VD = dyn_cast<VarDecl>(Result)))
6361 break;
6362
6363 if (!VD)
6364 return llvm::GlobalValue::DLLImportStorageClass;
6365 if (VD->hasAttr<DLLExportAttr>())
6366 return llvm::GlobalValue::DLLExportStorageClass;
6367 if (VD->hasAttr<DLLImportAttr>())
6368 return llvm::GlobalValue::DLLImportStorageClass;
6369 return llvm::GlobalValue::DefaultStorageClass;
6370}
6371
Fariborz Jahanian71394042009-01-23 23:53:38 +00006372void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00006373 if (!ObjCEmptyCacheVar) {
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006374 ObjCEmptyCacheVar =
6375 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false,
6376 llvm::GlobalValue::ExternalLinkage, nullptr,
6377 "_objc_empty_cache");
6378 if (CGM.getTriple().isOSBinFormatCOFF())
6379 ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache"));
Craig Topper8a13c412014-05-21 05:09:00 +00006380
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006381 // Only OS X with deployment version <10.9 use the empty vtable symbol
Fariborz Jahanian42d49552013-10-24 17:40:28 +00006382 const llvm::Triple &Triple = CGM.getTarget().getTriple();
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006383 if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006384 ObjCEmptyVtableVar =
6385 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false,
6386 llvm::GlobalValue::ExternalLinkage, nullptr,
6387 "_objc_empty_vtable");
John McCall176f8922016-11-30 02:39:18 +00006388 else
6389 ObjCEmptyVtableVar =
6390 llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
Fariborz Jahanian71394042009-01-23 23:53:38 +00006391 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006392
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00006393 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006394 uint32_t InstanceStart =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006395 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006396 uint32_t InstanceSize = InstanceStart;
John McCallef19dbb2012-10-17 04:53:23 +00006397 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006398
John McCalldba63a72016-11-30 23:54:50 +00006399 llvm::Constant *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006400
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006401 const auto *CI = ID->getClassInterface();
6402 assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0");
6403
John McCall0d54a172012-10-17 04:53:31 +00006404 // Build the flags for the metaclass.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006405 bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
6406 ? !CI->hasAttr<DLLExportAttr>()
6407 : CI->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006408 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006409 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006410
6411 // FIXME: why is this flag set on the metaclass?
6412 // ObjC metaclasses have no fields and don't really get constructed.
6413 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006414 flags |= NonFragileABI_Class_HasCXXStructors;
John McCall0d54a172012-10-17 04:53:31 +00006415 if (!ID->hasNonZeroConstructors())
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006416 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
John McCall0d54a172012-10-17 04:53:31 +00006417 }
6418
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006419 if (!CI->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006420 // class is root
John McCallef19dbb2012-10-17 04:53:23 +00006421 flags |= NonFragileABI_Class_Root;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006422
John McCalldba63a72016-11-30 23:54:50 +00006423 SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
6424 IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006425 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006426 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00006427 const ObjCInterfaceDecl *Root = ID->getClassInterface();
6428 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
6429 Root = Super;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006430
6431 const auto *Super = CI->getSuperClass();
John McCalldba63a72016-11-30 23:54:50 +00006432 IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
6433 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006434 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006435
6436 llvm::GlobalVariable *CLASS_RO_GV =
6437 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6438
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006439 llvm::GlobalVariable *MetaTClass =
John McCalldba63a72016-11-30 23:54:50 +00006440 BuildClassObject(CI, /*metaclass*/ true,
6441 IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
Rafael Espindolab7350042018-03-01 00:35:47 +00006442 CGM.setGVProperties(MetaTClass, CI);
Fariborz Jahanian67260552009-11-17 21:37:35 +00006443 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00006444
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006445 // Metadata for the class
John McCallef19dbb2012-10-17 04:53:23 +00006446 flags = 0;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006447 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006448 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006449
6450 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006451 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006452
John McCall0d54a172012-10-17 04:53:31 +00006453 // Set a flag to enable a runtime optimization when a class has
6454 // fields that require destruction but which don't require
6455 // anything except zero-initialization during construction. This
6456 // is most notably true of __strong and __weak types, but you can
6457 // also imagine there being C++ types with non-trivial default
6458 // constructors that merely set all fields to null.
6459 if (!ID->hasNonZeroConstructors())
6460 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6461 }
6462
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006463 if (hasObjCExceptionAttribute(CGM.getContext(), CI))
John McCallef19dbb2012-10-17 04:53:23 +00006464 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006465
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006466 if (!CI->getSuperClass()) {
John McCallef19dbb2012-10-17 04:53:23 +00006467 flags |= NonFragileABI_Class_Root;
Craig Topper8a13c412014-05-21 05:09:00 +00006468 SuperClassGV = nullptr;
Chris Lattnerb433b272009-04-19 06:02:28 +00006469 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006470 // Has a root. Current class is not a root.
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006471 const auto *Super = CI->getSuperClass();
John McCalldba63a72016-11-30 23:54:50 +00006472 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006473 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006474
Daniel Dunbar961202372009-05-03 12:57:56 +00006475 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006476 CLASS_RO_GV =
6477 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006478
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006479 llvm::GlobalVariable *ClassMD =
John McCalldba63a72016-11-30 23:54:50 +00006480 BuildClassObject(CI, /*metaclass*/ false,
6481 MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden);
Rafael Espindolab7350042018-03-01 00:35:47 +00006482 CGM.setGVProperties(ClassMD, CI);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006483 DefinedClasses.push_back(ClassMD);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006484 ImplementedClasses.push_back(CI);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006485
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006486 // Determine if this class is also "non-lazy".
6487 if (ImplementationIsNonLazy(ID))
6488 DefinedNonLazyClasses.push_back(ClassMD);
6489
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006490 // Force the definition of the EHType if necessary.
John McCallef19dbb2012-10-17 04:53:23 +00006491 if (flags & NonFragileABI_Class_Exception)
John McCalldba63a72016-11-30 23:54:50 +00006492 (void) GetInterfaceEHType(CI, ForDefinition);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006493 // Make sure method definition entries are all clear for next implementation.
6494 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00006495}
6496
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006497/// GenerateProtocolRef - This routine is called to generate code for
6498/// a protocol reference expression; as in:
6499/// @code
6500/// @protocol(Proto1);
6501/// @endcode
6502/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
6503/// which will hold address of the protocol meta-data.
6504///
John McCall882987f2013-02-28 19:01:20 +00006505llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006506 const ObjCProtocolDecl *PD) {
6507
Fariborz Jahanian464423d2009-04-10 18:47:34 +00006508 // This routine is called for @protocol only. So, we must build definition
6509 // of protocol's meta-data (not a reference to it!)
6510 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006511 llvm::Constant *Init =
6512 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00006513 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006514
Akira Hatanaka187770d2019-05-09 17:43:52 +00006515 std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_");
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006516 ProtocolName += PD->getObjCRuntimeNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006517
John McCall7f416cc2015-09-08 08:05:57 +00006518 CharUnits Align = CGF.getPointerAlign();
6519
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006520 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
6521 if (PTGV)
John McCall7f416cc2015-09-08 08:05:57 +00006522 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Saleem Abdulrasool9f83f3b2017-06-29 00:54:44 +00006523 PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
6524 llvm::GlobalValue::WeakAnyLinkage, Init,
6525 ProtocolName);
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006526 PTGV->setSection(GetSectionName("__objc_protorefs",
6527 "coalesced,no_dead_strip"));
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006528 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006529 PTGV->setAlignment(Align.getAsAlign());
Saleem Abdulrasool9f83f3b2017-06-29 00:54:44 +00006530 if (!CGM.getTriple().isOSBinFormatMachO())
6531 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
Saleem Abdulrasoolbe2b5cb2018-01-23 19:35:51 +00006532 CGM.addUsedGlobal(PTGV);
John McCall7f416cc2015-09-08 08:05:57 +00006533 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006534}
6535
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006536/// GenerateCategory - Build metadata for a category implementation.
6537/// struct _category_t {
6538/// const char * const name;
6539/// struct _class_t *const cls;
6540/// const struct _method_list_t * const instance_methods;
6541/// const struct _method_list_t * const class_methods;
6542/// const struct _protocol_list_t * const protocols;
6543/// const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00006544/// const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00006545/// const uint32_t size;
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006546/// }
6547///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006548void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006549 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Akira Hatanaka187770d2019-05-09 17:43:52 +00006550 const char *Prefix = "_OBJC_$_CATEGORY_";
Fangrui Song6907ce22018-07-30 19:24:48 +00006551
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006552 llvm::SmallString<64> ExtCatName(Prefix);
6553 ExtCatName += Interface->getObjCRuntimeNameAsString();
6554 ExtCatName += "_$_";
6555 ExtCatName += OCD->getNameAsString();
Fangrui Song6907ce22018-07-30 19:24:48 +00006556
John McCall176f8922016-11-30 02:39:18 +00006557 ConstantInitBuilder builder(CGM);
6558 auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
6559 values.add(GetClassName(OCD->getIdentifier()->getName()));
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006560 // meta-class entry symbol
John McCalldba63a72016-11-30 23:54:50 +00006561 values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
John McCall176f8922016-11-30 02:39:18 +00006562 std::string listName =
Saleem Abdulrasool209150a2016-10-24 21:25:57 +00006563 (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006564
John McCall176f8922016-11-30 02:39:18 +00006565 SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
6566 SmallVector<const ObjCMethodDecl *, 8> classMethods;
6567 for (const auto *MD : OCD->methods()) {
6568 if (MD->isInstanceMethod()) {
6569 instanceMethods.push_back(MD);
6570 } else {
6571 classMethods.push_back(MD);
6572 }
6573 }
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006574
John McCall176f8922016-11-30 02:39:18 +00006575 values.add(emitMethodList(listName, MethodListType::CategoryInstanceMethods,
6576 instanceMethods));
6577 values.add(emitMethodList(listName, MethodListType::CategoryClassMethods,
6578 classMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006579
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006580 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00006581 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006582 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006583 SmallString<256> ExtName;
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006584 llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006585 << OCD->getName();
Akira Hatanaka187770d2019-05-09 17:43:52 +00006586 values.add(EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006587 + Interface->getObjCRuntimeNameAsString() + "_$_"
6588 + Category->getName(),
John McCall176f8922016-11-30 02:39:18 +00006589 Category->protocol_begin(),
6590 Category->protocol_end()));
Akira Hatanaka187770d2019-05-09 17:43:52 +00006591 values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00006592 OCD, Category, ObjCTypes, false));
Akira Hatanaka187770d2019-05-09 17:43:52 +00006593 values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00006594 OCD, Category, ObjCTypes, true));
Mike Stump658fe022009-07-30 22:28:39 +00006595 } else {
John McCall176f8922016-11-30 02:39:18 +00006596 values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
6597 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6598 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006599 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006600
Manman Ren42ff3902016-02-24 17:49:50 +00006601 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
John McCall176f8922016-11-30 02:39:18 +00006602 values.addInt(ObjCTypes.IntTy, Size);
Manman Ren42ff3902016-02-24 17:49:50 +00006603
John McCall176f8922016-11-30 02:39:18 +00006604 llvm::GlobalVariable *GCATV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00006605 finishAndCreateGlobal(values, ExtCatName.str(), CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00006606 CGM.addCompilerUsedGlobal(GCATV);
John McCall2c91c3b2019-05-30 04:09:01 +00006607 if (Interface->hasAttr<ObjCClassStubAttr>())
6608 DefinedStubCategories.push_back(GCATV);
6609 else
6610 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006611
6612 // Determine if this category is also "non-lazy".
6613 if (ImplementationIsNonLazy(OCD))
6614 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006615 // method definition entries must be clear for next implementation.
6616 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006617}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006618
John McCall176f8922016-11-30 02:39:18 +00006619/// emitMethodConstant - Return a struct objc_method constant. If
6620/// forProtocol is true, the implementation will be null; otherwise,
6621/// the method must have a definition registered with the runtime.
6622///
6623/// struct _objc_method {
6624/// SEL _cmd;
6625/// char *method_type;
6626/// char *_imp;
6627/// }
6628void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
6629 const ObjCMethodDecl *MD,
6630 bool forProtocol) {
6631 auto method = builder.beginStruct(ObjCTypes.MethodTy);
6632 method.addBitCast(GetMethodVarName(MD->getSelector()),
6633 ObjCTypes.SelectorPtrTy);
6634 method.add(GetMethodVarType(MD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006635
John McCall176f8922016-11-30 02:39:18 +00006636 if (forProtocol) {
6637 // Protocol methods have no implementation. So, this entry is always NULL.
6638 method.addNullPointer(ObjCTypes.Int8PtrTy);
6639 } else {
6640 llvm::Function *fn = GetMethodDefinition(MD);
6641 assert(fn && "no definition for method?");
6642 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
6643 }
6644
6645 method.finishAndAddTo(builder);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006646}
6647
John McCall176f8922016-11-30 02:39:18 +00006648/// Build meta-data for method declarations.
6649///
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006650/// struct _method_list_t {
6651/// uint32_t entsize; // sizeof(struct _objc_method)
6652/// uint32_t method_count;
6653/// struct _objc_method method_list[method_count];
6654/// }
6655///
Zachary Turner41a9ee92017-10-11 23:54:34 +00006656llvm::Constant *
6657CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
6658 ArrayRef<const ObjCMethodDecl *> methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006659 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006660 if (methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006661 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006662
John McCall176f8922016-11-30 02:39:18 +00006663 StringRef prefix;
6664 bool forProtocol;
6665 switch (kind) {
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006666 case MethodListType::CategoryInstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006667 prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006668 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006669 break;
6670 case MethodListType::CategoryClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006671 prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006672 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006673 break;
6674 case MethodListType::InstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006675 prefix = "_OBJC_$_INSTANCE_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006676 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006677 break;
6678 case MethodListType::ClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006679 prefix = "_OBJC_$_CLASS_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006680 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006681 break;
6682
6683 case MethodListType::ProtocolInstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006684 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006685 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006686 break;
6687 case MethodListType::ProtocolClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006688 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006689 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006690 break;
6691 case MethodListType::OptionalProtocolInstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006692 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_";
John McCall176f8922016-11-30 02:39:18 +00006693 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006694 break;
6695 case MethodListType::OptionalProtocolClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006696 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_";
John McCall176f8922016-11-30 02:39:18 +00006697 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006698 break;
6699 }
6700
John McCall176f8922016-11-30 02:39:18 +00006701 ConstantInitBuilder builder(CGM);
6702 auto values = builder.beginStruct();
6703
6704 // sizeof(struct _objc_method)
6705 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
6706 values.addInt(ObjCTypes.IntTy, Size);
6707 // method_count
6708 values.addInt(ObjCTypes.IntTy, methods.size());
6709 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
6710 for (auto MD : methods) {
6711 emitMethodConstant(methodArray, MD, forProtocol);
6712 }
6713 methodArray.finishAndAddTo(values);
6714
Akira Hatanaka187770d2019-05-09 17:43:52 +00006715 llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00006716 CGM.addCompilerUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006717 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006718}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006719
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006720/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6721/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006722llvm::GlobalVariable *
6723CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6724 const ObjCIvarDecl *Ivar) {
6725 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006726 llvm::SmallString<64> Name("OBJC_IVAR_$_");
6727 Name += Container->getObjCRuntimeNameAsString();
6728 Name += ".";
6729 Name += Ivar->getName();
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006730 llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
6731 if (!IvarOffsetGV) {
6732 IvarOffsetGV =
6733 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy,
6734 false, llvm::GlobalValue::ExternalLinkage,
6735 nullptr, Name.str());
6736 if (CGM.getTriple().isOSBinFormatCOFF()) {
6737 bool IsPrivateOrPackage =
6738 Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6739 Ivar->getAccessControl() == ObjCIvarDecl::Package;
6740
Saleem Abdulrasoolad75c7d2017-10-25 03:58:15 +00006741 const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();
6742
6743 if (ContainingID->hasAttr<DLLImportAttr>())
6744 IvarOffsetGV
6745 ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
6746 else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
6747 IvarOffsetGV
6748 ->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006749 }
6750 }
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006751 return IvarOffsetGV;
6752}
6753
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006754llvm::Constant *
6755CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6756 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00006757 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006758 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Tim Northover238b5082014-03-29 13:42:40 +00006759 IvarOffsetGV->setInitializer(
6760 llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006761 IvarOffsetGV->setAlignment(llvm::Align(
6762 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy)));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006763
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006764 if (!CGM.getTriple().isOSBinFormatCOFF()) {
6765 // FIXME: This matches gcc, but shouldn't the visibility be set on the use
6766 // as well (i.e., in ObjCIvarOffsetVariable).
6767 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6768 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6769 ID->getVisibility() == HiddenVisibility)
6770 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6771 else
6772 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
6773 }
6774
Erik Pilkington2ff012d2019-01-17 18:18:53 +00006775 // If ID's layout is known, then make the global constant. This serves as a
6776 // useful assertion: we'll never use this variable to calculate ivar offsets,
6777 // so if the runtime tries to patch it then we should crash.
6778 if (isClassLayoutKnownStatically(ID))
6779 IvarOffsetGV->setConstant(true);
6780
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006781 if (CGM.getTriple().isOSBinFormatMachO())
6782 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006783 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006784}
6785
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006786/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006787/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006788/// IvarListnfABIPtrTy.
6789/// struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00006790/// unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006791/// char *name;
6792/// char *type;
6793/// uint32_t alignment;
6794/// uint32_t size;
6795/// }
6796/// struct _ivar_list_t {
6797/// uint32 entsize; // sizeof(struct _ivar_t)
6798/// uint32 count;
6799/// struct _iver_t list[count];
6800/// }
6801///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00006802
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006803llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006804 const ObjCImplementationDecl *ID) {
6805
John McCall176f8922016-11-30 02:39:18 +00006806 ConstantInitBuilder builder(CGM);
6807 auto ivarList = builder.beginStruct();
6808 ivarList.addInt(ObjCTypes.IntTy,
6809 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
6810 auto ivarCountSlot = ivarList.addPlaceholder();
6811 auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006812
Jordy Rosea91768e2011-07-22 02:08:32 +00006813 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006814 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006815
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006816 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006817
Fangrui Song6907ce22018-07-30 19:24:48 +00006818 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00006819 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00006820 // Ignore unnamed bit-fields.
6821 if (!IVD->getDeclName())
6822 continue;
John McCall176f8922016-11-30 02:39:18 +00006823
6824 auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
6825 ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
6826 ComputeIvarBaseOffset(CGM, ID, IVD)));
6827 ivar.add(GetMethodVarName(IVD->getIdentifier()));
6828 ivar.add(GetMethodVarType(IVD));
Chris Lattner2192fe52011-07-18 04:24:23 +00006829 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006830 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmowdd31ca12012-10-08 16:25:52 +00006831 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006832 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006833 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006834 Align = llvm::Log2_32(Align);
John McCall176f8922016-11-30 02:39:18 +00006835 ivar.addInt(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00006836 // NOTE. Size of a bitfield does not match gcc's, because of the
6837 // way bitfields are treated special in each. But I am told that
6838 // 'size' for bitfield ivars is ignored by the runtime so it does
6839 // not matter. If it matters, there is enough info to get the
6840 // bitfield right!
John McCall176f8922016-11-30 02:39:18 +00006841 ivar.addInt(ObjCTypes.IntTy, Size);
6842 ivar.finishAndAddTo(ivars);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006843 }
6844 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006845 if (ivars.empty()) {
6846 ivars.abandon();
6847 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00006848 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCall176f8922016-11-30 02:39:18 +00006849 }
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006850
John McCall176f8922016-11-30 02:39:18 +00006851 auto ivarCount = ivars.size();
6852 ivars.finishAndAddTo(ivarList);
6853 ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
6854
Akira Hatanaka187770d2019-05-09 17:43:52 +00006855 const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_";
6856 llvm::GlobalVariable *GV = finishAndCreateGlobal(
6857 ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00006858 CGM.addCompilerUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00006859 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006860}
6861
6862llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006863 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006864 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006865
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006866 if (!Entry) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006867 // We use the initializer as a marker of whether this is a forward
6868 // reference or not. At module finalization we add the empty
6869 // contents for protocols which were referenced but never defined.
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006870 llvm::SmallString<64> Protocol;
Akira Hatanaka6bc3a772019-03-14 15:17:37 +00006871 llvm::raw_svector_ostream(Protocol) << "_OBJC_PROTOCOL_$_"
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006872 << PD->getObjCRuntimeNameAsString();
6873
6874 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6875 false, llvm::GlobalValue::ExternalLinkage,
6876 nullptr, Protocol);
6877 if (!CGM.getTriple().isOSBinFormatMachO())
6878 Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
6879 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006880
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006881 return Entry;
6882}
6883
6884/// GetOrEmitProtocol - Generate the protocol meta-data:
6885/// @code
6886/// struct _protocol_t {
6887/// id isa; // NULL
6888/// const char * const protocol_name;
6889/// const struct _protocol_list_t * protocol_list; // super protocols
6890/// const struct method_list_t * const instance_methods;
6891/// const struct method_list_t * const class_methods;
6892/// const struct method_list_t *optionalInstanceMethods;
6893/// const struct method_list_t *optionalClassMethods;
6894/// const struct _prop_list_t * properties;
6895/// const uint32_t size; // sizeof(struct _protocol_t)
6896/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006897/// const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006898/// const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00006899/// const struct _prop_list_t * class_properties;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006900/// }
6901/// @endcode
6902///
6903
6904llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006905 const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00006906 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006907
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006908 // Early exit if a defining object has already been generated.
6909 if (Entry && Entry->hasInitializer())
6910 return Entry;
6911
Douglas Gregora715bff2012-01-01 19:51:50 +00006912 // Use the protocol definition, if there is one.
Alex Lorenzb111da12018-08-17 22:18:08 +00006913 assert(PD->hasDefinition() &&
6914 "emitting protocol metadata without definition");
6915 PD = PD->getDefinition();
Fangrui Song6907ce22018-07-30 19:24:48 +00006916
John McCall176f8922016-11-30 02:39:18 +00006917 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006918
John McCall176f8922016-11-30 02:39:18 +00006919 ConstantInitBuilder builder(CGM);
6920 auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
Douglas Gregora9d84932011-05-27 01:19:52 +00006921
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006922 // isa is NULL
John McCall176f8922016-11-30 02:39:18 +00006923 values.addNullPointer(ObjCTypes.ObjectPtrTy);
6924 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
Akira Hatanaka187770d2019-05-09 17:43:52 +00006925 values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_"
John McCall176f8922016-11-30 02:39:18 +00006926 + PD->getObjCRuntimeNameAsString(),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006927 PD->protocol_begin(),
John McCall176f8922016-11-30 02:39:18 +00006928 PD->protocol_end()));
6929 values.add(methodLists.emitMethodList(this, PD,
6930 ProtocolMethodLists::RequiredInstanceMethods));
6931 values.add(methodLists.emitMethodList(this, PD,
6932 ProtocolMethodLists::RequiredClassMethods));
6933 values.add(methodLists.emitMethodList(this, PD,
6934 ProtocolMethodLists::OptionalInstanceMethods));
6935 values.add(methodLists.emitMethodList(this, PD,
6936 ProtocolMethodLists::OptionalClassMethods));
6937 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00006938 "_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006939 nullptr, PD, ObjCTypes, false));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006940 uint32_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006941 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
John McCall176f8922016-11-30 02:39:18 +00006942 values.addInt(ObjCTypes.IntTy, Size);
6943 values.addInt(ObjCTypes.IntTy, 0);
Akira Hatanaka187770d2019-05-09 17:43:52 +00006944 values.add(EmitProtocolMethodTypes("_OBJC_$_PROTOCOL_METHOD_TYPES_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006945 + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006946 methodLists.emitExtendedTypesArray(this),
6947 ObjCTypes));
6948
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006949 // const char *demangledName;
John McCall176f8922016-11-30 02:39:18 +00006950 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Rence7bff52016-01-29 23:46:55 +00006951
John McCall176f8922016-11-30 02:39:18 +00006952 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00006953 "_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006954 nullptr, PD, ObjCTypes, true));
Fangrui Song6907ce22018-07-30 19:24:48 +00006955
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006956 if (Entry) {
Rafael Espindola24615092014-09-12 20:14:20 +00006957 // Already created, fix the linkage and update the initializer.
6958 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
John McCall176f8922016-11-30 02:39:18 +00006959 values.finishAndSetAsInitializer(Entry);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006960 } else {
John McCall176f8922016-11-30 02:39:18 +00006961 llvm::SmallString<64> symbolName;
6962 llvm::raw_svector_ostream(symbolName)
Akira Hatanaka6bc3a772019-03-14 15:17:37 +00006963 << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006964
John McCall176f8922016-11-30 02:39:18 +00006965 Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
6966 /*constant*/ false,
6967 llvm::GlobalValue::WeakAnyLinkage);
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006968 if (!CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00006969 Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
John McCallf9582a72012-03-30 21:29:05 +00006970
6971 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006972 }
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006973 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoolbe2b5cb2018-01-23 19:35:51 +00006974 CGM.addUsedGlobal(Entry);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006975
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006976 // Use this protocol meta-data to build protocol list table in section
6977 // __DATA, __objc_protolist
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006978 llvm::SmallString<64> ProtocolRef;
Akira Hatanaka6bc3a772019-03-14 15:17:37 +00006979 llvm::raw_svector_ostream(ProtocolRef) << "_OBJC_LABEL_PROTOCOL_$_"
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006980 << PD->getObjCRuntimeNameAsString();
6981
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006982 llvm::GlobalVariable *PTGV =
6983 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006984 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00006985 ProtocolRef);
6986 if (!CGM.getTriple().isOSBinFormatMachO())
6987 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006988 PTGV->setAlignment(llvm::Align(
6989 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)));
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006990 PTGV->setSection(GetSectionName("__objc_protolist",
6991 "coalesced,no_dead_strip"));
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006992 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoolbe2b5cb2018-01-23 19:35:51 +00006993 CGM.addUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006994 return Entry;
6995}
6996
6997/// EmitProtocolList - Generate protocol list meta-data:
6998/// @code
6999/// struct _protocol_list_t {
7000/// long protocol_count; // Note, this is 32/64 bit
7001/// struct _protocol_t[protocol_count];
7002/// }
7003/// @endcode
7004///
Zachary Turner41a9ee92017-10-11 23:54:34 +00007005llvm::Constant *
7006CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
7007 ObjCProtocolDecl::protocol_iterator begin,
7008 ObjCProtocolDecl::protocol_iterator end) {
Dmitri Gribenkof8579502013-01-12 19:30:44 +00007009 SmallVector<llvm::Constant *, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007010
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007011 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007012 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00007013 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007014
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007015 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00007016 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007017 Name.toVector(TmpName);
7018 llvm::GlobalVariable *GV =
7019 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007020 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007021 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007022
John McCall176f8922016-11-30 02:39:18 +00007023 ConstantInitBuilder builder(CGM);
7024 auto values = builder.beginStruct();
7025 auto countSlot = values.addPlaceholder();
7026
7027 // A null-terminated array of protocols.
7028 auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007029 for (; begin != end; ++begin)
John McCall176f8922016-11-30 02:39:18 +00007030 array.add(GetProtocolRef(*begin)); // Implemented???
7031 auto count = array.size();
7032 array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007033
John McCall176f8922016-11-30 02:39:18 +00007034 array.finishAndAddTo(values);
7035 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007036
Akira Hatanaka187770d2019-05-09 17:43:52 +00007037 GV = finishAndCreateGlobal(values, Name, CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00007038 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007039 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007040 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007041}
7042
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00007043/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
7044/// This code gen. amounts to generating code for:
7045/// @code
7046/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
7047/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007048///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00007049LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00007050 CodeGen::CodeGenFunction &CGF,
7051 QualType ObjectTy,
7052 llvm::Value *BaseValue,
7053 const ObjCIvarDecl *Ivar,
7054 unsigned CVRQualifiers) {
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00007055 ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00007056 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00007057 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00007058 Offset);
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00007059}
7060
Erik Pilkington2ff012d2019-01-17 18:18:53 +00007061llvm::Value *
7062CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
7063 const ObjCInterfaceDecl *Interface,
7064 const ObjCIvarDecl *Ivar) {
7065 llvm::Value *IvarOffsetValue;
7066 if (isClassLayoutKnownStatically(Interface)) {
7067 IvarOffsetValue = llvm::ConstantInt::get(
7068 ObjCTypes.IvarOffsetVarTy,
7069 ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar));
7070 } else {
7071 llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
7072 IvarOffsetValue =
7073 CGF.Builder.CreateAlignedLoad(GV, CGF.getSizeAlign(), "ivar");
7074 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
7075 cast<llvm::LoadInst>(IvarOffsetValue)
7076 ->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
7077 llvm::MDNode::get(VMContext, None));
7078 }
Tim Northover238b5082014-03-29 13:42:40 +00007079
7080 // This could be 32bit int or 64bit integer depending on the architecture.
7081 // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007082 // as this is what caller always expects.
Tim Northover238b5082014-03-29 13:42:40 +00007083 if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
7084 IvarOffsetValue = CGF.Builder.CreateIntCast(
7085 IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
7086 return IvarOffsetValue;
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00007087}
7088
John McCall234eac82011-05-13 23:16:18 +00007089static void appendSelectorForMessageRefTable(std::string &buffer,
7090 Selector selector) {
7091 if (selector.isUnarySelector()) {
7092 buffer += selector.getNameForSlot(0);
7093 return;
7094 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007095
John McCall234eac82011-05-13 23:16:18 +00007096 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
7097 buffer += selector.getNameForSlot(i);
7098 buffer += '_';
7099 }
7100}
7101
Eric Christopherd160c502016-01-29 01:35:53 +00007102/// Emit a "vtable" message send. We emit a weak hidden-visibility
John McCall9e8bb002011-05-14 03:10:52 +00007103/// struct, initially containing the selector pointer and a pointer to
7104/// a "fixup" variant of the appropriate objc_msgSend. To call, we
7105/// load and call the function pointer, passing the address of the
7106/// struct as the second parameter. The runtime determines whether
7107/// the selector is currently emitted using vtable dispatch; if so, it
7108/// substitutes a stub function which simply tail-calls through the
7109/// appropriate vtable slot, and if not, it substitues a stub function
7110/// which tail-calls objc_msgSend. Both stubs adjust the selector
7111/// argument to correctly point to the selector.
7112RValue
7113CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
7114 ReturnValueSlot returnSlot,
7115 QualType resultType,
7116 Selector selector,
7117 llvm::Value *arg0,
7118 QualType arg0Type,
7119 bool isSuper,
7120 const CallArgList &formalArgs,
7121 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00007122 // Compute the actual arguments.
7123 CallArgList args;
7124
John McCall9e8bb002011-05-14 03:10:52 +00007125 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00007126 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00007127 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
7128 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00007129
John McCall9e8bb002011-05-14 03:10:52 +00007130 // Second argument: a pointer to the message ref structure. Leave
7131 // the actual argument value blank for now.
Craig Topper8a13c412014-05-21 05:09:00 +00007132 args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
John McCall234eac82011-05-13 23:16:18 +00007133
7134 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
7135
John McCalla729c622012-02-17 03:33:10 +00007136 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCall234eac82011-05-13 23:16:18 +00007137
John McCall5880fb82011-05-14 21:12:11 +00007138 NullReturnState nullReturn;
7139
John McCall9e8bb002011-05-14 03:10:52 +00007140 // Find the function to call and the mangled name for the message
7141 // ref structure. Using a different mangled name wouldn't actually
7142 // be a problem; it would just be a waste.
7143 //
7144 // The runtime currently never uses vtable dispatch for anything
7145 // except normal, non-super message-sends.
7146 // FIXME: don't use this for that.
James Y Knight9871db02019-02-05 16:42:33 +00007147 llvm::FunctionCallee fn = nullptr;
Akira Hatanaka187770d2019-05-09 17:43:52 +00007148 std::string messageRefName("_");
Tim Northovere77cc392014-03-29 13:28:05 +00007149 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
John McCall234eac82011-05-13 23:16:18 +00007150 if (isSuper) {
7151 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
7152 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007153 } else {
John McCall5880fb82011-05-14 21:12:11 +00007154 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00007155 fn = ObjCTypes.getMessageSendStretFixupFn();
7156 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007157 }
John McCall234eac82011-05-13 23:16:18 +00007158 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
7159 fn = ObjCTypes.getMessageSendFpretFixupFn();
7160 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00007161 } else {
John McCall234eac82011-05-13 23:16:18 +00007162 if (isSuper) {
7163 fn = ObjCTypes.getMessageSendSuper2FixupFn();
7164 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007165 } else {
John McCall234eac82011-05-13 23:16:18 +00007166 fn = ObjCTypes.getMessageSendFixupFn();
7167 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007168 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00007169 }
John McCall234eac82011-05-13 23:16:18 +00007170 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
7171 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007172
John McCall234eac82011-05-13 23:16:18 +00007173 // Append the selector name, except use underscores anywhere we
7174 // would have used colons.
7175 appendSelectorForMessageRefTable(messageRefName, selector);
7176
7177 llvm::GlobalVariable *messageRef
7178 = CGM.getModule().getGlobalVariable(messageRefName);
7179 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00007180 // Build the message ref structure.
John McCall176f8922016-11-30 02:39:18 +00007181 ConstantInitBuilder builder(CGM);
7182 auto values = builder.beginStruct();
James Y Knight9871db02019-02-05 16:42:33 +00007183 values.add(cast<llvm::Constant>(fn.getCallee()));
John McCall176f8922016-11-30 02:39:18 +00007184 values.add(GetMethodVarName(selector));
7185 messageRef = values.finishAndCreateGlobal(messageRefName,
7186 CharUnits::fromQuantity(16),
7187 /*constant*/ false,
7188 llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007189 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00007190 messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced"));
John McCall234eac82011-05-13 23:16:18 +00007191 }
Fangrui Song6907ce22018-07-30 19:24:48 +00007192
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00007193 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00007194 if (CGM.getLangOpts().ObjCAutoRefCount && method)
David Majnemer59f77922016-06-24 04:05:48 +00007195 for (const auto *ParamDecl : method->parameters()) {
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00007196 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
7197 if (!nullReturn.NullBB)
7198 nullReturn.init(CGF, arg0);
7199 requiresnullCheck = true;
7200 break;
7201 }
7202 }
Fangrui Song6907ce22018-07-30 19:24:48 +00007203
John McCall7f416cc2015-09-08 08:05:57 +00007204 Address mref =
7205 Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
7206 CGF.getPointerAlign());
John McCall234eac82011-05-13 23:16:18 +00007207
John McCall9e8bb002011-05-14 03:10:52 +00007208 // Update the message ref argument.
Yaxun Liu5b330e82018-03-15 15:25:19 +00007209 args[1].setRValue(RValue::get(mref.getPointer()));
John McCall234eac82011-05-13 23:16:18 +00007210
7211 // Load the function to call from the message ref table.
James Y Knight751fe282019-02-09 22:22:28 +00007212 Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0);
John McCallb92ab1a2016-10-26 23:46:34 +00007213 llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
John McCall234eac82011-05-13 23:16:18 +00007214
John McCallb92ab1a2016-10-26 23:46:34 +00007215 calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
7216 CGCallee callee(CGCalleeInfo(), calleePtr);
John McCall234eac82011-05-13 23:16:18 +00007217
John McCalla729c622012-02-17 03:33:10 +00007218 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Kuba Mracekbce5cea2017-06-30 16:28:15 +00007219 return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
Craig Topper8a13c412014-05-21 05:09:00 +00007220 requiresnullCheck ? method : nullptr);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007221}
7222
7223/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007224CodeGen::RValue
7225CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007226 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007227 QualType ResultType,
7228 Selector Sel,
7229 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007230 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00007231 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007232 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00007233 return isVTableDispatchedSelector(Sel)
7234 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007235 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00007236 false, CallArgs, Method)
7237 : EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00007238 EmitSelector(CGF, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007239 Receiver, CGF.getContext().getObjCIdType(),
John McCall1e3157b2015-09-10 22:27:50 +00007240 false, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007241}
7242
John McCalldba63a72016-11-30 23:54:50 +00007243llvm::Constant *
7244CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
7245 bool metaclass,
7246 ForDefinition_t isForDefinition) {
7247 auto prefix =
7248 (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
7249 return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
7250 isForDefinition,
7251 ID->isWeakImported(),
7252 !isForDefinition
7253 && CGM.getTriple().isOSBinFormatCOFF()
7254 && ID->hasAttr<DLLImportAttr>());
7255}
7256
7257llvm::Constant *
7258CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
7259 ForDefinition_t IsForDefinition,
7260 bool Weak, bool DLLImport) {
Rafael Espindola554256c2014-02-26 22:25:45 +00007261 llvm::GlobalValue::LinkageTypes L =
7262 Weak ? llvm::GlobalValue::ExternalWeakLinkage
7263 : llvm::GlobalValue::ExternalLinkage;
7264
John McCalldba63a72016-11-30 23:54:50 +00007265 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
Erik Pilkington92d8a292018-10-12 17:22:10 +00007266 if (!GV || GV->getType() != ObjCTypes.ClassnfABITy->getPointerTo()) {
7267 auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
7268 nullptr, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007269
John McCalldba63a72016-11-30 23:54:50 +00007270 if (DLLImport)
Erik Pilkington92d8a292018-10-12 17:22:10 +00007271 NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
7272
7273 if (GV) {
7274 GV->replaceAllUsesWith(
7275 llvm::ConstantExpr::getBitCast(NewGV, GV->getType()));
7276 GV->eraseFromParent();
7277 }
7278 GV = NewGV;
7279 CGM.getModule().getGlobalList().push_back(GV);
John McCalldba63a72016-11-30 23:54:50 +00007280 }
7281
Rafael Espindola554256c2014-02-26 22:25:45 +00007282 assert(GV->getLinkage() == L);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007283 return GV;
7284}
7285
John McCall2c91c3b2019-05-30 04:09:01 +00007286llvm::Constant *
7287CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
7288 llvm::Constant *ClassGV = GetClassGlobal(ID, /*metaclass*/ false,
7289 NotForDefinition);
7290
7291 if (!ID->hasAttr<ObjCClassStubAttr>())
7292 return ClassGV;
7293
7294 ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy);
7295
7296 // Stub classes are pointer-aligned. Classrefs pointing at stub classes
7297 // must set the least significant bit set to 1.
7298 auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
7299 return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx);
7300}
7301
7302llvm::Value *
7303CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF,
7304 const ObjCInterfaceDecl *ID,
7305 llvm::GlobalVariable *Entry) {
7306 if (ID && ID->hasAttr<ObjCClassStubAttr>()) {
7307 // Classrefs pointing at Objective-C stub classes must be loaded by calling
7308 // a special runtime function.
7309 return CGF.EmitRuntimeCall(
7310 ObjCTypes.getLoadClassrefFn(), Entry, "load_classref_result");
7311 }
7312
7313 CharUnits Align = CGF.getPointerAlign();
7314 return CGF.Builder.CreateAlignedLoad(Entry, Align);
7315}
7316
John McCalldba63a72016-11-30 23:54:50 +00007317llvm::Value *
7318CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
7319 IdentifierInfo *II,
7320 const ObjCInterfaceDecl *ID) {
John McCall31168b02011-06-15 23:02:42 +00007321 llvm::GlobalVariable *&Entry = ClassReferences[II];
Fangrui Song6907ce22018-07-30 19:24:48 +00007322
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007323 if (!Entry) {
John McCalldba63a72016-11-30 23:54:50 +00007324 llvm::Constant *ClassGV;
7325 if (ID) {
John McCall2c91c3b2019-05-30 04:09:01 +00007326 ClassGV = GetClassGlobalForClassRef(ID);
John McCalldba63a72016-11-30 23:54:50 +00007327 } else {
7328 ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
7329 NotForDefinition);
John McCall2c91c3b2019-05-30 04:09:01 +00007330 assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy &&
7331 "classref was emitted with the wrong type?");
John McCalldba63a72016-11-30 23:54:50 +00007332 }
7333
Akira Hatanaka187770d2019-05-09 17:43:52 +00007334 std::string SectionName =
7335 GetSectionName("__objc_classrefs", "regular,no_dead_strip");
7336 Entry = new llvm::GlobalVariable(
John McCall2c91c3b2019-05-30 04:09:01 +00007337 CGM.getModule(), ClassGV->getType(), false,
Akira Hatanaka187770d2019-05-09 17:43:52 +00007338 getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
7339 "OBJC_CLASSLIST_REFERENCES_$_");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007340 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
John McCall2c91c3b2019-05-30 04:09:01 +00007341 if (!ID || !ID->hasAttr<ObjCClassStubAttr>())
7342 Entry->setSection(SectionName);
7343
Rafael Espindola060062a2014-03-06 22:15:10 +00007344 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007345 }
John McCall2c91c3b2019-05-30 04:09:01 +00007346
7347 return EmitLoadOfClassRef(CGF, ID, Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007348}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007349
John McCall882987f2013-02-28 19:01:20 +00007350llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00007351 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00007352 // If the class has the objc_runtime_visible attribute, we need to
7353 // use the Objective-C runtime to get the class.
7354 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
7355 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
7356
John McCalldba63a72016-11-30 23:54:50 +00007357 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
John McCall31168b02011-06-15 23:02:42 +00007358}
7359
7360llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
John McCall882987f2013-02-28 19:01:20 +00007361 CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00007362 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
John McCalldba63a72016-11-30 23:54:50 +00007363 return EmitClassRefFromId(CGF, II, nullptr);
John McCall31168b02011-06-15 23:02:42 +00007364}
7365
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007366llvm::Value *
John McCall882987f2013-02-28 19:01:20 +00007367CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007368 const ObjCInterfaceDecl *ID) {
7369 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007370
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007371 if (!Entry) {
John McCall2c91c3b2019-05-30 04:09:01 +00007372 llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007373 std::string SectionName =
7374 GetSectionName("__objc_superrefs", "regular,no_dead_strip");
7375 Entry = new llvm::GlobalVariable(
John McCall2c91c3b2019-05-30 04:09:01 +00007376 CGM.getModule(), ClassGV->getType(), false,
Akira Hatanaka187770d2019-05-09 17:43:52 +00007377 getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
7378 "OBJC_CLASSLIST_SUP_REFS_$_");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007379 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
Akira Hatanaka187770d2019-05-09 17:43:52 +00007380 Entry->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00007381 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007382 }
John McCall2c91c3b2019-05-30 04:09:01 +00007383
7384 return EmitLoadOfClassRef(CGF, ID, Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007385}
7386
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007387/// EmitMetaClassRef - Return a Value * of the address of _class_t
7388/// meta-data
7389///
John McCall882987f2013-02-28 19:01:20 +00007390llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00007391 const ObjCInterfaceDecl *ID,
7392 bool Weak) {
John McCall7f416cc2015-09-08 08:05:57 +00007393 CharUnits Align = CGF.getPointerAlign();
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007394 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
Rafael Espindola21039aa2014-02-27 16:26:32 +00007395 if (!Entry) {
John McCalldba63a72016-11-30 23:54:50 +00007396 auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007397 std::string SectionName =
7398 GetSectionName("__objc_superrefs", "regular,no_dead_strip");
7399 Entry = new llvm::GlobalVariable(
7400 CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
7401 getLinkageTypeForObjCMetadata(CGM, SectionName), MetaClassGV,
7402 "OBJC_CLASSLIST_SUP_REFS_$_");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007403 Entry->setAlignment(Align.getAsAlign());
Akira Hatanaka187770d2019-05-09 17:43:52 +00007404 Entry->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00007405 CGM.addCompilerUsedGlobal(Entry);
Rafael Espindola21039aa2014-02-27 16:26:32 +00007406 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007407
John McCall7f416cc2015-09-08 08:05:57 +00007408 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007409}
7410
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007411/// GetClass - Return a reference to the class for the given interface
7412/// decl.
John McCall882987f2013-02-28 19:01:20 +00007413llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007414 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00007415 if (ID->isWeakImported()) {
John McCalldba63a72016-11-30 23:54:50 +00007416 auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
Nick Lewycky9a441642014-02-27 00:36:00 +00007417 (void)ClassGV;
John McCalldba63a72016-11-30 23:54:50 +00007418 assert(!isa<llvm::GlobalVariable>(ClassGV) ||
7419 cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
Fariborz Jahanian95ace552009-11-17 22:42:00 +00007420 }
Fangrui Song6907ce22018-07-30 19:24:48 +00007421
John McCall882987f2013-02-28 19:01:20 +00007422 return EmitClassRef(CGF, ID);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007423}
7424
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007425/// Generates a message send where the super is the receiver. This is
7426/// a message send to self with special delivery semantics indicating
7427/// which class's method should be called.
7428CodeGen::RValue
7429CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007430 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007431 QualType ResultType,
7432 Selector Sel,
7433 const ObjCInterfaceDecl *Class,
7434 bool isCategoryImpl,
7435 llvm::Value *Receiver,
7436 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007437 const CodeGen::CallArgList &CallArgs,
7438 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007439 // ...
7440 // Create and init a super structure; this is a (receiver, class)
7441 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00007442 Address ObjCSuper =
7443 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
7444 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007445
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007446 llvm::Value *ReceiverAsObject =
7447 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
James Y Knight751fe282019-02-09 22:22:28 +00007448 CGF.Builder.CreateStore(ReceiverAsObject,
7449 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007450
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007451 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00007452 llvm::Value *Target;
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007453 if (IsClassMessage)
Fariborz Jahanian85b99da2014-08-28 17:05:17 +00007454 Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007455 else
John McCall882987f2013-02-28 19:01:20 +00007456 Target = EmitSuperClassRef(CGF, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007457
Mike Stump18bb9282009-05-16 07:57:57 +00007458 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
7459 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00007460 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007461 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
7462 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
James Y Knight751fe282019-02-09 22:22:28 +00007463 CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007464
John McCall9e8bb002011-05-14 03:10:52 +00007465 return (isVTableDispatchedSelector(Sel))
7466 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
John McCall7f416cc2015-09-08 08:05:57 +00007467 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00007468 true, CallArgs, Method)
7469 : EmitMessageSend(CGF, Return, ResultType,
John McCall882987f2013-02-28 19:01:20 +00007470 EmitSelector(CGF, Sel),
John McCall7f416cc2015-09-08 08:05:57 +00007471 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall1e3157b2015-09-10 22:27:50 +00007472 true, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007473}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007474
John McCall882987f2013-02-28 19:01:20 +00007475llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007476 Selector Sel) {
7477 Address Addr = EmitSelectorAddr(CGF, Sel);
7478
7479 llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
Fangrui Song6907ce22018-07-30 19:24:48 +00007480 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
John McCall7f416cc2015-09-08 08:05:57 +00007481 llvm::MDNode::get(VMContext, None));
7482 return LI;
7483}
7484
7485Address CGObjCNonFragileABIMac::EmitSelectorAddr(CodeGenFunction &CGF,
7486 Selector Sel) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007487 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007488
John McCall7f416cc2015-09-08 08:05:57 +00007489 CharUnits Align = CGF.getPointerAlign();
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007490 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007491 llvm::Constant *Casted =
7492 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
7493 ObjCTypes.SelectorPtrTy);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007494 std::string SectionName =
7495 GetSectionName("__objc_selrefs", "literal_pointers,no_dead_strip");
7496 Entry = new llvm::GlobalVariable(
7497 CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
7498 getLinkageTypeForObjCMetadata(CGM, SectionName), Casted,
7499 "OBJC_SELECTOR_REFERENCES_");
Michael Gottesman5c205962013-02-05 23:08:45 +00007500 Entry->setExternallyInitialized(true);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007501 Entry->setSection(SectionName);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007502 Entry->setAlignment(Align.getAsAlign());
Rafael Espindola060062a2014-03-06 22:15:10 +00007503 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007504 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007505
John McCall7f416cc2015-09-08 08:05:57 +00007506 return Address(Entry, Align);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007507}
John McCall7f416cc2015-09-08 08:05:57 +00007508
Fariborz Jahanian06292952009-02-16 22:52:32 +00007509/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007510/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00007511///
7512void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00007513 llvm::Value *src,
John McCall7f416cc2015-09-08 08:05:57 +00007514 Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007515 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007516 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007517 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007518 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007519 assert(Size <= 8 && "does not support size > 8");
7520 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7521 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007522 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7523 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007524 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7525 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007526 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00007527 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007528}
7529
7530/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
7531/// objc_assign_strongCast (id src, id *dst)
7532///
7533void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007534 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007535 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007536 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007537 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007538 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007539 assert(Size <= 8 && "does not support size > 8");
7540 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007541 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007542 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7543 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007544 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7545 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007546 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007547 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
7548 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007549}
7550
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007551void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007552 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007553 Address DestPtr,
7554 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00007555 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007556 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
7557 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007558 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size };
John McCall882987f2013-02-28 19:01:20 +00007559 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007560}
7561
Fariborz Jahanian06292952009-02-16 22:52:32 +00007562/// EmitObjCWeakRead - Code gen for loading value of a __weak
7563/// object: objc_read_weak (id *src)
7564///
7565llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007566 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007567 Address AddrWeakObj) {
7568 llvm::Type *DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007569 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00007570 llvm::Value *read_weak =
7571 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00007572 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00007573 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007574 return read_weak;
7575}
7576
7577/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
7578/// objc_assign_weak (id src, id *dst)
7579///
7580void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007581 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007582 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007583 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007584 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007585 assert(Size <= 8 && "does not support size > 8");
7586 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7587 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007588 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7589 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007590 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7591 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007592 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007593 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
7594 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007595}
7596
7597/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
7598/// objc_assign_global (id src, id *dst)
7599///
7600void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007601 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00007602 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007603 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007604 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007605 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007606 assert(Size <= 8 && "does not support size > 8");
7607 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7608 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007609 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7610 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007611 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7612 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007613 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00007614 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00007615 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
7616 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00007617 else
John McCall882987f2013-02-28 19:01:20 +00007618 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
7619 args, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007620}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007621
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007622void
John McCallbd309292010-07-06 01:34:17 +00007623CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
7624 const ObjCAtSynchronizedStmt &S) {
James Y Knight9871db02019-02-05 16:42:33 +00007625 EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(),
7626 ObjCTypes.getSyncExitFn());
John McCallbd309292010-07-06 01:34:17 +00007627}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007628
John McCall2ca705e2010-07-24 00:37:23 +00007629llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00007630CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00007631 // There's a particular fixed type info for 'id'.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007632 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
7633 auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007634 if (!IDEHType) {
John McCall2ca705e2010-07-24 00:37:23 +00007635 IDEHType =
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007636 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
7637 llvm::GlobalValue::ExternalLinkage, nullptr,
7638 "OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007639 if (CGM.getTriple().isOSBinFormatCOFF())
7640 IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id"));
7641 }
John McCall2ca705e2010-07-24 00:37:23 +00007642 return IDEHType;
7643 }
7644
7645 // All other types should be Objective-C interface pointer types.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007646 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
John McCall2ca705e2010-07-24 00:37:23 +00007647 assert(PT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007648
John McCall2ca705e2010-07-24 00:37:23 +00007649 const ObjCInterfaceType *IT = PT->getInterfaceType();
7650 assert(IT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007651
John McCalldba63a72016-11-30 23:54:50 +00007652 return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007653}
John McCall2ca705e2010-07-24 00:37:23 +00007654
John McCallbd309292010-07-06 01:34:17 +00007655void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
7656 const ObjCAtTryStmt &S) {
James Y Knight9871db02019-02-05 16:42:33 +00007657 EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(),
7658 ObjCTypes.getObjCEndCatchFn(),
7659 ObjCTypes.getExceptionRethrowFn());
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00007660}
7661
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007662/// EmitThrowStmt - Generate code for a throw statement.
7663void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007664 const ObjCAtThrowStmt &S,
7665 bool ClearInsertionPoint) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007666 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00007667 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00007668 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
James Y Knight3933add2019-01-30 02:54:28 +00007669 llvm::CallBase *Call =
7670 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception);
7671 Call->setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007672 } else {
James Y Knight3933add2019-01-30 02:54:28 +00007673 llvm::CallBase *Call =
7674 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn());
7675 Call->setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007676 }
7677
John McCall17afe452010-10-16 08:21:07 +00007678 CGF.Builder.CreateUnreachable();
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007679 if (ClearInsertionPoint)
7680 CGF.Builder.ClearInsertionPoint();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007681}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007682
John McCall2ca705e2010-07-24 00:37:23 +00007683llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007684CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
John McCalldba63a72016-11-30 23:54:50 +00007685 ForDefinition_t IsForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007686 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007687 StringRef ClassName = ID->getObjCRuntimeNameAsString();
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007688
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007689 // If we don't need a definition, return the entry if found or check
7690 // if we use an external reference.
John McCalldba63a72016-11-30 23:54:50 +00007691 if (!IsForDefinition) {
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007692 if (Entry)
7693 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00007694
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007695 // If this type (or a super class) has the __objc_exception__
7696 // attribute, emit an external reference.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007697 if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
7698 std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str();
7699 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
7700 false, llvm::GlobalValue::ExternalLinkage,
7701 nullptr, EHTypeName);
Rafael Espindolab7350042018-03-01 00:35:47 +00007702 CGM.setGVProperties(Entry, ID);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007703 return Entry;
7704 }
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007705 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007706
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007707 // Otherwise we need to either make a new entry or fill in the initializer.
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007708 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007709
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007710 std::string VTableName = "objc_ehtype_vtable";
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007711 auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007712 if (!VTableGV) {
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007713 VTableGV =
7714 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false,
7715 llvm::GlobalValue::ExternalLinkage, nullptr,
7716 VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007717 if (CGM.getTriple().isOSBinFormatCOFF())
7718 VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
7719 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007720
Chris Lattnerece04092012-02-07 00:39:47 +00007721 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
John McCall176f8922016-11-30 02:39:18 +00007722 ConstantInitBuilder builder(CGM);
7723 auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
Ahmed Bougacha5d0199a2017-11-17 19:46:47 +00007724 values.add(
7725 llvm::ConstantExpr::getInBoundsGetElementPtr(VTableGV->getValueType(),
7726 VTableGV, VTableIdx));
John McCalldba63a72016-11-30 23:54:50 +00007727 values.add(GetClassName(ClassName));
7728 values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007729
John McCalldba63a72016-11-30 23:54:50 +00007730 llvm::GlobalValue::LinkageTypes L = IsForDefinition
Rafael Espindola554256c2014-02-26 22:25:45 +00007731 ? llvm::GlobalValue::ExternalLinkage
7732 : llvm::GlobalValue::WeakAnyLinkage;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007733 if (Entry) {
John McCall176f8922016-11-30 02:39:18 +00007734 values.finishAndSetAsInitializer(Entry);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007735 Entry->setAlignment(CGM.getPointerAlign().getAsAlign());
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007736 } else {
John McCall176f8922016-11-30 02:39:18 +00007737 Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName,
7738 CGM.getPointerAlign(),
7739 /*constant*/ false,
7740 L);
Rafael Espindolab7350042018-03-01 00:35:47 +00007741 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
7742 CGM.setGVProperties(Entry, ID);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007743 }
Rafael Espindola554256c2014-02-26 22:25:45 +00007744 assert(Entry->getLinkage() == L);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007745
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007746 if (!CGM.getTriple().isOSBinFormatCOFF())
7747 if (ID->getVisibility() == HiddenVisibility)
7748 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007749
John McCalldba63a72016-11-30 23:54:50 +00007750 if (IsForDefinition)
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00007751 if (CGM.getTriple().isOSBinFormatMachO())
7752 Entry->setSection("__DATA,__objc_const");
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007753
7754 return Entry;
7755}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007756
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00007757/* *** */
7758
Daniel Dunbarb036db82008-08-13 03:21:16 +00007759CodeGen::CGObjCRuntime *
7760CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall5fb5df92012-06-20 06:18:46 +00007761 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7762 case ObjCRuntime::FragileMacOSX:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007763 return new CGObjCMac(CGM);
John McCall5fb5df92012-06-20 06:18:46 +00007764
7765 case ObjCRuntime::MacOSX:
7766 case ObjCRuntime::iOS:
Tim Northover756447a2015-10-30 16:30:36 +00007767 case ObjCRuntime::WatchOS:
John McCall5fb5df92012-06-20 06:18:46 +00007768 return new CGObjCNonFragileABIMac(CGM);
7769
David Chisnallb601c962012-07-03 20:49:52 +00007770 case ObjCRuntime::GNUstep:
7771 case ObjCRuntime::GCC:
John McCall775086e2012-07-12 02:07:58 +00007772 case ObjCRuntime::ObjFW:
John McCall5fb5df92012-06-20 06:18:46 +00007773 llvm_unreachable("these runtimes are not Mac runtimes");
7774 }
7775 llvm_unreachable("bad runtime");
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007776}