blob: f36c28a85a68fc00ba0dfb8233056e529112bc92 [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"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000019#include "clang/AST/ASTContext.h"
Reid Kleckner98031782019-12-09 16:11:56 -080020#include "clang/AST/Attr.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"
Reid Kleckner98031782019-12-09 16:11:56 -080028#include "clang/CodeGen/ConstantInitBuilder.h"
Justin Lebar5e83dfe2016-10-21 21:45:01 +000029#include "llvm/ADT/CachedHashString.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000030#include "llvm/ADT/DenseSet.h"
31#include "llvm/ADT/SetVector.h"
32#include "llvm/ADT/SmallPtrSet.h"
33#include "llvm/ADT/SmallString.h"
Chandler Carruthffd55512013-01-02 11:45:17 +000034#include "llvm/IR/DataLayout.h"
35#include "llvm/IR/InlineAsm.h"
36#include "llvm/IR/IntrinsicInst.h"
37#include "llvm/IR/LLVMContext.h"
38#include "llvm/IR/Module.h"
Akira Hatanaka2ec36f02018-08-17 15:46:07 +000039#include "llvm/Support/ScopedPrinter.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000040#include "llvm/Support/raw_ostream.h"
Torok Edwindb714922009-08-24 13:25:12 +000041#include <cstdio>
Daniel Dunbar303e2c22008-08-11 02:45:11 +000042
43using namespace clang;
Daniel Dunbar41cf9de2008-09-09 01:06:48 +000044using namespace CodeGen;
Daniel Dunbar303e2c22008-08-11 02:45:11 +000045
46namespace {
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000047
Daniel Dunbar59e476b2009-08-03 17:06:42 +000048// FIXME: We should find a nicer way to make the labels for metadata, string
49// concatenation is lame.
Daniel Dunbarb036db82008-08-13 03:21:16 +000050
Fariborz Jahanian279eda62009-01-21 22:04:16 +000051class ObjCCommonTypesHelper {
Owen Anderson170229f2009-07-14 23:10:40 +000052protected:
53 llvm::LLVMContext &VMContext;
Daniel Dunbar59e476b2009-08-03 17:06:42 +000054
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000055private:
John McCall9dc0db22011-05-15 01:53:33 +000056 // The types of these functions don't really matter because we
57 // should always bitcast before calling them.
58
59 /// id objc_msgSend (id, SEL, ...)
Fangrui Song6907ce22018-07-30 19:24:48 +000060 ///
John McCall9dc0db22011-05-15 01:53:33 +000061 /// The default messenger, used for sends whose ABI is unchanged from
62 /// the all-integer/pointer case.
James Y Knight9871db02019-02-05 16:42:33 +000063 llvm::FunctionCallee getMessageSendFn() const {
John McCall31168b02011-06-15 23:02:42 +000064 // Add the non-lazy-bind attribute, since objc_msgSend is likely to
65 // be called a lot.
Chris Lattnera5f58b02011-07-09 17:41:47 +000066 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Reid Klecknerde864822017-03-21 16:57:30 +000067 return CGM.CreateRuntimeFunction(
68 llvm::FunctionType::get(ObjectPtrTy, params, true), "objc_msgSend",
69 llvm::AttributeList::get(CGM.getLLVMContext(),
70 llvm::AttributeList::FunctionIndex,
71 llvm::Attribute::NonLazyBind));
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000072 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000073
John McCall9dc0db22011-05-15 01:53:33 +000074 /// void objc_msgSend_stret (id, SEL, ...)
75 ///
76 /// The messenger used when the return value is an aggregate returned
77 /// by indirect reference in the first argument, and therefore the
78 /// self and selector parameters are shifted over by one.
James Y Knight9871db02019-02-05 16:42:33 +000079 llvm::FunctionCallee getMessageSendStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000080 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +000081 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
82 params, true),
83 "objc_msgSend_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000084 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000085
John McCall9dc0db22011-05-15 01:53:33 +000086 /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
87 ///
88 /// The messenger used when the return value is returned on the x87
89 /// floating-point stack; without a special entrypoint, the nil case
90 /// would be unbalanced.
James Y Knight9871db02019-02-05 16:42:33 +000091 llvm::FunctionCallee getMessageSendFpretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000092 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Chris Lattnerece04092012-02-07 00:39:47 +000093 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
94 params, true),
John McCall9dc0db22011-05-15 01:53:33 +000095 "objc_msgSend_fpret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000096 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000097
Anders Carlsson2f1a6c32011-10-31 16:27:11 +000098 /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
99 ///
100 /// The messenger used when the return value is returned in two values on the
101 /// x87 floating point stack; without a special entrypoint, the nil case
102 /// would be unbalanced. Only used on 64-bit X86.
James Y Knight9871db02019-02-05 16:42:33 +0000103 llvm::FunctionCallee getMessageSendFp2retFn() const {
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000104 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
105 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
Serge Guelton1d993272017-05-09 19:31:30 +0000106 llvm::Type *resultType =
107 llvm::StructType::get(longDoubleType, longDoubleType);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000108
109 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
110 params, true),
111 "objc_msgSend_fp2ret");
112 }
113
John McCall9dc0db22011-05-15 01:53:33 +0000114 /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
115 ///
116 /// The messenger used for super calls, which have different dispatch
117 /// semantics. The class passed is the superclass of the current
118 /// class.
James Y Knight9871db02019-02-05 16:42:33 +0000119 llvm::FunctionCallee getMessageSendSuperFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000120 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000121 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000122 params, true),
123 "objc_msgSendSuper");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000124 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000125
John McCall9dc0db22011-05-15 01:53:33 +0000126 /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
127 ///
128 /// A slightly different messenger used for super calls. The class
129 /// passed is the current class.
James Y Knight9871db02019-02-05 16:42:33 +0000130 llvm::FunctionCallee getMessageSendSuperFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000131 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000132 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000133 params, true),
134 "objc_msgSendSuper2");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000135 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000136
John McCall9dc0db22011-05-15 01:53:33 +0000137 /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
138 /// SEL op, ...)
139 ///
140 /// The messenger used for super calls which return an aggregate indirectly.
James Y Knight9871db02019-02-05 16:42:33 +0000141 llvm::FunctionCallee getMessageSendSuperStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000142 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000143 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000144 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000145 "objc_msgSendSuper_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000146 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000147
John McCall9dc0db22011-05-15 01:53:33 +0000148 /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
149 /// SEL op, ...)
150 ///
151 /// objc_msgSendSuper_stret with the super2 semantics.
James Y Knight9871db02019-02-05 16:42:33 +0000152 llvm::FunctionCallee getMessageSendSuperStretFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000153 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000154 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000155 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000156 "objc_msgSendSuper2_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000157 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000158
James Y Knight9871db02019-02-05 16:42:33 +0000159 llvm::FunctionCallee getMessageSendSuperFpretFn() const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000160 // There is no objc_msgSendSuper_fpret? How can that work?
161 return getMessageSendSuperFn();
162 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000163
James Y Knight9871db02019-02-05 16:42:33 +0000164 llvm::FunctionCallee getMessageSendSuperFpretFn2() const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000165 // There is no objc_msgSendSuper_fpret? How can that work?
166 return getMessageSendSuperFn2();
167 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000168
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000169protected:
170 CodeGen::CodeGenModule &CGM;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000171
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000172public:
John McCall176f8922016-11-30 02:39:18 +0000173 llvm::IntegerType *ShortTy, *IntTy, *LongTy;
174 llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
Tim Northover238b5082014-03-29 13:42:40 +0000175 llvm::Type *IvarOffsetVarTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000176
Daniel Dunbar5d715592008-08-12 05:28:47 +0000177 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
John McCall176f8922016-11-30 02:39:18 +0000178 llvm::PointerType *ObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000179
Fariborz Jahanian406b1172008-11-18 20:18:11 +0000180 /// PtrObjectPtrTy - LLVM type for id *
John McCall176f8922016-11-30 02:39:18 +0000181 llvm::PointerType *PtrObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000182
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000183 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
John McCall176f8922016-11-30 02:39:18 +0000184 llvm::PointerType *SelectorPtrTy;
Fangrui Song6907ce22018-07-30 19:24:48 +0000185
Douglas Gregor020de322012-01-17 18:36:30 +0000186private:
Daniel Dunbarb036db82008-08-13 03:21:16 +0000187 /// ProtocolPtrTy - LLVM type for external protocol handles
188 /// (typeof(Protocol))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000189 llvm::Type *ExternalProtocolPtrTy;
Fangrui Song6907ce22018-07-30 19:24:48 +0000190
Douglas Gregor020de322012-01-17 18:36:30 +0000191public:
192 llvm::Type *getExternalProtocolPtrTy() {
193 if (!ExternalProtocolPtrTy) {
194 // FIXME: It would be nice to unify this with the opaque type, so that the
195 // IR comes out a bit cleaner.
196 CodeGen::CodeGenTypes &Types = CGM.getTypes();
197 ASTContext &Ctx = CGM.getContext();
198 llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
199 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
200 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000201
Douglas Gregor020de322012-01-17 18:36:30 +0000202 return ExternalProtocolPtrTy;
203 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000204
Daniel Dunbarc722b852008-08-30 03:02:31 +0000205 // SuperCTy - clang type for struct objc_super.
206 QualType SuperCTy;
207 // SuperPtrCTy - clang type for struct objc_super *.
208 QualType SuperPtrCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000209
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000210 /// SuperTy - LLVM type for struct objc_super.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000211 llvm::StructType *SuperTy;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +0000212 /// SuperPtrTy - LLVM type for struct objc_super *.
John McCall176f8922016-11-30 02:39:18 +0000213 llvm::PointerType *SuperPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000214
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000215 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
216 /// in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000217 llvm::StructType *PropertyTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000218
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000219 /// PropertyListTy - LLVM type for struct objc_property_list
220 /// (_prop_list_t in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000221 llvm::StructType *PropertyListTy;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000222 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
John McCall176f8922016-11-30 02:39:18 +0000223 llvm::PointerType *PropertyListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000224
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000225 // MethodTy - LLVM type for struct objc_method.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000226 llvm::StructType *MethodTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000227
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000228 /// CacheTy - LLVM type for struct objc_cache.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000229 llvm::Type *CacheTy;
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000230 /// CachePtrTy - LLVM type for struct objc_cache *.
John McCall176f8922016-11-30 02:39:18 +0000231 llvm::PointerType *CachePtrTy;
Fangrui Song6907ce22018-07-30 19:24:48 +0000232
James Y Knight9871db02019-02-05 16:42:33 +0000233 llvm::FunctionCallee getGetPropertyFn() {
Chris Lattnerce8754e2009-04-22 02:44:54 +0000234 CodeGen::CodeGenTypes &Types = CGM.getTypes();
235 ASTContext &Ctx = CGM.getContext();
236 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
John McCall2da83a32010-02-26 00:48:12 +0000237 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
238 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Benjamin Kramer30934732016-07-02 11:41:41 +0000239 CanQualType Params[] = {
240 IdType, SelType,
241 Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), Ctx.BoolTy};
Chris Lattner2192fe52011-07-18 04:24:23 +0000242 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000243 Types.GetFunctionType(
244 Types.arrangeBuiltinFunctionDeclaration(IdType, Params));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000245 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
246 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000247
James Y Knight9871db02019-02-05 16:42:33 +0000248 llvm::FunctionCallee getSetPropertyFn() {
Chris Lattnerce8754e2009-04-22 02:44:54 +0000249 CodeGen::CodeGenTypes &Types = CGM.getTypes();
250 ASTContext &Ctx = CGM.getContext();
251 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
John McCall2da83a32010-02-26 00:48:12 +0000252 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
253 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Benjamin Kramer30934732016-07-02 11:41:41 +0000254 CanQualType Params[] = {
255 IdType,
256 SelType,
257 Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(),
258 IdType,
259 Ctx.BoolTy,
260 Ctx.BoolTy};
Chris Lattner2192fe52011-07-18 04:24:23 +0000261 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000262 Types.GetFunctionType(
263 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000264 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
265 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000266
James Y Knight9871db02019-02-05 16:42:33 +0000267 llvm::FunctionCallee getOptimizedSetPropertyFn(bool atomic, bool copy) {
Ted Kremeneke65b0862012-03-06 20:05:56 +0000268 CodeGen::CodeGenTypes &Types = CGM.getTypes();
269 ASTContext &Ctx = CGM.getContext();
Fangrui Song6907ce22018-07-30 19:24:48 +0000270 // void objc_setProperty_atomic(id self, SEL _cmd,
Ted Kremeneke65b0862012-03-06 20:05:56 +0000271 // id newValue, ptrdiff_t offset);
Fangrui Song6907ce22018-07-30 19:24:48 +0000272 // void objc_setProperty_nonatomic(id self, SEL _cmd,
Ted Kremeneke65b0862012-03-06 20:05:56 +0000273 // id newValue, ptrdiff_t offset);
Fangrui Song6907ce22018-07-30 19:24:48 +0000274 // void objc_setProperty_atomic_copy(id self, SEL _cmd,
Ted Kremeneke65b0862012-03-06 20:05:56 +0000275 // id newValue, ptrdiff_t offset);
Fangrui Song6907ce22018-07-30 19:24:48 +0000276 // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
Ted Kremeneke65b0862012-03-06 20:05:56 +0000277 // id newValue, ptrdiff_t offset);
Fangrui Song6907ce22018-07-30 19:24:48 +0000278
Ted Kremeneke65b0862012-03-06 20:05:56 +0000279 SmallVector<CanQualType,4> Params;
280 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
281 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
282 Params.push_back(IdType);
283 Params.push_back(SelType);
284 Params.push_back(IdType);
285 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
286 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000287 Types.GetFunctionType(
288 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Ted Kremeneke65b0862012-03-06 20:05:56 +0000289 const char *name;
290 if (atomic && copy)
291 name = "objc_setProperty_atomic_copy";
292 else if (atomic && !copy)
293 name = "objc_setProperty_atomic";
294 else if (!atomic && copy)
295 name = "objc_setProperty_nonatomic_copy";
296 else
297 name = "objc_setProperty_nonatomic";
Fangrui Song6907ce22018-07-30 19:24:48 +0000298
Ted Kremeneke65b0862012-03-06 20:05:56 +0000299 return CGM.CreateRuntimeFunction(FTy, name);
300 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000301
James Y Knight9871db02019-02-05 16:42:33 +0000302 llvm::FunctionCallee getCopyStructFn() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000303 CodeGen::CodeGenTypes &Types = CGM.getTypes();
304 ASTContext &Ctx = CGM.getContext();
305 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000306 SmallVector<CanQualType,5> Params;
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000307 Params.push_back(Ctx.VoidPtrTy);
308 Params.push_back(Ctx.VoidPtrTy);
Saleem Abdulrasool91d9bfc2017-06-17 17:30:31 +0000309 Params.push_back(Ctx.getSizeType());
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000310 Params.push_back(Ctx.BoolTy);
311 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000312 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000313 Types.GetFunctionType(
314 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000315 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
316 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000317
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000318 /// This routine declares and returns address of:
319 /// void objc_copyCppObjectAtomic(
Fangrui Song6907ce22018-07-30 19:24:48 +0000320 /// void *dest, const void *src,
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000321 /// void (*copyHelper) (void *dest, const void *source));
James Y Knight9871db02019-02-05 16:42:33 +0000322 llvm::FunctionCallee getCppAtomicObjectFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000323 CodeGen::CodeGenTypes &Types = CGM.getTypes();
324 ASTContext &Ctx = CGM.getContext();
325 /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
326 SmallVector<CanQualType,3> Params;
327 Params.push_back(Ctx.VoidPtrTy);
328 Params.push_back(Ctx.VoidPtrTy);
329 Params.push_back(Ctx.VoidPtrTy);
330 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000331 Types.GetFunctionType(
332 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000333 return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
334 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000335
James Y Knight9871db02019-02-05 16:42:33 +0000336 llvm::FunctionCallee getEnumerationMutationFn() {
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000337 CodeGen::CodeGenTypes &Types = CGM.getTypes();
338 ASTContext &Ctx = CGM.getContext();
Chris Lattnerce8754e2009-04-22 02:44:54 +0000339 // void objc_enumerationMutation (id)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000340 SmallVector<CanQualType,1> Params;
John McCall2da83a32010-02-26 00:48:12 +0000341 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Chris Lattner2192fe52011-07-18 04:24:23 +0000342 llvm::FunctionType *FTy =
John McCallc56a8b32016-03-11 04:30:31 +0000343 Types.GetFunctionType(
344 Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000345 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
346 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000347
James Y Knight9871db02019-02-05 16:42:33 +0000348 llvm::FunctionCallee getLookUpClassFn() {
Douglas Gregor24ae22c2016-04-01 23:23:52 +0000349 CodeGen::CodeGenTypes &Types = CGM.getTypes();
350 ASTContext &Ctx = CGM.getContext();
351 // Class objc_lookUpClass (const char *)
352 SmallVector<CanQualType,1> Params;
353 Params.push_back(
354 Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst())));
355 llvm::FunctionType *FTy =
356 Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration(
357 Ctx.getCanonicalType(Ctx.getObjCClassType()),
358 Params));
359 return CGM.CreateRuntimeFunction(FTy, "objc_lookUpClass");
360 }
361
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000362 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
James Y Knight9871db02019-02-05 16:42:33 +0000363 llvm::FunctionCallee getGcReadWeakFn() {
Chris Lattnerce8754e2009-04-22 02:44:54 +0000364 // id objc_read_weak (id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000365 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000366 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000367 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000368 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000369 }
370
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000371 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
James Y Knight9871db02019-02-05 16:42:33 +0000372 llvm::FunctionCallee getGcAssignWeakFn() {
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000373 // id objc_assign_weak (id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000374 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000375 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000376 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000377 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
378 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000379
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000380 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
James Y Knight9871db02019-02-05 16:42:33 +0000381 llvm::FunctionCallee getGcAssignGlobalFn() {
Chris Lattner0a696a422009-04-22 02:38:11 +0000382 // id objc_assign_global(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000383 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000384 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000385 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000386 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
387 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000388
Fariborz Jahanian217af242010-07-20 20:30:03 +0000389 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
James Y Knight9871db02019-02-05 16:42:33 +0000390 llvm::FunctionCallee getGcAssignThreadLocalFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000391 // id objc_assign_threadlocal(id src, id * dest)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000392 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian217af242010-07-20 20:30:03 +0000393 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000394 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian217af242010-07-20 20:30:03 +0000395 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
396 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000397
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000398 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
James Y Knight9871db02019-02-05 16:42:33 +0000399 llvm::FunctionCallee getGcAssignIvarFn() {
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000400 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000401 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
402 CGM.PtrDiffTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000403 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000404 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000405 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
406 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000407
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000408 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
James Y Knight9871db02019-02-05 16:42:33 +0000409 llvm::FunctionCallee GcMemmoveCollectableFn() {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000410 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000411 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
John McCall9dc0db22011-05-15 01:53:33 +0000412 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000413 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
414 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000415
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000416 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
James Y Knight9871db02019-02-05 16:42:33 +0000417 llvm::FunctionCallee getGcAssignStrongCastFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000418 // id objc_assign_strongCast(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000419 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000420 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000421 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000422 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
423 }
Anders Carlsson9ab53d12009-02-16 22:59:18 +0000424
425 /// ExceptionThrowFn - LLVM objc_exception_throw function.
James Y Knight9871db02019-02-05 16:42:33 +0000426 llvm::FunctionCallee getExceptionThrowFn() {
Chris Lattner0a696a422009-04-22 02:38:11 +0000427 // void objc_exception_throw(id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000428 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000429 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000430 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000431 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
432 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000433
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000434 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
James Y Knight9871db02019-02-05 16:42:33 +0000435 llvm::FunctionCallee getExceptionRethrowFn() {
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000436 // void objc_exception_rethrow(void)
John McCall9dc0db22011-05-15 01:53:33 +0000437 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000438 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
439 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000440
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000441 /// SyncEnterFn - LLVM object_sync_enter function.
James Y Knight9871db02019-02-05 16:42:33 +0000442 llvm::FunctionCallee getSyncEnterFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000443 // int objc_sync_enter (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000444 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerdcceee72009-04-06 16:53:45 +0000445 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000446 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000447 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
448 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000449
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000450 /// SyncExitFn - LLVM object_sync_exit function.
James Y Knight9871db02019-02-05 16:42:33 +0000451 llvm::FunctionCallee getSyncExitFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000452 // int objc_sync_exit (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000453 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000454 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000455 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000456 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
457 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000458
James Y Knight9871db02019-02-05 16:42:33 +0000459 llvm::FunctionCallee getSendFn(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000460 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
461 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000462
James Y Knight9871db02019-02-05 16:42:33 +0000463 llvm::FunctionCallee getSendFn2(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000464 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
465 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000466
James Y Knight9871db02019-02-05 16:42:33 +0000467 llvm::FunctionCallee getSendStretFn(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000468 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
469 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000470
James Y Knight9871db02019-02-05 16:42:33 +0000471 llvm::FunctionCallee getSendStretFn2(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000472 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
473 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000474
James Y Knight9871db02019-02-05 16:42:33 +0000475 llvm::FunctionCallee getSendFpretFn(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000476 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
477 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000478
James Y Knight9871db02019-02-05 16:42:33 +0000479 llvm::FunctionCallee getSendFpretFn2(bool IsSuper) const {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000480 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
481 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000482
James Y Knight9871db02019-02-05 16:42:33 +0000483 llvm::FunctionCallee getSendFp2retFn(bool IsSuper) const {
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000484 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
485 }
486
James Y Knight9871db02019-02-05 16:42:33 +0000487 llvm::FunctionCallee getSendFp2RetFn2(bool IsSuper) const {
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000488 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
489 }
490
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000491 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000492};
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000493
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000494/// ObjCTypesHelper - Helper class that encapsulates lazy
495/// construction of varies types used during ObjC generation.
496class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000497public:
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000498 /// SymtabTy - LLVM type for struct objc_symtab.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000499 llvm::StructType *SymtabTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000500 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
John McCall176f8922016-11-30 02:39:18 +0000501 llvm::PointerType *SymtabPtrTy;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000502 /// ModuleTy - LLVM type for struct objc_module.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000503 llvm::StructType *ModuleTy;
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000504
Daniel Dunbarb036db82008-08-13 03:21:16 +0000505 /// ProtocolTy - LLVM type for struct objc_protocol.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000506 llvm::StructType *ProtocolTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000507 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
John McCall176f8922016-11-30 02:39:18 +0000508 llvm::PointerType *ProtocolPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000509 /// ProtocolExtensionTy - LLVM type for struct
510 /// objc_protocol_extension.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000511 llvm::StructType *ProtocolExtensionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000512 /// ProtocolExtensionTy - LLVM type for struct
513 /// objc_protocol_extension *.
John McCall176f8922016-11-30 02:39:18 +0000514 llvm::PointerType *ProtocolExtensionPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000515 /// MethodDescriptionTy - LLVM type for struct
516 /// objc_method_description.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000517 llvm::StructType *MethodDescriptionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000518 /// MethodDescriptionListTy - LLVM type for struct
519 /// objc_method_description_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000520 llvm::StructType *MethodDescriptionListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000521 /// MethodDescriptionListPtrTy - LLVM type for struct
522 /// objc_method_description_list *.
John McCall176f8922016-11-30 02:39:18 +0000523 llvm::PointerType *MethodDescriptionListPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000524 /// ProtocolListTy - LLVM type for struct objc_property_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000525 llvm::StructType *ProtocolListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000526 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
John McCall176f8922016-11-30 02:39:18 +0000527 llvm::PointerType *ProtocolListPtrTy;
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000528 /// CategoryTy - LLVM type for struct objc_category.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000529 llvm::StructType *CategoryTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000530 /// ClassTy - LLVM type for struct objc_class.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000531 llvm::StructType *ClassTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000532 /// ClassPtrTy - LLVM type for struct objc_class *.
John McCall176f8922016-11-30 02:39:18 +0000533 llvm::PointerType *ClassPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000534 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000535 llvm::StructType *ClassExtensionTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000536 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
John McCall176f8922016-11-30 02:39:18 +0000537 llvm::PointerType *ClassExtensionPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000538 // IvarTy - LLVM type for struct objc_ivar.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000539 llvm::StructType *IvarTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000540 /// IvarListTy - LLVM type for struct objc_ivar_list.
John McCall176f8922016-11-30 02:39:18 +0000541 llvm::StructType *IvarListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000542 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
John McCall176f8922016-11-30 02:39:18 +0000543 llvm::PointerType *IvarListPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000544 /// MethodListTy - LLVM type for struct objc_method_list.
John McCall176f8922016-11-30 02:39:18 +0000545 llvm::StructType *MethodListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000546 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
John McCall176f8922016-11-30 02:39:18 +0000547 llvm::PointerType *MethodListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000548
Anders Carlsson9ff22482008-09-09 10:10:21 +0000549 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
John McCall176f8922016-11-30 02:39:18 +0000550 llvm::StructType *ExceptionDataTy;
Fangrui Song6907ce22018-07-30 19:24:48 +0000551
Anders Carlsson9ff22482008-09-09 10:10:21 +0000552 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
James Y Knight9871db02019-02-05 16:42:33 +0000553 llvm::FunctionCallee getExceptionTryEnterFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000554 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000555 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000556 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000557 "objc_exception_try_enter");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000558 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000559
560 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
James Y Knight9871db02019-02-05 16:42:33 +0000561 llvm::FunctionCallee getExceptionTryExitFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000562 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000563 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000564 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000565 "objc_exception_try_exit");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000566 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000567
568 /// ExceptionExtractFn - LLVM objc_exception_extract function.
James Y Knight9871db02019-02-05 16:42:33 +0000569 llvm::FunctionCallee getExceptionExtractFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000570 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000571 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000572 params, false),
Chris Lattnerc6406db2009-04-22 02:26:14 +0000573 "objc_exception_extract");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000574 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000575
Anders Carlsson9ff22482008-09-09 10:10:21 +0000576 /// ExceptionMatchFn - LLVM objc_exception_match function.
James Y Knight9871db02019-02-05 16:42:33 +0000577 llvm::FunctionCallee getExceptionMatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000578 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000579 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000580 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000581 "objc_exception_match");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000582 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000583
Anders Carlsson9ff22482008-09-09 10:10:21 +0000584 /// SetJmpFn - LLVM _setjmp function.
James Y Knight9871db02019-02-05 16:42:33 +0000585 llvm::FunctionCallee getSetJmpFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000586 // This is specifically the prototype for x86.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000587 llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
Reid Klecknerde864822017-03-21 16:57:30 +0000588 return CGM.CreateRuntimeFunction(
589 llvm::FunctionType::get(CGM.Int32Ty, params, false), "_setjmp",
590 llvm::AttributeList::get(CGM.getLLVMContext(),
591 llvm::AttributeList::FunctionIndex,
592 llvm::Attribute::NonLazyBind));
Chris Lattnerc6406db2009-04-22 02:26:14 +0000593 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000594
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000595public:
596 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000597};
598
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000599/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000600/// modern abi
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000601class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000602public:
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000603 // MethodListnfABITy - LLVM for struct _method_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000604 llvm::StructType *MethodListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000605
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000606 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
John McCall176f8922016-11-30 02:39:18 +0000607 llvm::PointerType *MethodListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000608
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000609 // ProtocolnfABITy = LLVM for struct _protocol_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000610 llvm::StructType *ProtocolnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000611
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000612 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
John McCall176f8922016-11-30 02:39:18 +0000613 llvm::PointerType *ProtocolnfABIPtrTy;
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000614
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000615 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
Chris Lattnera5f58b02011-07-09 17:41:47 +0000616 llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000617
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000618 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
John McCall176f8922016-11-30 02:39:18 +0000619 llvm::PointerType *ProtocolListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000620
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000621 // ClassnfABITy - LLVM for struct _class_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000622 llvm::StructType *ClassnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000623
Fariborz Jahanian71394042009-01-23 23:53:38 +0000624 // ClassnfABIPtrTy - LLVM for struct _class_t*
John McCall176f8922016-11-30 02:39:18 +0000625 llvm::PointerType *ClassnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000626
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000627 // IvarnfABITy - LLVM for struct _ivar_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000628 llvm::StructType *IvarnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000629
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000630 // IvarListnfABITy - LLVM for struct _ivar_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000631 llvm::StructType *IvarListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000632
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000633 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
John McCall176f8922016-11-30 02:39:18 +0000634 llvm::PointerType *IvarListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000635
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000636 // ClassRonfABITy - LLVM for struct _class_ro_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000637 llvm::StructType *ClassRonfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000638
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000639 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
John McCall176f8922016-11-30 02:39:18 +0000640 llvm::PointerType *ImpnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000641
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000642 // CategorynfABITy - LLVM for struct _category_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000643 llvm::StructType *CategorynfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000644
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000645 // New types for nonfragile abi messaging.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000646
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000647 // MessageRefTy - LLVM for:
648 // struct _message_ref_t {
649 // IMP messenger;
650 // SEL name;
651 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000652 llvm::StructType *MessageRefTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000653 // MessageRefCTy - clang type for struct _message_ref_t
654 QualType MessageRefCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000655
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000656 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000657 llvm::Type *MessageRefPtrTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000658 // MessageRefCPtrTy - clang type for struct _message_ref_t*
659 QualType MessageRefCPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000660
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000661 // SuperMessageRefTy - LLVM for:
662 // struct _super_message_ref_t {
663 // SUPER_IMP messenger;
664 // SEL name;
665 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000666 llvm::StructType *SuperMessageRefTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000667
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000668 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
John McCall176f8922016-11-30 02:39:18 +0000669 llvm::PointerType *SuperMessageRefPtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000670
James Y Knight9871db02019-02-05 16:42:33 +0000671 llvm::FunctionCallee getMessageSendFixupFn() {
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000672 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000673 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000674 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000675 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000676 "objc_msgSend_fixup");
677 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000678
James Y Knight9871db02019-02-05 16:42:33 +0000679 llvm::FunctionCallee getMessageSendFpretFixupFn() {
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000680 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000681 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000682 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000683 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000684 "objc_msgSend_fpret_fixup");
685 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000686
James Y Knight9871db02019-02-05 16:42:33 +0000687 llvm::FunctionCallee getMessageSendStretFixupFn() {
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000688 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000689 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000690 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000691 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000692 "objc_msgSend_stret_fixup");
693 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000694
James Y Knight9871db02019-02-05 16:42:33 +0000695 llvm::FunctionCallee getMessageSendSuper2FixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000696 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000697 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000698 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000699 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000700 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000701 "objc_msgSendSuper2_fixup");
702 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000703
James Y Knight9871db02019-02-05 16:42:33 +0000704 llvm::FunctionCallee getMessageSendSuper2StretFixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000705 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000706 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000707 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000708 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000709 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000710 "objc_msgSendSuper2_stret_fixup");
711 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000712
James Y Knight9871db02019-02-05 16:42:33 +0000713 llvm::FunctionCallee getObjCEndCatchFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000714 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000715 "objc_end_catch");
Chris Lattnera7c00b42009-04-22 02:15:23 +0000716 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000717
James Y Knight9871db02019-02-05 16:42:33 +0000718 llvm::FunctionCallee getObjCBeginCatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000719 llvm::Type *params[] = { Int8PtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000720 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000721 params, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000722 "objc_begin_catch");
723 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +0000724
John McCall2c91c3b2019-05-30 04:09:01 +0000725 /// Class objc_loadClassref (void *)
726 ///
727 /// Loads from a classref. For Objective-C stub classes, this invokes the
728 /// initialization callback stored inside the stub. For all other classes
729 /// this simply dereferences the pointer.
730 llvm::FunctionCallee getLoadClassrefFn() const {
731 // Add the non-lazy-bind attribute, since objc_loadClassref is likely to
732 // be called a lot.
733 //
734 // Also it is safe to make it readnone, since we never load or store the
735 // classref except by calling this function.
736 llvm::Type *params[] = { Int8PtrPtrTy };
737 llvm::FunctionCallee F = CGM.CreateRuntimeFunction(
738 llvm::FunctionType::get(ClassnfABIPtrTy, params, false),
739 "objc_loadClassref",
740 llvm::AttributeList::get(CGM.getLLVMContext(),
741 llvm::AttributeList::FunctionIndex,
742 {llvm::Attribute::NonLazyBind,
743 llvm::Attribute::ReadNone,
744 llvm::Attribute::NoUnwind}));
745 if (!CGM.getTriple().isOSBinFormatCOFF())
746 cast<llvm::Function>(F.getCallee())->setLinkage(
747 llvm::Function::ExternalWeakLinkage);
748
749 return F;
750 }
751
Chris Lattnera5f58b02011-07-09 17:41:47 +0000752 llvm::StructType *EHTypeTy;
753 llvm::Type *EHTypePtrTy;
Fangrui Song6907ce22018-07-30 19:24:48 +0000754
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000755 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000756};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000757
Saleem Abdulrasool271106c2016-09-16 23:41:13 +0000758enum class ObjCLabelType {
759 ClassName,
760 MethodVarName,
761 MethodVarType,
762 PropertyName,
763};
764
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000765class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000766public:
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000767 class SKIP_SCAN {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000768 public:
769 unsigned skip;
770 unsigned scan;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000771 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000772 : skip(_skip), scan(_scan) {}
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000773 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000774
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000775 /// opcode for captured block variables layout 'instructions'.
776 /// In the following descriptions, 'I' is the value of the immediate field.
777 /// (field following the opcode).
778 ///
779 enum BLOCK_LAYOUT_OPCODE {
780 /// An operator which affects how the following layout should be
781 /// interpreted.
782 /// I == 0: Halt interpretation and treat everything else as
783 /// a non-pointer. Note that this instruction is equal
784 /// to '\0'.
785 /// I != 0: Currently unused.
786 BLOCK_LAYOUT_OPERATOR = 0,
Fangrui Song6907ce22018-07-30 19:24:48 +0000787
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000788 /// The next I+1 bytes do not contain a value of object pointer type.
789 /// Note that this can leave the stream unaligned, meaning that
790 /// subsequent word-size instructions do not begin at a multiple of
791 /// the pointer size.
792 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
Fangrui Song6907ce22018-07-30 19:24:48 +0000793
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000794 /// The next I+1 words do not contain a value of object pointer type.
795 /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
796 /// when the required skip quantity is a multiple of the pointer size.
797 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
Fangrui Song6907ce22018-07-30 19:24:48 +0000798
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000799 /// The next I+1 words are __strong pointers to Objective-C
800 /// objects or blocks.
801 BLOCK_LAYOUT_STRONG = 3,
Fangrui Song6907ce22018-07-30 19:24:48 +0000802
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000803 /// The next I+1 words are pointers to __block variables.
804 BLOCK_LAYOUT_BYREF = 4,
Fangrui Song6907ce22018-07-30 19:24:48 +0000805
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000806 /// The next I+1 words are __weak pointers to Objective-C
807 /// objects or blocks.
808 BLOCK_LAYOUT_WEAK = 5,
Fangrui Song6907ce22018-07-30 19:24:48 +0000809
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000810 /// The next I+1 words are __unsafe_unretained pointers to
811 /// Objective-C objects or blocks.
812 BLOCK_LAYOUT_UNRETAINED = 6
Fangrui Song6907ce22018-07-30 19:24:48 +0000813
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000814 /// The next I+1 words are block or object pointers with some
815 /// as-yet-unspecified ownership semantics. If we add more
816 /// flavors of ownership semantics, values will be taken from
817 /// this range.
818 ///
819 /// This is included so that older tools can at least continue
820 /// processing the layout past such things.
821 //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
Fangrui Song6907ce22018-07-30 19:24:48 +0000822
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000823 /// All other opcodes are reserved. Halt interpretation and
824 /// treat everything else as opaque.
825 };
Fangrui Song6907ce22018-07-30 19:24:48 +0000826
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000827 class RUN_SKIP {
828 public:
829 enum BLOCK_LAYOUT_OPCODE opcode;
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000830 CharUnits block_var_bytepos;
831 CharUnits block_var_size;
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000832 RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000833 CharUnits BytePos = CharUnits::Zero(),
834 CharUnits Size = CharUnits::Zero())
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +0000835 : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
Fangrui Song6907ce22018-07-30 19:24:48 +0000836
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000837 // Allow sorting based on byte pos.
838 bool operator<(const RUN_SKIP &b) const {
839 return block_var_bytepos < b.block_var_bytepos;
840 }
841 };
Fangrui Song6907ce22018-07-30 19:24:48 +0000842
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000843protected:
Owen Andersonae86c192009-07-13 04:10:07 +0000844 llvm::LLVMContext &VMContext;
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000845 // FIXME! May not be needing this after all.
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000846 unsigned ObjCABI;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000847
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000848 // arc/mrr layout of captured block literal variables.
849 SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000850
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000851 /// LazySymbols - Symbols to generate a lazy reference for. See
852 /// DefinedSymbols and FinishModule().
Daniel Dunbard027a922009-09-07 00:20:42 +0000853 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000854
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000855 /// DefinedSymbols - External symbols which are defined by this
856 /// module. The symbols in this list and LazySymbols are used to add
857 /// special linker symbols which ensure that Objective-C modules are
858 /// linked properly.
Daniel Dunbard027a922009-09-07 00:20:42 +0000859 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000860
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000861 /// ClassNames - uniqued class names.
Fariborz Jahanian451b92a2014-07-16 16:16:04 +0000862 llvm::StringMap<llvm::GlobalVariable*> ClassNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000863
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000864 /// MethodVarNames - uniqued method variable names.
865 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000866
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000867 /// DefinedCategoryNames - list of category names in form Class_Category.
Justin Lebar5e83dfe2016-10-21 21:45:01 +0000868 llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames;
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000869
Daniel Dunbarb036db82008-08-13 03:21:16 +0000870 /// MethodVarTypes - uniqued method type signatures. We have to use
871 /// a StringMap here because have no other unique reference.
872 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000873
Daniel Dunbar3c76cb52008-08-26 21:51:14 +0000874 /// MethodDefinitions - map of methods which have been defined in
875 /// this translation unit.
876 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000877
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -0800878 /// DirectMethodDefinitions - map of direct methods which have been defined in
879 /// this translation unit.
880 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> DirectMethodDefinitions;
881
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000882 /// PropertyNames - uniqued method variable names.
883 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000884
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000885 /// ClassReferences - uniqued class references.
886 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000887
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000888 /// SelectorReferences - uniqued selector references.
889 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000890
Daniel Dunbarb036db82008-08-13 03:21:16 +0000891 /// Protocols - Protocols for which an objc_protocol structure has
892 /// been emitted. Forward declarations are handled by creating an
893 /// empty structure whose initializer is filled in when/if defined.
894 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000895
Daniel Dunbarc475d422008-10-29 22:36:39 +0000896 /// DefinedProtocols - Protocols which have actually been
897 /// defined. We should not need this, see FIXME in GenerateProtocol.
898 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000899
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000900 /// DefinedClasses - List of defined classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000901 SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
Fangrui Song6907ce22018-07-30 19:24:48 +0000902
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +0000903 /// ImplementedClasses - List of @implemented classes.
904 SmallVector<const ObjCInterfaceDecl*, 16> ImplementedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000905
906 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000907 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000908
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000909 /// DefinedCategories - List of defined categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000910 SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000911
John McCall2c91c3b2019-05-30 04:09:01 +0000912 /// DefinedStubCategories - List of defined categories on class stubs.
913 SmallVector<llvm::GlobalValue*, 16> DefinedStubCategories;
914
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000915 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000916 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000917
John McCallcd21d542016-11-30 23:15:55 +0000918 /// Cached reference to the class for constant strings. This value has type
919 /// int * but is actually an Obj-C class pointer.
Sanjoy Dase369bd92017-05-01 17:08:00 +0000920 llvm::WeakTrackingVH ConstantStringClassRef;
John McCallcd21d542016-11-30 23:15:55 +0000921
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000922 /// The LLVM type corresponding to NSConstantString.
John McCallcd21d542016-11-30 23:15:55 +0000923 llvm::StructType *NSConstantStringType = nullptr;
924
925 llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
926
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000927 /// GetNameForMethod - Return a name for the given method.
928 /// \param[out] NameOut - The return value.
929 void GetNameForMethod(const ObjCMethodDecl *OMD,
930 const ObjCContainerDecl *CD,
Pierre Habouzit42f9d0c2019-12-19 01:25:03 -0800931 SmallVectorImpl<char> &NameOut,
932 bool ignoreCategoryNamespace = false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000933
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000934 /// GetMethodVarName - Return a unique constant for the given
935 /// selector's name. The return value has type char *.
936 llvm::Constant *GetMethodVarName(Selector Sel);
937 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000938
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000939 /// GetMethodVarType - Return a unique constant for the given
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000940 /// method's type encoding string. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000941
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000942 // FIXME: This is a horrible name.
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000943 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
944 bool Extended = false);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000945 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000946
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000947 /// GetPropertyName - Return a unique constant for the given
948 /// name. The return value has type char *.
949 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000950
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000951 // FIXME: This can be dropped once string functions are unified.
952 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
953 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000954
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000955 /// GetClassName - Return a unique constant for the given selector's
Fariborz Jahanian451b92a2014-07-16 16:16:04 +0000956 /// runtime name (which may change via use of objc_runtime_name attribute on
957 /// class or protocol definition. The return value has type char *.
958 llvm::Constant *GetClassName(StringRef RuntimeName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000959
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000960 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
961
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000962 /// BuildIvarLayout - Builds ivar layout bitmap for the class
963 /// implementation for the __strong or __weak case.
964 ///
John McCall460ce582015-10-22 18:38:17 +0000965 /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there
966 /// are any weak ivars defined directly in the class. Meaningless unless
967 /// building a weak layout. Does not guarantee that the layout will
968 /// actually have any entries, because the ivar might be under-aligned.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000969 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
John McCall3fd13f062015-10-21 18:06:47 +0000970 CharUnits beginOffset,
971 CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +0000972 bool forStrongLayout,
973 bool hasMRCWeakIvars);
974
975 llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI,
976 CharUnits beginOffset,
977 CharUnits endOffset) {
978 return BuildIvarLayout(OI, beginOffset, endOffset, true, false);
979 }
980
981 llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI,
982 CharUnits beginOffset,
983 CharUnits endOffset,
984 bool hasMRCWeakIvars) {
985 return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
986 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000987
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000988 Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
Fangrui Song6907ce22018-07-30 19:24:48 +0000989
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000990 void UpdateRunSkipBlockVars(bool IsByref,
991 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000992 CharUnits FieldOffset,
993 CharUnits FieldSize);
Fangrui Song6907ce22018-07-30 19:24:48 +0000994
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000995 void BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000996 CharUnits BytePos, bool &HasUnion,
997 bool ByrefLayout=false);
Fangrui Song6907ce22018-07-30 19:24:48 +0000998
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000999 void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
1000 const RecordDecl *RD,
1001 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00001002 CharUnits BytePos, bool &HasUnion,
1003 bool ByrefLayout);
Fangrui Song6907ce22018-07-30 19:24:48 +00001004
Fariborz Jahanian23290b02012-11-01 18:32:55 +00001005 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
Fangrui Song6907ce22018-07-30 19:24:48 +00001006
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00001007 llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
Fangrui Song6907ce22018-07-30 19:24:48 +00001008
Fariborz Jahanian01dff422009-03-05 19:17:31 +00001009 /// GetIvarLayoutName - Returns a unique constant for the given
1010 /// ivar layout bitmap.
1011 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
1012 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001013
Fariborz Jahanian066347e2009-01-28 22:18:42 +00001014 /// EmitPropertyList - Emit the given property list. The return
1015 /// value has type PropertyListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001016 llvm::Constant *EmitPropertyList(Twine Name,
1017 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +00001018 const ObjCContainerDecl *OCD,
Manman Renad0e7912016-01-29 19:22:54 +00001019 const ObjCCommonTypesHelper &ObjCTypes,
1020 bool IsClassProperty);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001021
Fangrui Song6907ce22018-07-30 19:24:48 +00001022 /// EmitProtocolMethodTypes - Generate the array of extended method type
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001023 /// strings. The return value has type Int8PtrPtrTy.
Fangrui Song6907ce22018-07-30 19:24:48 +00001024 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
Zachary Turner41a9ee92017-10-11 23:54:34 +00001025 ArrayRef<llvm::Constant*> MethodTypes,
1026 const ObjCCommonTypesHelper &ObjCTypes);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001027
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001028 /// GetProtocolRef - Return a reference to the internal protocol
1029 /// description, creating an empty one if it has not been
1030 /// defined. The return value has type ProtocolPtrTy.
1031 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +00001032
Douglas Gregor24ae22c2016-04-01 23:23:52 +00001033 /// Return a reference to the given Class using runtime calls rather than
1034 /// by a symbol reference.
1035 llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
1036 const ObjCInterfaceDecl *ID,
1037 ObjCCommonTypesHelper &ObjCTypes);
1038
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00001039 std::string GetSectionName(StringRef Section, StringRef MachOAttributes);
1040
John McCall3fd13f062015-10-21 18:06:47 +00001041public:
Daniel Dunbar30c65362009-03-09 20:09:19 +00001042 /// CreateMetadataVar - Create a global variable with internal
1043 /// linkage for use by the Objective-C runtime.
1044 ///
1045 /// This is a convenience wrapper which not only creates the
1046 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +00001047 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001048 ///
1049 /// \param Name - The variable name.
1050 /// \param Init - The variable initializer; this is also used to
John McCall176f8922016-11-30 02:39:18 +00001051 /// define the type of the variable.
Alp Toker541d5072014-06-07 23:30:53 +00001052 /// \param Section - The section the variable should go into, or empty.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001053 /// \param Align - The alignment for the variable, or 0.
1054 /// \param AddToUsed - Whether the variable should be added to
John McCall176f8922016-11-30 02:39:18 +00001055 /// "llvm.used".
Zachary Turner41a9ee92017-10-11 23:54:34 +00001056 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
John McCall176f8922016-11-30 02:39:18 +00001057 ConstantStructBuilder &Init,
1058 StringRef Section, CharUnits Align,
1059 bool AddToUsed);
Zachary Turner41a9ee92017-10-11 23:54:34 +00001060 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
John McCall176f8922016-11-30 02:39:18 +00001061 llvm::Constant *Init,
John McCall7f416cc2015-09-08 08:05:57 +00001062 StringRef Section, CharUnits Align,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001063 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +00001064
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001065 llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00001066 ObjCLabelType LabelType,
1067 bool ForceNonFragileABI = false,
1068 bool NullTerminate = true);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00001069
John McCall3fd13f062015-10-21 18:06:47 +00001070protected:
John McCall9e8bb002011-05-14 03:10:52 +00001071 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1072 ReturnValueSlot Return,
1073 QualType ResultType,
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08001074 Selector Sel,
John McCall9e8bb002011-05-14 03:10:52 +00001075 llvm::Value *Arg0,
1076 QualType Arg0Ty,
1077 bool IsSuper,
1078 const CallArgList &CallArgs,
1079 const ObjCMethodDecl *OMD,
John McCall1e3157b2015-09-10 22:27:50 +00001080 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00001081 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +00001082
Daniel Dunbar5e639272010-04-25 20:39:01 +00001083 /// EmitImageInfo - Emit the image info marker used to encode some module
1084 /// level information.
1085 void EmitImageInfo();
1086
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001087public:
Owen Andersonae86c192009-07-13 04:10:07 +00001088 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
John McCalla729c622012-02-17 03:33:10 +00001089 CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001090
John McCall3fd13f062015-10-21 18:06:47 +00001091 bool isNonFragileABI() const {
1092 return ObjCABI == 2;
1093 }
1094
John McCall7f416cc2015-09-08 08:05:57 +00001095 ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
John McCallcd21d542016-11-30 23:15:55 +00001096 ConstantAddress GenerateConstantNSString(const StringLiteral *SL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001097
Craig Topper4f12f102014-03-12 06:41:41 +00001098 llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
Craig Topper8a13c412014-05-21 05:09:00 +00001099 const ObjCContainerDecl *CD=nullptr) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001100
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08001101 llvm::Function *GenerateDirectMethod(const ObjCMethodDecl *OMD,
1102 const ObjCContainerDecl *CD);
1103
1104 void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
1105 const ObjCMethodDecl *OMD,
1106 const ObjCContainerDecl *CD) override;
1107
Craig Topper4f12f102014-03-12 06:41:41 +00001108 void GenerateProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001109
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001110 /// GetOrEmitProtocol - Get the protocol object for the given
1111 /// declaration, emitting it if necessary. The return value has type
1112 /// ProtocolPtrTy.
1113 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001114
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001115 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1116 /// object for the given declaration, emitting it if needed. These
1117 /// forward references will be filled in with empty bodies if no
1118 /// definition is seen. The return value has type ProtocolPtrTy.
1119 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCallcd21d542016-11-30 23:15:55 +00001120
1121 virtual llvm::Constant *getNSConstantStringClassRef() = 0;
1122
Craig Topper4f12f102014-03-12 06:41:41 +00001123 llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1124 const CGBlockInfo &blockInfo) override;
1125 llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1126 const CGBlockInfo &blockInfo) override;
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00001127 std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM,
1128 const CGBlockInfo &blockInfo) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001129
1130 llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1131 QualType T) override;
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00001132
1133private:
1134 void fillRunSkipBlockVars(CodeGenModule &CGM, const CGBlockInfo &blockInfo);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001135};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001136
John McCall176f8922016-11-30 02:39:18 +00001137namespace {
1138
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001139enum class MethodListType {
1140 CategoryInstanceMethods,
1141 CategoryClassMethods,
1142 InstanceMethods,
1143 ClassMethods,
1144 ProtocolInstanceMethods,
1145 ProtocolClassMethods,
1146 OptionalProtocolInstanceMethods,
1147 OptionalProtocolClassMethods,
1148};
1149
John McCall176f8922016-11-30 02:39:18 +00001150/// A convenience class for splitting the methods of a protocol into
1151/// the four interesting groups.
1152class ProtocolMethodLists {
1153public:
1154 enum Kind {
1155 RequiredInstanceMethods,
1156 RequiredClassMethods,
1157 OptionalInstanceMethods,
1158 OptionalClassMethods
1159 };
1160 enum {
1161 NumProtocolMethodLists = 4
1162 };
1163
1164 static MethodListType getMethodListKind(Kind kind) {
1165 switch (kind) {
1166 case RequiredInstanceMethods:
1167 return MethodListType::ProtocolInstanceMethods;
1168 case RequiredClassMethods:
1169 return MethodListType::ProtocolClassMethods;
1170 case OptionalInstanceMethods:
1171 return MethodListType::OptionalProtocolInstanceMethods;
1172 case OptionalClassMethods:
1173 return MethodListType::OptionalProtocolClassMethods;
1174 }
1175 llvm_unreachable("bad kind");
1176 }
1177
1178 SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];
1179
1180 static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
1181 ProtocolMethodLists result;
1182
1183 for (auto MD : PD->methods()) {
1184 size_t index = (2 * size_t(MD->isOptional()))
1185 + (size_t(MD->isClassMethod()));
1186 result.Methods[index].push_back(MD);
1187 }
1188
1189 return result;
1190 }
1191
1192 template <class Self>
1193 SmallVector<llvm::Constant*, 8> emitExtendedTypesArray(Self *self) const {
1194 // In both ABIs, the method types list is parallel with the
1195 // concatenation of the methods arrays in the following order:
1196 // instance methods
1197 // class methods
1198 // optional instance methods
1199 // optional class methods
1200 SmallVector<llvm::Constant*, 8> result;
1201
1202 // Methods is already in the correct order for both ABIs.
1203 for (auto &list : Methods) {
1204 for (auto MD : list) {
1205 result.push_back(self->GetMethodVarType(MD, true));
1206 }
1207 }
1208
1209 return result;
1210 }
1211
1212 template <class Self>
1213 llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD,
1214 Kind kind) const {
1215 return self->emitMethodList(PD->getObjCRuntimeNameAsString(),
1216 getMethodListKind(kind), Methods[kind]);
1217 }
1218};
1219
1220} // end anonymous namespace
1221
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001222class CGObjCMac : public CGObjCCommonMac {
1223private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001224 friend ProtocolMethodLists;
John McCall176f8922016-11-30 02:39:18 +00001225
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001226 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001227
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001228 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001229 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001230 void EmitModuleInfo();
1231
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001232 /// EmitModuleSymols - Emit module symbols, the list of defined
1233 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001234 llvm::Constant *EmitModuleSymbols();
1235
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001236 /// FinishModule - Write out global data structures at the end of
1237 /// processing a translation unit.
1238 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +00001239
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001240 /// EmitClassExtension - Generate the class extension structure used
1241 /// to store the weak ivar layout and properties. The return value
1242 /// has type ClassExtensionPtrTy.
John McCall3fd13f062015-10-21 18:06:47 +00001243 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
John McCall460ce582015-10-22 18:38:17 +00001244 CharUnits instanceSize,
Manman Renad0e7912016-01-29 19:22:54 +00001245 bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00001246 bool isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001247
1248 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1249 /// for the given class.
John McCall882987f2013-02-28 19:01:20 +00001250 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001251 const ObjCInterfaceDecl *ID);
Fangrui Song6907ce22018-07-30 19:24:48 +00001252
John McCall882987f2013-02-28 19:01:20 +00001253 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00001254 IdentifierInfo *II);
Craig Topper4f12f102014-03-12 06:41:41 +00001255
1256 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
1257
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001258 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1259 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001260
1261 /// EmitIvarList - Emit the ivar list for the given
1262 /// implementation. If ForClass is true the list of class ivars
1263 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1264 /// interface ivars will be emitted. The return value has type
1265 /// IvarListPtrTy.
1266 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00001267 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001268
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001269 /// EmitMetaClass - Emit a forward reference to the class structure
1270 /// for the metaclass of the given interface. The return value has
1271 /// type ClassPtrTy.
1272 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1273
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001274 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001275 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001276 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1277 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00001278 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001279
John McCall176f8922016-11-30 02:39:18 +00001280 void emitMethodConstant(ConstantArrayBuilder &builder,
1281 const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001282
John McCall176f8922016-11-30 02:39:18 +00001283 void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
1284 const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001285
1286 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +00001287 /// implementation. The return value has type MethodListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001288 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
John McCall176f8922016-11-30 02:39:18 +00001289 ArrayRef<const ObjCMethodDecl *> Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001290
Daniel Dunbarc475d422008-10-29 22:36:39 +00001291 /// GetOrEmitProtocol - Get the protocol object for the given
1292 /// declaration, emitting it if necessary. The return value has type
1293 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001294 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001295
1296 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1297 /// object for the given declaration, emitting it if needed. These
1298 /// forward references will be filled in with empty bodies if no
1299 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001300 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbarc475d422008-10-29 22:36:39 +00001301
Daniel Dunbarb036db82008-08-13 03:21:16 +00001302 /// EmitProtocolExtension - Generate the protocol extension
1303 /// structure used to store optional instance and class methods, and
1304 /// protocol properties. The return value has type
1305 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001306 llvm::Constant *
1307 EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00001308 const ProtocolMethodLists &methodLists);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001309
1310 /// EmitProtocolList - Generate the list of referenced
1311 /// protocols. The return value has type ProtocolListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001312 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001313 ObjCProtocolDecl::protocol_iterator begin,
1314 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001315
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001316 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1317 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001318 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
Erik Pilkingtond5e66f0e2019-12-10 16:43:39 -08001319 Address EmitSelectorAddr(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001320
1321public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001322 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001323
John McCallcd21d542016-11-30 23:15:55 +00001324 llvm::Constant *getNSConstantStringClassRef() override;
1325
Craig Topper4f12f102014-03-12 06:41:41 +00001326 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001327
Craig Topper4f12f102014-03-12 06:41:41 +00001328 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1329 ReturnValueSlot Return,
1330 QualType ResultType,
1331 Selector Sel, llvm::Value *Receiver,
1332 const CallArgList &CallArgs,
1333 const ObjCInterfaceDecl *Class,
1334 const ObjCMethodDecl *Method) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001335
Craig Topper4f12f102014-03-12 06:41:41 +00001336 CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001337 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001338 ReturnValueSlot Return, QualType ResultType,
1339 Selector Sel, const ObjCInterfaceDecl *Class,
1340 bool isCategoryImpl, llvm::Value *Receiver,
1341 bool IsClassMessage, const CallArgList &CallArgs,
1342 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001343
Craig Topper4f12f102014-03-12 06:41:41 +00001344 llvm::Value *GetClass(CodeGenFunction &CGF,
1345 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001346
John McCall7f416cc2015-09-08 08:05:57 +00001347 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
1348 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001349
1350 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1351 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001352 llvm::Value *GetSelector(CodeGenFunction &CGF,
1353 const ObjCMethodDecl *Method) override;
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001354
Craig Topper4f12f102014-03-12 06:41:41 +00001355 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001356
Craig Topper4f12f102014-03-12 06:41:41 +00001357 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001358
Craig Topper4f12f102014-03-12 06:41:41 +00001359 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001360
Craig Topper4f12f102014-03-12 06:41:41 +00001361 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001362
Craig Topper4f12f102014-03-12 06:41:41 +00001363 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1364 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001365
James Y Knight9871db02019-02-05 16:42:33 +00001366 llvm::FunctionCallee GetPropertyGetFunction() override;
1367 llvm::FunctionCallee GetPropertySetFunction() override;
1368 llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
1369 bool copy) override;
1370 llvm::FunctionCallee GetGetStructFunction() override;
1371 llvm::FunctionCallee GetSetStructFunction() override;
1372 llvm::FunctionCallee GetCppAtomicObjectGetFunction() override;
1373 llvm::FunctionCallee GetCppAtomicObjectSetFunction() override;
1374 llvm::FunctionCallee EnumerationMutationFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001375
Craig Topper4f12f102014-03-12 06:41:41 +00001376 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1377 const ObjCAtTryStmt &S) override;
1378 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1379 const ObjCAtSynchronizedStmt &S) override;
John McCallbd309292010-07-06 01:34:17 +00001380 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Craig Topper4f12f102014-03-12 06:41:41 +00001381 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1382 bool ClearInsertionPoint=true) override;
1383 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001384 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001385 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001386 llvm::Value *src, Address dst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001387 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001388 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001389 bool threadlocal = false) override;
1390 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001391 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001392 llvm::Value *ivarOffset) override;
1393 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001394 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001395 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001396 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001397 llvm::Value *size) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001398
Craig Topper4f12f102014-03-12 06:41:41 +00001399 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1400 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1401 unsigned CVRQualifiers) override;
1402 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1403 const ObjCInterfaceDecl *Interface,
1404 const ObjCIvarDecl *Ivar) override;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001405};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001406
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001407class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001408private:
John McCallc4ae1dd2016-11-30 04:18:19 +00001409 friend ProtocolMethodLists;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001410 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001411 llvm::GlobalVariable* ObjCEmptyCacheVar;
John McCall176f8922016-11-30 02:39:18 +00001412 llvm::Constant* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001413
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001414 /// SuperClassReferences - uniqued super class references.
1415 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001416
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001417 /// MetaClassReferences - uniqued meta class references.
1418 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001419
1420 /// EHTypeReferences - uniqued class ehtype references.
1421 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001422
John McCall9e8bb002011-05-14 03:10:52 +00001423 /// VTableDispatchMethods - List of methods for which we generate
1424 /// vtable-based message dispatch.
1425 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001426
Fariborz Jahanian67260552009-11-17 21:37:35 +00001427 /// DefinedMetaClasses - List of defined meta-classes.
1428 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
Fangrui Song6907ce22018-07-30 19:24:48 +00001429
John McCall9e8bb002011-05-14 03:10:52 +00001430 /// isVTableDispatchedSelector - Returns true if SEL is a
1431 /// vtable-based selector.
1432 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001433
Fariborz Jahanian71394042009-01-23 23:53:38 +00001434 /// FinishNonFragileABIModule - Write out global data structures at the end of
1435 /// processing a translation unit.
1436 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001437
Daniel Dunbar19573e72009-05-15 21:48:48 +00001438 /// AddModuleClassList - Add the given list of class pointers to the
1439 /// module with the provided symbol and section names.
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001440 void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container,
1441 StringRef SymbolName, StringRef SectionName);
Daniel Dunbar19573e72009-05-15 21:48:48 +00001442
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001443 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1444 unsigned InstanceStart,
1445 unsigned InstanceSize,
1446 const ObjCImplementationDecl *ID);
John McCalldba63a72016-11-30 23:54:50 +00001447 llvm::GlobalVariable *BuildClassObject(const ObjCInterfaceDecl *CI,
1448 bool isMetaclass,
1449 llvm::Constant *IsAGV,
1450 llvm::Constant *SuperClassGV,
1451 llvm::Constant *ClassRoGV,
1452 bool HiddenVisibility);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001453
John McCall176f8922016-11-30 02:39:18 +00001454 void emitMethodConstant(ConstantArrayBuilder &builder,
1455 const ObjCMethodDecl *MD,
1456 bool forProtocol);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001457
John McCall176f8922016-11-30 02:39:18 +00001458 /// Emit the method list for the given implementation. The return value
1459 /// has type MethodListnfABITy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001460 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
John McCall176f8922016-11-30 02:39:18 +00001461 ArrayRef<const ObjCMethodDecl *> Methods);
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00001462
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001463 /// EmitIvarList - Emit the ivar list for the given
1464 /// implementation. If ForClass is true the list of class ivars
1465 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1466 /// interface ivars will be emitted. The return value has type
1467 /// IvarListnfABIPtrTy.
1468 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001469
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001470 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001471 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00001472 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001473
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001474 /// GetOrEmitProtocol - Get the protocol object for the given
1475 /// declaration, emitting it if necessary. The return value has type
1476 /// ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001477 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001478
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001479 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1480 /// object for the given declaration, emitting it if needed. These
1481 /// forward references will be filled in with empty bodies if no
1482 /// definition is seen. The return value has type ProtocolPtrTy.
Craig Topper4f12f102014-03-12 06:41:41 +00001483 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001484
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001485 /// EmitProtocolList - Generate the list of referenced
1486 /// protocols. The return value has type ProtocolListPtrTy.
Zachary Turner41a9ee92017-10-11 23:54:34 +00001487 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001488 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001489 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001490
John McCall9e8bb002011-05-14 03:10:52 +00001491 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1492 ReturnValueSlot Return,
1493 QualType ResultType,
1494 Selector Sel,
1495 llvm::Value *Receiver,
1496 QualType Arg0Ty,
1497 bool IsSuper,
1498 const CallArgList &CallArgs,
1499 const ObjCMethodDecl *Method);
Fangrui Song6907ce22018-07-30 19:24:48 +00001500
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001501 /// GetClassGlobal - Return the global variable for the Objective-C
1502 /// class of the given name.
John McCalldba63a72016-11-30 23:54:50 +00001503 llvm::Constant *GetClassGlobal(StringRef Name,
1504 ForDefinition_t IsForDefinition,
1505 bool Weak = false, bool DLLImport = false);
1506 llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID,
1507 bool isMetaclass,
1508 ForDefinition_t isForDefinition);
Rafael Espindola554256c2014-02-26 22:25:45 +00001509
John McCall2c91c3b2019-05-30 04:09:01 +00001510 llvm::Constant *GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID);
1511
1512 llvm::Value *EmitLoadOfClassRef(CodeGenFunction &CGF,
1513 const ObjCInterfaceDecl *ID,
1514 llvm::GlobalVariable *Entry);
1515
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001516 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001517 /// for the given class reference.
John McCall882987f2013-02-28 19:01:20 +00001518 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001519 const ObjCInterfaceDecl *ID);
Fangrui Song6907ce22018-07-30 19:24:48 +00001520
John McCall882987f2013-02-28 19:01:20 +00001521 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
John McCalldba63a72016-11-30 23:54:50 +00001522 IdentifierInfo *II,
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00001523 const ObjCInterfaceDecl *ID);
Craig Topper4f12f102014-03-12 06:41:41 +00001524
1525 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001526
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001527 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1528 /// for the given super class reference.
John McCall882987f2013-02-28 19:01:20 +00001529 llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001530 const ObjCInterfaceDecl *ID);
1531
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001532 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1533 /// meta-data
John McCall882987f2013-02-28 19:01:20 +00001534 llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00001535 const ObjCInterfaceDecl *ID, bool Weak);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001536
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001537 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1538 /// the given ivar.
1539 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001540 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001541 const ObjCInterfaceDecl *ID,
1542 const ObjCIvarDecl *Ivar);
1543
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001544 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1545 /// for the given selector.
John McCall7f416cc2015-09-08 08:05:57 +00001546 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
Erik Pilkingtond5e66f0e2019-12-10 16:43:39 -08001547 Address EmitSelectorAddr(Selector Sel);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001548
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001549 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001550 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001551 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
John McCalldba63a72016-11-30 23:54:50 +00001552 ForDefinition_t IsForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001553
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001554 StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001555
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00001556 StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; }
Daniel Dunbar15894b72009-04-07 05:48:37 +00001557
Daniel Dunbar961202372009-05-03 12:57:56 +00001558 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001559 uint32_t &InstanceStart,
1560 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001561
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001562 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001563 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001564 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1565 return CGM.getContext().Selectors.getSelector(0, &II);
1566 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001567
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001568 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001569 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1570 return CGM.getContext().Selectors.getSelector(1, &II);
1571 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001572
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001573 /// ImplementationIsNonLazy - Check whether the given category or
1574 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001575 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001576
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001577 bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001578 const ObjCIvarDecl *IV) {
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001579 // Annotate the load as an invariant load iff inside an instance method
1580 // and ivar belongs to instance method's class and one of its super class.
1581 // This check is needed because the ivar offset is a lazily
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001582 // initialised value that may depend on objc_msgSend to perform a fixup on
1583 // the first message dispatch.
1584 //
1585 // An additional opportunity to mark the load as invariant arises when the
1586 // base of the ivar access is a parameter to an Objective C method.
1587 // However, because the parameters are not available in the current
1588 // interface, we cannot perform this check.
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08001589 //
1590 // Note that for direct methods, because objc_msgSend is skipped,
1591 // and that the method may be inlined, this optimization actually
1592 // can't be performed.
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001593 if (const ObjCMethodDecl *MD =
1594 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08001595 if (MD->isInstanceMethod() && !MD->isDirectMethod())
Fariborz Jahaniandafffbe2014-03-04 18:34:52 +00001596 if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
1597 return IV->getContainingInterface()->isSuperClassOf(ID);
Saleem Abdulrasool5f25bc32013-02-17 04:03:34 +00001598 return false;
1599 }
1600
Erik Pilkington2ff012d2019-01-17 18:18:53 +00001601 bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) {
1602 // NSObject is a fixed size. If we can see the @implementation of a class
1603 // which inherits from NSObject then we know that all it's offsets also must
1604 // be fixed. FIXME: Can we do this if see a chain of super classes with
1605 // implementations leading to NSObject?
1606 return ID->getImplementation() && ID->getSuperClass() &&
1607 ID->getSuperClass()->getName() == "NSObject";
1608 }
1609
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001610public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001611 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
John McCallcd21d542016-11-30 23:15:55 +00001612
1613 llvm::Constant *getNSConstantStringClassRef() override;
1614
Craig Topper4f12f102014-03-12 06:41:41 +00001615 llvm::Function *ModuleInitFunction() override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001616
Craig Topper4f12f102014-03-12 06:41:41 +00001617 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1618 ReturnValueSlot Return,
1619 QualType ResultType, Selector Sel,
1620 llvm::Value *Receiver,
1621 const CallArgList &CallArgs,
1622 const ObjCInterfaceDecl *Class,
1623 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001624
Craig Topper4f12f102014-03-12 06:41:41 +00001625 CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001626 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Craig Topper4f12f102014-03-12 06:41:41 +00001627 ReturnValueSlot Return, QualType ResultType,
1628 Selector Sel, const ObjCInterfaceDecl *Class,
1629 bool isCategoryImpl, llvm::Value *Receiver,
1630 bool IsClassMessage, const CallArgList &CallArgs,
1631 const ObjCMethodDecl *Method) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001632
Craig Topper4f12f102014-03-12 06:41:41 +00001633 llvm::Value *GetClass(CodeGenFunction &CGF,
1634 const ObjCInterfaceDecl *ID) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001635
John McCall7f416cc2015-09-08 08:05:57 +00001636 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override
1637 { return EmitSelector(CGF, Sel); }
1638 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override
Erik Pilkingtond5e66f0e2019-12-10 16:43:39 -08001639 { return EmitSelectorAddr(Sel); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001640
1641 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1642 /// untyped one.
Craig Topper4f12f102014-03-12 06:41:41 +00001643 llvm::Value *GetSelector(CodeGenFunction &CGF,
1644 const ObjCMethodDecl *Method) override
John McCall882987f2013-02-28 19:01:20 +00001645 { return EmitSelector(CGF, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001646
Craig Topper4f12f102014-03-12 06:41:41 +00001647 void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001648
Craig Topper4f12f102014-03-12 06:41:41 +00001649 void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;
David Chisnall92d436b2012-01-31 18:59:20 +00001650
Craig Topper4f12f102014-03-12 06:41:41 +00001651 void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}
David Chisnall92d436b2012-01-31 18:59:20 +00001652
Craig Topper4f12f102014-03-12 06:41:41 +00001653 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1654 const ObjCProtocolDecl *PD) override;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001655
Craig Topper4f12f102014-03-12 06:41:41 +00001656 llvm::Constant *GetEHType(QualType T) override;
John McCall2ca705e2010-07-24 00:37:23 +00001657
James Y Knight9871db02019-02-05 16:42:33 +00001658 llvm::FunctionCallee GetPropertyGetFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001659 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001660 }
James Y Knight9871db02019-02-05 16:42:33 +00001661 llvm::FunctionCallee GetPropertySetFunction() override {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001662 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001663 }
Craig Topper4f12f102014-03-12 06:41:41 +00001664
James Y Knight9871db02019-02-05 16:42:33 +00001665 llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
1666 bool copy) override {
Ted Kremeneke65b0862012-03-06 20:05:56 +00001667 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1668 }
Craig Topper4f12f102014-03-12 06:41:41 +00001669
James Y Knight9871db02019-02-05 16:42:33 +00001670 llvm::FunctionCallee GetSetStructFunction() override {
David Chisnall168b80f2010-12-26 22:13:16 +00001671 return ObjCTypes.getCopyStructFn();
1672 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001673
James Y Knight9871db02019-02-05 16:42:33 +00001674 llvm::FunctionCallee GetGetStructFunction() override {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001675 return ObjCTypes.getCopyStructFn();
1676 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001677
James Y Knight9871db02019-02-05 16:42:33 +00001678 llvm::FunctionCallee GetCppAtomicObjectSetFunction() override {
David Chisnall0d75e062012-12-17 18:54:24 +00001679 return ObjCTypes.getCppAtomicObjectFunction();
1680 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00001681
James Y Knight9871db02019-02-05 16:42:33 +00001682 llvm::FunctionCallee GetCppAtomicObjectGetFunction() override {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001683 return ObjCTypes.getCppAtomicObjectFunction();
1684 }
Craig Topper4f12f102014-03-12 06:41:41 +00001685
James Y Knight9871db02019-02-05 16:42:33 +00001686 llvm::FunctionCallee EnumerationMutationFunction() override {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001687 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001688 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001689
Craig Topper4f12f102014-03-12 06:41:41 +00001690 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1691 const ObjCAtTryStmt &S) override;
1692 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1693 const ObjCAtSynchronizedStmt &S) override;
1694 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
1695 bool ClearInsertionPoint=true) override;
1696 llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001697 Address AddrWeakObj) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001698 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001699 llvm::Value *src, Address edst) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001700 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001701 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001702 bool threadlocal = false) override;
1703 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001704 llvm::Value *src, Address dest,
Craig Topper4f12f102014-03-12 06:41:41 +00001705 llvm::Value *ivarOffset) override;
1706 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001707 llvm::Value *src, Address dest) override;
Craig Topper4f12f102014-03-12 06:41:41 +00001708 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00001709 Address dest, Address src,
Craig Topper4f12f102014-03-12 06:41:41 +00001710 llvm::Value *size) override;
1711 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1712 llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
1713 unsigned CVRQualifiers) override;
1714 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1715 const ObjCInterfaceDecl *Interface,
1716 const ObjCIvarDecl *Ivar) override;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001717};
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001718
1719/// A helper class for performing the null-initialization of a return
1720/// value.
1721struct NullReturnState {
1722 llvm::BasicBlock *NullBB;
Craig Topper8a13c412014-05-21 05:09:00 +00001723 NullReturnState() : NullBB(nullptr) {}
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001724
John McCall3d1e2c92013-02-12 05:53:35 +00001725 /// Perform a null-check of the given receiver.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001726 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
John McCall3d1e2c92013-02-12 05:53:35 +00001727 // Make blocks for the null-receiver and call edges.
1728 NullBB = CGF.createBasicBlock("msgSend.null-receiver");
1729 llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001730
1731 // Check for a null receiver and, if there is one, jump to the
John McCall3d1e2c92013-02-12 05:53:35 +00001732 // null-receiver block. There's no point in trying to avoid it:
1733 // we're always going to put *something* there, because otherwise
1734 // we shouldn't have done this null-check in the first place.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001735 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1736 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1737
1738 // Otherwise, start performing the call.
1739 CGF.EmitBlock(callBB);
1740 }
1741
John McCall3d1e2c92013-02-12 05:53:35 +00001742 /// Complete the null-return operation. It is valid to call this
1743 /// regardless of whether 'init' has been called.
Kuba Mracekbce5cea2017-06-30 16:28:15 +00001744 RValue complete(CodeGenFunction &CGF,
1745 ReturnValueSlot returnSlot,
1746 RValue result,
1747 QualType resultType,
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001748 const CallArgList &CallArgs,
1749 const ObjCMethodDecl *Method) {
John McCall3d1e2c92013-02-12 05:53:35 +00001750 // If we never had to do a null-check, just use the raw result.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001751 if (!NullBB) return result;
John McCall3d1e2c92013-02-12 05:53:35 +00001752
1753 // The continuation block. This will be left null if we don't have an
1754 // IP, which can happen if the method we're calling is marked noreturn.
Craig Topper8a13c412014-05-21 05:09:00 +00001755 llvm::BasicBlock *contBB = nullptr;
1756
John McCall3d1e2c92013-02-12 05:53:35 +00001757 // Finish the call path.
1758 llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
1759 if (callBB) {
1760 contBB = CGF.createBasicBlock("msgSend.cont");
1761 CGF.Builder.CreateBr(contBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001762 }
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001763
John McCall3d1e2c92013-02-12 05:53:35 +00001764 // Okay, start emitting the null-receiver block.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001765 CGF.EmitBlock(NullBB);
Fangrui Song6907ce22018-07-30 19:24:48 +00001766
John McCall3d1e2c92013-02-12 05:53:35 +00001767 // Release any consumed arguments we've got.
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001768 if (Method) {
1769 CallArgList::const_iterator I = CallArgs.begin();
1770 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1771 e = Method->param_end(); i != e; ++i, ++I) {
1772 const ParmVarDecl *ParamDecl = (*i);
1773 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
Yaxun Liu5b330e82018-03-15 15:25:19 +00001774 RValue RV = I->getRValue(CGF);
Fangrui Song6907ce22018-07-30 19:24:48 +00001775 assert(RV.isScalar() &&
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001776 "NullReturnState::complete - arg not on object");
John McCallcdda29c2013-03-13 03:10:54 +00001777 CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001778 }
1779 }
1780 }
John McCall3d1e2c92013-02-12 05:53:35 +00001781
1782 // The phi code below assumes that we haven't needed any control flow yet.
1783 assert(CGF.Builder.GetInsertBlock() == NullBB);
1784
1785 // If we've got a void return, just jump to the continuation block.
1786 if (result.isScalar() && resultType->isVoidType()) {
1787 // No jumps required if the message-send was noreturn.
1788 if (contBB) CGF.EmitBlock(contBB);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001789 return result;
1790 }
1791
John McCall3d1e2c92013-02-12 05:53:35 +00001792 // If we've got a scalar return, build a phi.
1793 if (result.isScalar()) {
1794 // Derive the null-initialization value.
1795 llvm::Constant *null = CGF.CGM.EmitNullConstant(resultType);
1796
1797 // If no join is necessary, just flow out.
1798 if (!contBB) return RValue::get(null);
1799
1800 // Otherwise, build a phi.
1801 CGF.EmitBlock(contBB);
1802 llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2);
1803 phi->addIncoming(result.getScalarVal(), callBB);
1804 phi->addIncoming(null, NullBB);
1805 return RValue::get(phi);
1806 }
1807
1808 // If we've got an aggregate return, null the buffer out.
1809 // FIXME: maybe we should be doing things differently for all the
1810 // cases where the ABI has us returning (1) non-agg values in
1811 // memory or (2) agg values in registers.
1812 if (result.isAggregate()) {
1813 assert(result.isAggregate() && "null init of non-aggregate result?");
Kuba Mracekbce5cea2017-06-30 16:28:15 +00001814 if (!returnSlot.isUnused())
1815 CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
John McCall3d1e2c92013-02-12 05:53:35 +00001816 if (contBB) CGF.EmitBlock(contBB);
1817 return result;
1818 }
1819
1820 // Complex types.
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001821 CGF.EmitBlock(contBB);
John McCall3d1e2c92013-02-12 05:53:35 +00001822 CodeGenFunction::ComplexPairTy callResult = result.getComplexVal();
1823
1824 // Find the scalar type and its zero value.
1825 llvm::Type *scalarTy = callResult.first->getType();
1826 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1827
1828 // Build phis for both coordinates.
1829 llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2);
1830 real->addIncoming(callResult.first, callBB);
1831 real->addIncoming(scalarZero, NullBB);
1832 llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2);
1833 imag->addIncoming(callResult.second, callBB);
1834 imag->addIncoming(scalarZero, NullBB);
1835 return RValue::getComplex(real, imag);
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001836 }
1837};
1838
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001839} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001840
1841/* *** Helper Functions *** */
1842
1843/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001844static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
David Blaikiee3b172a2015-04-02 18:55:21 +00001845 llvm::GlobalVariable *C, unsigned idx0,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001846 unsigned idx1) {
1847 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001848 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1849 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001850 };
David Blaikiee3b172a2015-04-02 18:55:21 +00001851 return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001852}
1853
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001854/// hasObjCExceptionAttribute - Return true if this class or any super
1855/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001856static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001857 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001858 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001859 return true;
1860 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001861 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001862 return false;
1863}
1864
Akira Hatanaka187770d2019-05-09 17:43:52 +00001865static llvm::GlobalValue::LinkageTypes
1866getLinkageTypeForObjCMetadata(CodeGenModule &CGM, StringRef Section) {
1867 if (CGM.getTriple().isOSBinFormatMachO() &&
1868 (Section.empty() || Section.startswith("__DATA")))
1869 return llvm::GlobalValue::InternalLinkage;
1870 return llvm::GlobalValue::PrivateLinkage;
1871}
1872
1873/// A helper function to create an internal or private global variable.
1874static llvm::GlobalVariable *
1875finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder,
1876 const llvm::Twine &Name, CodeGenModule &CGM) {
1877 std::string SectionName;
1878 if (CGM.getTriple().isOSBinFormatMachO())
1879 SectionName = "__DATA, __objc_const";
1880 auto *GV = Builder.finishAndCreateGlobal(
1881 Name, CGM.getPointerAlign(), /*constant*/ false,
1882 getLinkageTypeForObjCMetadata(CGM, SectionName));
1883 GV->setSection(SectionName);
1884 return GV;
1885}
1886
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001887/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001888
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001889CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001890 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001891 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001892 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001893}
1894
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001895/// GetClass - Return a reference to the class for the given interface
1896/// decl.
John McCall882987f2013-02-28 19:01:20 +00001897llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001898 const ObjCInterfaceDecl *ID) {
John McCall882987f2013-02-28 19:01:20 +00001899 return EmitClassRef(CGF, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001900}
1901
1902/// GetSelector - Return the pointer to the unique'd string for this selector.
John McCall7f416cc2015-09-08 08:05:57 +00001903llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
1904 return EmitSelector(CGF, Sel);
1905}
1906Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
Erik Pilkingtond5e66f0e2019-12-10 16:43:39 -08001907 return EmitSelectorAddr(Sel);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001908}
John McCall882987f2013-02-28 19:01:20 +00001909llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001910 *Method) {
John McCall882987f2013-02-28 19:01:20 +00001911 return EmitSelector(CGF, Method->getSelector());
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001912}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001913
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001914llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001915 if (T->isObjCIdType() ||
1916 T->isObjCQualifiedIdType()) {
1917 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001918 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001919 }
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001920 if (T->isObjCClassType() ||
1921 T->isObjCQualifiedClassType()) {
1922 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001923 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001924 }
1925 if (T->isObjCObjectPointerType())
1926 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
Fangrui Song6907ce22018-07-30 19:24:48 +00001927
John McCall2ca705e2010-07-24 00:37:23 +00001928 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall2ca705e2010-07-24 00:37:23 +00001929}
1930
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001931/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001932/*
1933 struct __builtin_CFString {
1934 const int *isa; // point to __CFConstantStringClassReference
1935 int flags;
1936 const char *str;
1937 long length;
1938 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001939*/
1940
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001941/// or Generate a constant NSString object.
1942/*
1943 struct __builtin_NSString {
1944 const int *isa; // point to __NSConstantStringClassReference
1945 const char *str;
1946 unsigned int length;
1947 };
1948*/
1949
John McCallcd21d542016-11-30 23:15:55 +00001950ConstantAddress
1951CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) {
1952 return (!CGM.getLangOpts().NoConstantCFStrings
1953 ? CGM.GetAddrOfConstantCFString(SL)
1954 : GenerateConstantNSString(SL));
1955}
1956
1957static llvm::StringMapEntry<llvm::GlobalVariable *> &
1958GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
1959 const StringLiteral *Literal, unsigned &StringLength) {
1960 StringRef String = Literal->getString();
1961 StringLength = String.size();
1962 return *Map.insert(std::make_pair(String, nullptr)).first;
1963}
1964
1965llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1966 if (llvm::Value *V = ConstantStringClassRef)
1967 return cast<llvm::Constant>(V);
1968
1969 auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
1970 std::string str =
1971 StringClass.empty() ? "_NSConstantStringClassReference"
1972 : "_" + StringClass + "ClassReference";
1973
1974 llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0);
1975 auto GV = CGM.CreateRuntimeVariable(PTy, str);
1976 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1977 ConstantStringClassRef = V;
1978 return V;
1979}
1980
1981llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1982 if (llvm::Value *V = ConstantStringClassRef)
1983 return cast<llvm::Constant>(V);
1984
1985 auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
Fangrui Song6907ce22018-07-30 19:24:48 +00001986 std::string str =
1987 StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
John McCallcd21d542016-11-30 23:15:55 +00001988 : "OBJC_CLASS_$_" + StringClass;
John McCall2c91c3b2019-05-30 04:09:01 +00001989 llvm::Constant *GV = GetClassGlobal(str, NotForDefinition);
John McCallcd21d542016-11-30 23:15:55 +00001990
1991 // Make sure the result is of the correct type.
1992 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
1993
1994 ConstantStringClassRef = V;
1995 return V;
1996}
1997
1998ConstantAddress
1999CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) {
2000 unsigned StringLength = 0;
2001 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
2002 GetConstantStringEntry(NSConstantStringMap, Literal, StringLength);
2003
2004 if (auto *C = Entry.second)
2005 return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
2006
2007 // If we don't already have it, get _NSConstantStringClassReference.
2008 llvm::Constant *Class = getNSConstantStringClassRef();
2009
2010 // If we don't already have it, construct the type for a constant NSString.
2011 if (!NSConstantStringType) {
2012 NSConstantStringType =
2013 llvm::StructType::create({
2014 CGM.Int32Ty->getPointerTo(),
2015 CGM.Int8PtrTy,
2016 CGM.IntTy
2017 }, "struct.__builtin_NSString");
2018 }
2019
2020 ConstantInitBuilder Builder(CGM);
2021 auto Fields = Builder.beginStruct(NSConstantStringType);
2022
2023 // Class pointer.
2024 Fields.add(Class);
2025
2026 // String pointer.
2027 llvm::Constant *C =
2028 llvm::ConstantDataArray::getString(VMContext, Entry.first());
2029
2030 llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
2031 bool isConstant = !CGM.getLangOpts().WritableStrings;
2032
2033 auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant,
2034 Linkage, C, ".str");
2035 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2036 // Don't enforce the target's minimum global alignment, since the only use
2037 // of the string is via this class initializer.
Guillaume Chateletc79099e2019-10-03 13:00:29 +00002038 GV->setAlignment(llvm::Align::None());
John McCallcd21d542016-11-30 23:15:55 +00002039 Fields.addBitCast(GV, CGM.Int8PtrTy);
2040
2041 // String length.
2042 Fields.addInt(CGM.IntTy, StringLength);
2043
2044 // The struct.
2045 CharUnits Alignment = CGM.getPointerAlign();
2046 GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
2047 /*constant*/ true,
2048 llvm::GlobalVariable::PrivateLinkage);
2049 const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
2050 const char *NSStringNonFragileABISection =
2051 "__DATA,__objc_stringobj,regular,no_dead_strip";
2052 // FIXME. Fix section.
2053 GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile()
2054 ? NSStringNonFragileABISection
2055 : NSStringSection);
2056 Entry.second = GV;
2057
2058 return ConstantAddress(GV, Alignment);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002059}
2060
Ted Kremeneke65b0862012-03-06 20:05:56 +00002061enum {
2062 kCFTaggedObjectID_Integer = (1 << 1) + 1
2063};
2064
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002065/// Generates a message send where the super is the receiver. This is
2066/// a message send to self with special delivery semantics indicating
2067/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00002068CodeGen::RValue
2069CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00002070 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00002071 QualType ResultType,
2072 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002073 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002074 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002075 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00002076 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00002077 const CodeGen::CallArgList &CallArgs,
2078 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002079 // Create and init a super structure; this is a (receiver, class)
2080 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00002081 Address ObjCSuper =
2082 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
2083 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002084 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002085 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
James Y Knight751fe282019-02-09 22:22:28 +00002086 CGF.Builder.CreateStore(ReceiverAsObject,
2087 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00002088
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002089 // If this is a class message the metaclass is passed as the target.
2090 llvm::Value *Target;
2091 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002092 if (isCategoryImpl) {
2093 // Message sent to 'super' in a class method defined in a category
2094 // implementation requires an odd treatment.
2095 // If we are in a class method, we must retrieve the
2096 // _metaclass_ for the current class, pointed at by
2097 // the class's "isa" pointer. The following assumes that
2098 // isa" is the first ivar in a class (which it must be).
John McCall882987f2013-02-28 19:01:20 +00002099 Target = EmitClassRef(CGF, Class->getSuperClass());
David Blaikie1ed728c2015-04-05 22:45:47 +00002100 Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
John McCall7f416cc2015-09-08 08:05:57 +00002101 Target = CGF.Builder.CreateAlignedLoad(Target, CGF.getPointerAlign());
Mike Stump658fe022009-07-30 22:28:39 +00002102 } else {
David Blaikie1ed728c2015-04-05 22:45:47 +00002103 llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
2104 llvm::Value *SuperPtr =
2105 CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00002106 llvm::Value *Super =
2107 CGF.Builder.CreateAlignedLoad(SuperPtr, CGF.getPointerAlign());
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00002108 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002109 }
David Blaikie1ed728c2015-04-05 22:45:47 +00002110 } else if (isCategoryImpl)
John McCall882987f2013-02-28 19:01:20 +00002111 Target = EmitClassRef(CGF, Class->getSuperClass());
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00002112 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002113 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
David Blaikie1ed728c2015-04-05 22:45:47 +00002114 ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
John McCall7f416cc2015-09-08 08:05:57 +00002115 Target = CGF.Builder.CreateAlignedLoad(ClassPtr, CGF.getPointerAlign());
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002116 }
Mike Stump18bb9282009-05-16 07:57:57 +00002117 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
2118 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00002119 llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00002120 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00002121 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
James Y Knight751fe282019-02-09 22:22:28 +00002122 CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002123 return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.getPointer(),
2124 ObjCTypes.SuperPtrCTy, true, CallArgs, Method, Class,
2125 ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002126}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002127
2128/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00002129CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00002130 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00002131 QualType ResultType,
2132 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002133 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00002134 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00002135 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00002136 const ObjCMethodDecl *Method) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002137 return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2138 CGF.getContext().getObjCIdType(), false, CallArgs,
2139 Method, Class, ObjCTypes);
John McCall1e3157b2015-09-10 22:27:50 +00002140}
2141
2142static bool isWeakLinkedClass(const ObjCInterfaceDecl *ID) {
2143 do {
2144 if (ID->isWeakImported())
2145 return true;
2146 } while ((ID = ID->getSuperClass()));
2147
2148 return false;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00002149}
2150
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00002151CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00002152CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
2153 ReturnValueSlot Return,
2154 QualType ResultType,
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002155 Selector Sel,
John McCall9e8bb002011-05-14 03:10:52 +00002156 llvm::Value *Arg0,
2157 QualType Arg0Ty,
2158 bool IsSuper,
2159 const CallArgList &CallArgs,
2160 const ObjCMethodDecl *Method,
John McCall1e3157b2015-09-10 22:27:50 +00002161 const ObjCInterfaceDecl *ClassReceiver,
John McCall9e8bb002011-05-14 03:10:52 +00002162 const ObjCCommonTypesHelper &ObjCTypes) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002163 CodeGenTypes &Types = CGM.getTypes();
2164 auto selTy = CGF.getContext().getObjCSelType();
2165 llvm::Value *SelValue;
2166
2167 if (Method && Method->isDirectMethod()) {
2168 // Direct methods will synthesize the proper `_cmd` internally,
2169 // so just don't bother with setting the `_cmd` argument.
2170 assert(!IsSuper);
2171 SelValue = llvm::UndefValue::get(Types.ConvertType(selTy));
2172 } else {
2173 SelValue = GetSelector(CGF, Sel);
2174 }
2175
Daniel Dunbarc722b852008-08-30 03:02:31 +00002176 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00002177 if (!IsSuper)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00002178 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman43dca6a2011-05-02 17:57:46 +00002179 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002180 ActualArgs.add(RValue::get(SelValue), selTy);
John McCall31168b02011-06-15 23:02:42 +00002181 ActualArgs.addFrom(CallArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002182
John McCalla729c622012-02-17 03:33:10 +00002183 // If we're calling a method, use the formal signature.
2184 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002185
Anders Carlsson280e61f12010-06-21 20:59:55 +00002186 if (Method)
Alp Toker314cc812014-01-25 16:55:45 +00002187 assert(CGM.getContext().getCanonicalType(Method->getReturnType()) ==
2188 CGM.getContext().getCanonicalType(ResultType) &&
Anders Carlsson280e61f12010-06-21 20:59:55 +00002189 "Result type mismatch!");
2190
John McCall1e3157b2015-09-10 22:27:50 +00002191 bool ReceiverCanBeNull = true;
2192
2193 // Super dispatch assumes that self is non-null; even the messenger
2194 // doesn't have a null check internally.
2195 if (IsSuper) {
2196 ReceiverCanBeNull = false;
2197
2198 // If this is a direct dispatch of a class method, check whether the class,
2199 // or anything in its hierarchy, was weak-linked.
2200 } else if (ClassReceiver && Method && Method->isClassMethod()) {
2201 ReceiverCanBeNull = isWeakLinkedClass(ClassReceiver);
2202
2203 // If we're emitting a method, and self is const (meaning just ARC, for now),
2204 // and the receiver is a load of self, then self is a valid object.
2205 } else if (auto CurMethod =
2206 dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) {
2207 auto Self = CurMethod->getSelfDecl();
2208 if (Self->getType().isConstQualified()) {
2209 if (auto LI = dyn_cast<llvm::LoadInst>(Arg0->stripPointerCasts())) {
2210 llvm::Value *SelfAddr = CGF.GetAddrOfLocalVar(Self).getPointer();
2211 if (SelfAddr == LI->getPointerOperand()) {
2212 ReceiverCanBeNull = false;
2213 }
2214 }
2215 }
2216 }
2217
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002218 bool RequiresNullCheck = false;
John McCall5880fb82011-05-14 21:12:11 +00002219
James Y Knight9871db02019-02-05 16:42:33 +00002220 llvm::FunctionCallee Fn = nullptr;
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08002221 if (Method && Method->isDirectMethod()) {
2222 Fn = GenerateDirectMethod(Method, Method->getClassInterface());
2223 } else if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002224 if (ReceiverCanBeNull) RequiresNullCheck = true;
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002225 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002226 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00002227 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
2228 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2229 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +00002230 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
2231 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2232 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002233 } else {
Tim Northovere77cc392014-03-29 13:28:05 +00002234 // arm64 uses objc_msgSend for stret methods and yet null receiver check
2235 // must be made for it.
Ahmed Bougachaa3df87b2015-10-02 22:41:59 +00002236 if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002237 RequiresNullCheck = true;
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00002238 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002239 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00002240 }
John McCall1e3157b2015-09-10 22:27:50 +00002241
James Y Knight9871db02019-02-05 16:42:33 +00002242 // Cast function to proper signature
2243 llvm::Constant *BitcastFn = cast<llvm::Constant>(
2244 CGF.Builder.CreateBitCast(Fn.getCallee(), MSI.MessengerType));
2245
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002246 // We don't need to emit a null check to zero out an indirect result if the
2247 // result is ignored.
2248 if (Return.isUnused())
2249 RequiresNullCheck = false;
2250
John McCall1e3157b2015-09-10 22:27:50 +00002251 // Emit a null-check if there's a consumed argument other than the receiver.
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002252 if (!RequiresNullCheck && CGM.getLangOpts().ObjCAutoRefCount && Method) {
David Majnemer59f77922016-06-24 04:05:48 +00002253 for (const auto *ParamDecl : Method->parameters()) {
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002254 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
John McCall1e3157b2015-09-10 22:27:50 +00002255 RequiresNullCheck = true;
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00002256 break;
2257 }
2258 }
John McCall1e3157b2015-09-10 22:27:50 +00002259 }
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002260
2261 NullReturnState nullReturn;
2262 if (RequiresNullCheck) {
2263 nullReturn.init(CGF, Arg0);
2264 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002265
James Y Knight3933add2019-01-30 02:54:28 +00002266 llvm::CallBase *CallSite;
James Y Knight9871db02019-02-05 16:42:33 +00002267 CGCallee Callee = CGCallee::forDirect(BitcastFn);
John McCallb92ab1a2016-10-26 23:46:34 +00002268 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2269 &CallSite);
John McCall1e3157b2015-09-10 22:27:50 +00002270
2271 // Mark the call as noreturn if the method is marked noreturn and the
2272 // receiver cannot be null.
2273 if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
James Y Knight3933add2019-01-30 02:54:28 +00002274 CallSite->setDoesNotReturn();
John McCall1e3157b2015-09-10 22:27:50 +00002275 }
2276
Kuba Mracekbce5cea2017-06-30 16:28:15 +00002277 return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
John McCall1e3157b2015-09-10 22:27:50 +00002278 RequiresNullCheck ? Method : nullptr);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002279}
2280
John McCall3fd13f062015-10-21 18:06:47 +00002281static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT,
2282 bool pointee = false) {
2283 // Note that GC qualification applies recursively to C pointer types
2284 // that aren't otherwise decorated. This is weird, but it's probably
2285 // an intentional workaround to the unreliable placement of GC qualifiers.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002286 if (FQT.isObjCGCStrong())
2287 return Qualifiers::Strong;
John McCall3fd13f062015-10-21 18:06:47 +00002288
2289 if (FQT.isObjCGCWeak())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002290 return Qualifiers::Weak;
John McCall3fd13f062015-10-21 18:06:47 +00002291
2292 if (auto ownership = FQT.getObjCLifetime()) {
2293 // Ownership does not apply recursively to C pointer types.
2294 if (pointee) return Qualifiers::GCNone;
2295 switch (ownership) {
2296 case Qualifiers::OCL_Weak: return Qualifiers::Weak;
2297 case Qualifiers::OCL_Strong: return Qualifiers::Strong;
2298 case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone;
2299 case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?");
2300 case Qualifiers::OCL_None: llvm_unreachable("known nonzero");
2301 }
2302 llvm_unreachable("bad objc ownership");
2303 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002304
John McCall3fd13f062015-10-21 18:06:47 +00002305 // Treat unqualified retainable pointers as strong.
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002306 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
2307 return Qualifiers::Strong;
Fangrui Song6907ce22018-07-30 19:24:48 +00002308
John McCall3fd13f062015-10-21 18:06:47 +00002309 // Walk into C pointer types, but only in GC.
2310 if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) {
2311 if (const PointerType *PT = FQT->getAs<PointerType>())
2312 return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true);
2313 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002314
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002315 return Qualifiers::GCNone;
2316}
2317
John McCall3fd13f062015-10-21 18:06:47 +00002318namespace {
2319 struct IvarInfo {
2320 CharUnits Offset;
2321 uint64_t SizeInWords;
2322 IvarInfo(CharUnits offset, uint64_t sizeInWords)
2323 : Offset(offset), SizeInWords(sizeInWords) {}
2324
2325 // Allow sorting based on byte pos.
2326 bool operator<(const IvarInfo &other) const {
2327 return Offset < other.Offset;
2328 }
2329 };
2330
2331 /// A helper class for building GC layout strings.
2332 class IvarLayoutBuilder {
2333 CodeGenModule &CGM;
2334
2335 /// The start of the layout. Offsets will be relative to this value,
2336 /// and entries less than this value will be silently discarded.
2337 CharUnits InstanceBegin;
2338
2339 /// The end of the layout. Offsets will never exceed this value.
2340 CharUnits InstanceEnd;
2341
2342 /// Whether we're generating the strong layout or the weak layout.
2343 bool ForStrongLayout;
2344
2345 /// Whether the offsets in IvarsInfo might be out-of-order.
2346 bool IsDisordered = false;
2347
2348 llvm::SmallVector<IvarInfo, 8> IvarsInfo;
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002349
John McCall3fd13f062015-10-21 18:06:47 +00002350 public:
2351 IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
2352 CharUnits instanceEnd, bool forStrongLayout)
2353 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2354 ForStrongLayout(forStrongLayout) {
2355 }
2356
2357 void visitRecord(const RecordType *RT, CharUnits offset);
2358
2359 template <class Iterator, class GetOffsetFn>
Fangrui Song6907ce22018-07-30 19:24:48 +00002360 void visitAggregate(Iterator begin, Iterator end,
John McCall3fd13f062015-10-21 18:06:47 +00002361 CharUnits aggrOffset,
2362 const GetOffsetFn &getOffset);
2363
2364 void visitField(const FieldDecl *field, CharUnits offset);
2365
2366 /// Add the layout of a block implementation.
2367 void visitBlock(const CGBlockInfo &blockInfo);
2368
2369 /// Is there any information for an interesting bitmap?
2370 bool hasBitmapData() const { return !IvarsInfo.empty(); }
2371
2372 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2373 llvm::SmallVectorImpl<unsigned char> &buffer);
2374
2375 static void dump(ArrayRef<unsigned char> buffer) {
2376 const unsigned char *s = buffer.data();
2377 for (unsigned i = 0, e = buffer.size(); i < e; i++)
2378 if (!(s[i] & 0xf0))
2379 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
2380 else
2381 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
2382 printf("\n");
2383 }
2384 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00002385} // end anonymous namespace
John McCall3fd13f062015-10-21 18:06:47 +00002386
John McCall351762c2011-02-07 10:33:21 +00002387llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
2388 const CGBlockInfo &blockInfo) {
Fangrui Song6907ce22018-07-30 19:24:48 +00002389
Chris Lattnerece04092012-02-07 00:39:47 +00002390 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
John McCall460ce582015-10-22 18:38:17 +00002391 if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
John McCall351762c2011-02-07 10:33:21 +00002392 return nullPtr;
2393
John McCall3fd13f062015-10-21 18:06:47 +00002394 IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize,
2395 /*for strong layout*/ true);
2396
2397 builder.visitBlock(blockInfo);
2398
2399 if (!builder.hasBitmapData())
2400 return nullPtr;
2401
2402 llvm::SmallVector<unsigned char, 32> buffer;
2403 llvm::Constant *C = builder.buildBitmap(*this, buffer);
John McCallf5ea0722015-10-29 23:36:14 +00002404 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
John McCall3fd13f062015-10-21 18:06:47 +00002405 printf("\n block variable layout for block: ");
2406 builder.dump(buffer);
2407 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002408
John McCall3fd13f062015-10-21 18:06:47 +00002409 return C;
2410}
2411
2412void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00002413 // __isa is the first field in block descriptor and must assume by runtime's
2414 // convention that it is GC'able.
John McCall3fd13f062015-10-21 18:06:47 +00002415 IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1));
John McCall351762c2011-02-07 10:33:21 +00002416
2417 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2418
John McCall351762c2011-02-07 10:33:21 +00002419 // Ignore the optional 'this' capture: C++ objects are not assumed
2420 // to be GC'ed.
2421
John McCall3fd13f062015-10-21 18:06:47 +00002422 CharUnits lastFieldOffset;
2423
John McCall351762c2011-02-07 10:33:21 +00002424 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002425 for (const auto &CI : blockDecl->captures()) {
2426 const VarDecl *variable = CI.getVariable();
John McCall351762c2011-02-07 10:33:21 +00002427 QualType type = variable->getType();
2428
2429 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2430
2431 // Ignore constant captures.
2432 if (capture.isConstant()) continue;
2433
John McCall3fd13f062015-10-21 18:06:47 +00002434 CharUnits fieldOffset = capture.getOffset();
2435
2436 // Block fields are not necessarily ordered; if we detect that we're
2437 // adding them out-of-order, make sure we sort later.
2438 if (fieldOffset < lastFieldOffset)
2439 IsDisordered = true;
2440 lastFieldOffset = fieldOffset;
John McCall351762c2011-02-07 10:33:21 +00002441
2442 // __block variables are passed by their descriptor address.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002443 if (CI.isByRef()) {
John McCall3fd13f062015-10-21 18:06:47 +00002444 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00002445 continue;
John McCall351762c2011-02-07 10:33:21 +00002446 }
2447
2448 assert(!type->isArrayType() && "array variable should not be caught");
2449 if (const RecordType *record = type->getAs<RecordType>()) {
John McCall3fd13f062015-10-21 18:06:47 +00002450 visitRecord(record, fieldOffset);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00002451 continue;
2452 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002453
John McCall351762c2011-02-07 10:33:21 +00002454 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
John McCall351762c2011-02-07 10:33:21 +00002455
John McCall3fd13f062015-10-21 18:06:47 +00002456 if (GCAttr == Qualifiers::Strong) {
2457 assert(CGM.getContext().getTypeSize(type)
2458 == CGM.getTarget().getPointerWidth(0));
2459 IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
2460 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00002461 }
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00002462}
2463
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00002464/// getBlockCaptureLifetime - This routine returns life time of the captured
2465/// block variable for the purpose of block layout meta-data generation. FQT is
2466/// the type of the variable captured in the block.
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002467Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
2468 bool ByrefLayout) {
John McCall460ce582015-10-22 18:38:17 +00002469 // If it has an ownership qualifier, we're done.
2470 if (auto lifetime = FQT.getObjCLifetime())
2471 return lifetime;
2472
2473 // If it doesn't, and this is ARC, it has no ownership.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002474 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCall460ce582015-10-22 18:38:17 +00002475 return Qualifiers::OCL_None;
Fangrui Song6907ce22018-07-30 19:24:48 +00002476
John McCall460ce582015-10-22 18:38:17 +00002477 // In MRC, retainable pointers are owned by non-__block variables.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002478 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002479 return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
Fangrui Song6907ce22018-07-30 19:24:48 +00002480
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00002481 return Qualifiers::OCL_None;
2482}
2483
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002484void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
2485 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002486 CharUnits FieldOffset,
2487 CharUnits FieldSize) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002488 // __block variables are passed by their descriptor address.
2489 if (IsByref)
2490 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002491 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002492 else if (LifeTime == Qualifiers::OCL_Strong)
2493 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002494 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002495 else if (LifeTime == Qualifiers::OCL_Weak)
2496 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002497 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002498 else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2499 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002500 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002501 else
2502 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2503 FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002504 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002505}
2506
2507void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2508 const RecordDecl *RD,
2509 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002510 CharUnits BytePos, bool &HasUnion,
2511 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002512 bool IsUnion = (RD && RD->isUnion());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002513 CharUnits MaxUnionSize = CharUnits::Zero();
Craig Topper8a13c412014-05-21 05:09:00 +00002514 const FieldDecl *MaxField = nullptr;
2515 const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002516 CharUnits MaxFieldOffset = CharUnits::Zero();
2517 CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
Fangrui Song6907ce22018-07-30 19:24:48 +00002518
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002519 if (RecFields.empty())
2520 return;
John McCallc8e01702013-04-16 22:48:15 +00002521 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fangrui Song6907ce22018-07-30 19:24:48 +00002522
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002523 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2524 const FieldDecl *Field = RecFields[i];
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002525 // Note that 'i' here is actually the field index inside RD of Field,
2526 // although this dependency is hidden.
2527 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002528 CharUnits FieldOffset =
2529 CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
Fangrui Song6907ce22018-07-30 19:24:48 +00002530
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002531 // Skip over unnamed or bitfields
2532 if (!Field->getIdentifier() || Field->isBitField()) {
2533 LastFieldBitfieldOrUnnamed = Field;
2534 LastBitfieldOrUnnamedOffset = FieldOffset;
2535 continue;
2536 }
Craig Topper8a13c412014-05-21 05:09:00 +00002537
2538 LastFieldBitfieldOrUnnamed = nullptr;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002539 QualType FQT = Field->getType();
2540 if (FQT->isRecordType() || FQT->isUnionType()) {
2541 if (FQT->isUnionType())
2542 HasUnion = true;
Fangrui Song6907ce22018-07-30 19:24:48 +00002543
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002544 BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
2545 BytePos + FieldOffset, HasUnion);
2546 continue;
2547 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002548
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002549 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00002550 auto *CArray = cast<ConstantArrayType>(Array);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002551 uint64_t ElCount = CArray->getSize().getZExtValue();
2552 assert(CArray && "only array with known element size is supported");
2553 FQT = CArray->getElementType();
2554 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00002555 auto *CArray = cast<ConstantArrayType>(Array);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002556 ElCount *= CArray->getSize().getZExtValue();
2557 FQT = CArray->getElementType();
2558 }
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002559 if (FQT->isRecordType() && ElCount) {
2560 int OldIndex = RunSkipBlockVars.size() - 1;
2561 const RecordType *RT = FQT->getAs<RecordType>();
2562 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
2563 HasUnion);
Fangrui Song6907ce22018-07-30 19:24:48 +00002564
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002565 // Replicate layout information for each array element. Note that
2566 // one element is already done.
2567 uint64_t ElIx = 1;
2568 for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002569 CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002570 for (int i = OldIndex+1; i <= FirstIndex; ++i)
2571 RunSkipBlockVars.push_back(
2572 RUN_SKIP(RunSkipBlockVars[i].opcode,
2573 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2574 RunSkipBlockVars[i].block_var_size));
2575 }
2576 continue;
2577 }
2578 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002579 CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002580 if (IsUnion) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002581 CharUnits UnionIvarSize = FieldSize;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002582 if (UnionIvarSize > MaxUnionSize) {
2583 MaxUnionSize = UnionIvarSize;
2584 MaxField = Field;
2585 MaxFieldOffset = FieldOffset;
2586 }
2587 } else {
2588 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002589 getBlockCaptureLifetime(FQT, ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002590 BytePos + FieldOffset,
2591 FieldSize);
2592 }
2593 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002594
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002595 if (LastFieldBitfieldOrUnnamed) {
2596 if (LastFieldBitfieldOrUnnamed->isBitField()) {
2597 // Last field was a bitfield. Must update the info.
2598 uint64_t BitFieldSize
2599 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002600 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
Eli Friedman8cbca202012-11-06 22:15:52 +00002601 ((BitFieldSize % ByteSizeInBits) != 0);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002602 CharUnits Size = CharUnits::fromQuantity(UnsSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002603 Size += LastBitfieldOrUnnamedOffset;
2604 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002605 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2606 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002607 BytePos + LastBitfieldOrUnnamedOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002608 Size);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002609 } else {
2610 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2611 // Last field was unnamed. Must update skip info.
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002612 CharUnits FieldSize
2613 = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002614 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002615 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2616 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002617 BytePos + LastBitfieldOrUnnamedOffset,
2618 FieldSize);
2619 }
2620 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002621
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002622 if (MaxField)
2623 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002624 getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002625 BytePos + MaxFieldOffset,
2626 MaxUnionSize);
2627}
2628
2629void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002630 CharUnits BytePos,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002631 bool &HasUnion,
2632 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002633 const RecordDecl *RD = RT->getDecl();
Aaron Ballman62e47c42014-03-10 13:43:55 +00002634 SmallVector<const FieldDecl*, 16> Fields(RD->fields());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002635 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
2636 const llvm::StructLayout *RecLayout =
2637 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
Fangrui Song6907ce22018-07-30 19:24:48 +00002638
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002639 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002640}
2641
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002642/// InlineLayoutInstruction - This routine produce an inline instruction for the
2643/// block variable layout if it can. If not, it returns 0. Rules are as follow:
2644/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
2645/// an inline layout of value 0x0000000000000xyz is interpreted as follows:
2646/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
2647/// y captured object of BLOCK_LAYOUT_BYREF. Followed by
2648/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
2649/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
2650/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
2651uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2652 SmallVectorImpl<unsigned char> &Layout) {
2653 uint64_t Result = 0;
2654 if (Layout.size() <= 3) {
2655 unsigned size = Layout.size();
2656 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2657 unsigned char inst;
2658 enum BLOCK_LAYOUT_OPCODE opcode ;
2659 switch (size) {
2660 case 3:
2661 inst = Layout[0];
2662 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2663 if (opcode == BLOCK_LAYOUT_STRONG)
2664 strong_word_count = (inst & 0xF)+1;
2665 else
2666 return 0;
2667 inst = Layout[1];
2668 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2669 if (opcode == BLOCK_LAYOUT_BYREF)
2670 byref_word_count = (inst & 0xF)+1;
2671 else
2672 return 0;
2673 inst = Layout[2];
2674 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2675 if (opcode == BLOCK_LAYOUT_WEAK)
2676 weak_word_count = (inst & 0xF)+1;
2677 else
2678 return 0;
2679 break;
Fangrui Song6907ce22018-07-30 19:24:48 +00002680
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002681 case 2:
2682 inst = Layout[0];
2683 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2684 if (opcode == BLOCK_LAYOUT_STRONG) {
2685 strong_word_count = (inst & 0xF)+1;
2686 inst = Layout[1];
2687 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2688 if (opcode == BLOCK_LAYOUT_BYREF)
2689 byref_word_count = (inst & 0xF)+1;
2690 else if (opcode == BLOCK_LAYOUT_WEAK)
2691 weak_word_count = (inst & 0xF)+1;
2692 else
2693 return 0;
2694 }
2695 else if (opcode == BLOCK_LAYOUT_BYREF) {
2696 byref_word_count = (inst & 0xF)+1;
2697 inst = Layout[1];
2698 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2699 if (opcode == BLOCK_LAYOUT_WEAK)
2700 weak_word_count = (inst & 0xF)+1;
2701 else
2702 return 0;
2703 }
2704 else
2705 return 0;
2706 break;
Fangrui Song6907ce22018-07-30 19:24:48 +00002707
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002708 case 1:
2709 inst = Layout[0];
2710 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2711 if (opcode == BLOCK_LAYOUT_STRONG)
2712 strong_word_count = (inst & 0xF)+1;
2713 else if (opcode == BLOCK_LAYOUT_BYREF)
2714 byref_word_count = (inst & 0xF)+1;
2715 else if (opcode == BLOCK_LAYOUT_WEAK)
2716 weak_word_count = (inst & 0xF)+1;
2717 else
2718 return 0;
2719 break;
Fangrui Song6907ce22018-07-30 19:24:48 +00002720
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002721 default:
2722 return 0;
2723 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002724
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002725 // Cannot inline when any of the word counts is 15. Because this is one less
2726 // than the actual work count (so 15 means 16 actual word counts),
2727 // and we can only display 0 thru 15 word counts.
2728 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2729 return 0;
Fangrui Song6907ce22018-07-30 19:24:48 +00002730
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002731 unsigned count =
2732 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
Fangrui Song6907ce22018-07-30 19:24:48 +00002733
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002734 if (size == count) {
2735 if (strong_word_count)
2736 Result = strong_word_count;
2737 Result <<= 4;
2738 if (byref_word_count)
2739 Result += byref_word_count;
2740 Result <<= 4;
2741 if (weak_word_count)
2742 Result += weak_word_count;
2743 }
2744 }
2745 return Result;
2746}
2747
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002748llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
2749 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2750 if (RunSkipBlockVars.empty())
2751 return nullPtr;
John McCallc8e01702013-04-16 22:48:15 +00002752 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2753 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002754 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
Fangrui Song6907ce22018-07-30 19:24:48 +00002755
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002756 // Sort on byte position; captures might not be allocated in order,
2757 // and unions can do funny things.
2758 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2759 SmallVector<unsigned char, 16> Layout;
Fangrui Song6907ce22018-07-30 19:24:48 +00002760
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002761 unsigned size = RunSkipBlockVars.size();
2762 for (unsigned i = 0; i < size; i++) {
2763 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2764 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2765 CharUnits end_byte_pos = start_byte_pos;
2766 unsigned j = i+1;
2767 while (j < size) {
2768 if (opcode == RunSkipBlockVars[j].opcode) {
2769 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2770 i++;
2771 }
2772 else
2773 break;
2774 }
2775 CharUnits size_in_bytes =
2776 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2777 if (j < size) {
2778 CharUnits gap =
2779 RunSkipBlockVars[j].block_var_bytepos -
2780 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2781 size_in_bytes += gap;
2782 }
2783 CharUnits residue_in_bytes = CharUnits::Zero();
2784 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2785 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2786 size_in_bytes -= residue_in_bytes;
2787 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2788 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002789
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002790 unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
2791 while (size_in_words >= 16) {
2792 // Note that value in imm. is one less that the actual
2793 // value. So, 0xf means 16 words follow!
2794 unsigned char inst = (opcode << 4) | 0xf;
2795 Layout.push_back(inst);
2796 size_in_words -= 16;
2797 }
2798 if (size_in_words > 0) {
2799 // Note that value in imm. is one less that the actual
2800 // value. So, we subtract 1 away!
2801 unsigned char inst = (opcode << 4) | (size_in_words-1);
2802 Layout.push_back(inst);
2803 }
2804 if (residue_in_bytes > CharUnits::Zero()) {
2805 unsigned char inst =
2806 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
2807 Layout.push_back(inst);
2808 }
2809 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002810
John McCall7f416cc2015-09-08 08:05:57 +00002811 while (!Layout.empty()) {
2812 unsigned char inst = Layout.back();
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002813 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2814 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2815 Layout.pop_back();
2816 else
2817 break;
2818 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002819
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002820 uint64_t Result = InlineLayoutInstruction(Layout);
2821 if (Result != 0) {
2822 // Block variable layout instruction has been inlined.
2823 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2824 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002825 printf("\n Inline BYREF variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002826 else
John McCall7f416cc2015-09-08 08:05:57 +00002827 printf("\n Inline block variable layout: ");
2828 printf("0x0%" PRIx64 "", Result);
2829 if (auto numStrong = (Result & 0xF00) >> 8)
2830 printf(", BL_STRONG:%d", (int) numStrong);
2831 if (auto numByref = (Result & 0x0F0) >> 4)
2832 printf(", BL_BYREF:%d", (int) numByref);
2833 if (auto numWeak = (Result & 0x00F) >> 0)
2834 printf(", BL_WEAK:%d", (int) numWeak);
2835 printf(", BL_OPERATOR:0\n");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002836 }
Vedant Kumar3ed0df02015-12-21 19:43:25 +00002837 return llvm::ConstantInt::get(CGM.IntPtrTy, Result);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002838 }
Fangrui Song6907ce22018-07-30 19:24:48 +00002839
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002840 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2841 Layout.push_back(inst);
2842 std::string BitMap;
2843 for (unsigned i = 0, e = Layout.size(); i != e; i++)
2844 BitMap += Layout[i];
Fangrui Song6907ce22018-07-30 19:24:48 +00002845
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002846 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2847 if (ComputeByrefLayout)
John McCall7f416cc2015-09-08 08:05:57 +00002848 printf("\n Byref variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002849 else
John McCall7f416cc2015-09-08 08:05:57 +00002850 printf("\n Block variable layout: ");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002851 for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
2852 unsigned char inst = BitMap[i];
2853 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2854 unsigned delta = 1;
2855 switch (opcode) {
2856 case BLOCK_LAYOUT_OPERATOR:
2857 printf("BL_OPERATOR:");
2858 delta = 0;
2859 break;
2860 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2861 printf("BL_NON_OBJECT_BYTES:");
2862 break;
2863 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2864 printf("BL_NON_OBJECT_WORD:");
2865 break;
2866 case BLOCK_LAYOUT_STRONG:
2867 printf("BL_STRONG:");
2868 break;
2869 case BLOCK_LAYOUT_BYREF:
2870 printf("BL_BYREF:");
2871 break;
2872 case BLOCK_LAYOUT_WEAK:
2873 printf("BL_WEAK:");
2874 break;
2875 case BLOCK_LAYOUT_UNRETAINED:
2876 printf("BL_UNRETAINED:");
2877 break;
2878 }
2879 // Actual value of word count is one more that what is in the imm.
2880 // field of the instruction
2881 printf("%d", (inst & 0xf) + delta);
2882 if (i < e-1)
2883 printf(", ");
2884 else
2885 printf("\n");
2886 }
2887 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00002888
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00002889 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2890 /*ForceNonFragileABI=*/true,
2891 /*NullTerminate=*/false);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002892 return getConstantGEP(VMContext, Entry, 0, 0);
2893}
2894
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00002895static std::string getBlockLayoutInfoString(
2896 const SmallVectorImpl<CGObjCCommonMac::RUN_SKIP> &RunSkipBlockVars,
2897 bool HasCopyDisposeHelpers) {
2898 std::string Str;
2899 for (const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
2900 if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
2901 // Copy/dispose helpers don't have any information about
2902 // __unsafe_unretained captures, so unconditionally concatenate a string.
2903 Str += "u";
2904 } else if (HasCopyDisposeHelpers) {
2905 // Information about __strong, __weak, or byref captures has already been
2906 // encoded into the names of the copy/dispose helpers. We have to add a
2907 // string here only when the copy/dispose helpers aren't generated (which
2908 // happens when the block is non-escaping).
2909 continue;
2910 } else {
2911 switch (R.opcode) {
2912 case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
2913 Str += "s";
2914 break;
2915 case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
2916 Str += "r";
2917 break;
2918 case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
2919 Str += "w";
2920 break;
2921 default:
2922 continue;
2923 }
2924 }
2925 Str += llvm::to_string(R.block_var_bytepos.getQuantity());
2926 Str += "l" + llvm::to_string(R.block_var_size.getQuantity());
2927 }
2928 return Str;
2929}
2930
2931void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM,
2932 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002933 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
Fangrui Song6907ce22018-07-30 19:24:48 +00002934
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002935 RunSkipBlockVars.clear();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002936 bool hasUnion = false;
Fangrui Song6907ce22018-07-30 19:24:48 +00002937
John McCallc8e01702013-04-16 22:48:15 +00002938 unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0);
2939 unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002940 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
Fangrui Song6907ce22018-07-30 19:24:48 +00002941
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002942 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
Fangrui Song6907ce22018-07-30 19:24:48 +00002943
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002944 // Calculate the basic layout of the block structure.
2945 const llvm::StructLayout *layout =
2946 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
Fangrui Song6907ce22018-07-30 19:24:48 +00002947
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002948 // Ignore the optional 'this' capture: C++ objects are not assumed
2949 // to be GC'ed.
Fariborz Jahanian4cf177e2012-12-04 17:20:57 +00002950 if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
2951 UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
2952 blockInfo.BlockHeaderForcedGapOffset,
2953 blockInfo.BlockHeaderForcedGapSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002954 // Walk the captured variables.
Aaron Ballman9371dd22014-03-14 18:34:04 +00002955 for (const auto &CI : blockDecl->captures()) {
2956 const VarDecl *variable = CI.getVariable();
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002957 QualType type = variable->getType();
Fangrui Song6907ce22018-07-30 19:24:48 +00002958
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002959 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
Fangrui Song6907ce22018-07-30 19:24:48 +00002960
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002961 // Ignore constant captures.
2962 if (capture.isConstant()) continue;
Fangrui Song6907ce22018-07-30 19:24:48 +00002963
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002964 CharUnits fieldOffset =
2965 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fangrui Song6907ce22018-07-30 19:24:48 +00002966
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002967 assert(!type->isArrayType() && "array variable should not be caught");
Aaron Ballman9371dd22014-03-14 18:34:04 +00002968 if (!CI.isByRef())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002969 if (const RecordType *record = type->getAs<RecordType>()) {
2970 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2971 continue;
2972 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002973 CharUnits fieldSize;
Aaron Ballman9371dd22014-03-14 18:34:04 +00002974 if (CI.isByRef())
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002975 fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2976 else
2977 fieldSize = CGM.getContext().getTypeSizeInChars(type);
Aaron Ballman9371dd22014-03-14 18:34:04 +00002978 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002979 fieldOffset, fieldSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002980 }
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00002981}
2982
2983llvm::Constant *
2984CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2985 const CGBlockInfo &blockInfo) {
2986 fillRunSkipBlockVars(CGM, blockInfo);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002987 return getBitmapBlockLayout(false);
2988}
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002989
Akira Hatanaka2ec36f02018-08-17 15:46:07 +00002990std::string CGObjCCommonMac::getRCBlockLayoutStr(CodeGenModule &CGM,
2991 const CGBlockInfo &blockInfo) {
2992 fillRunSkipBlockVars(CGM, blockInfo);
2993 return getBlockLayoutInfoString(RunSkipBlockVars,
2994 blockInfo.needsCopyDisposeHelpers());
2995}
2996
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002997llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2998 QualType T) {
2999 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
3000 assert(!T->isArrayType() && "__block array variable should not be caught");
3001 CharUnits fieldOffset;
3002 RunSkipBlockVars.clear();
3003 bool hasUnion = false;
3004 if (const RecordType *record = T->getAs<RecordType>()) {
3005 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
3006 llvm::Constant *Result = getBitmapBlockLayout(true);
Vedant Kumar2f5bb1152015-12-21 20:21:15 +00003007 if (isa<llvm::ConstantInt>(Result))
3008 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00003009 return Result;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00003010 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00003011 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
3012 return nullPtr;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00003013}
3014
John McCall882987f2013-02-28 19:01:20 +00003015llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00003016 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00003017 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00003018 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00003019 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
3020
Owen Andersonade90fd2009-07-29 18:54:39 +00003021 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00003022 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003023}
3024
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00003025void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00003026 // FIXME: We shouldn't need this, the protocol decl should contain enough
3027 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00003028 DefinedProtocols.insert(PD->getIdentifier());
3029
3030 // If we have generated a forward reference to this protocol, emit
3031 // it now. Otherwise do nothing, the protocol objects are lazily
3032 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003033 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00003034 GetOrEmitProtocol(PD);
3035}
3036
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00003037llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00003038 if (DefinedProtocols.count(PD->getIdentifier()))
3039 return GetOrEmitProtocol(PD);
Fangrui Song6907ce22018-07-30 19:24:48 +00003040
Daniel Dunbarc475d422008-10-29 22:36:39 +00003041 return GetOrEmitProtocolRef(PD);
3042}
3043
Douglas Gregor24ae22c2016-04-01 23:23:52 +00003044llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
3045 CodeGenFunction &CGF,
3046 const ObjCInterfaceDecl *ID,
3047 ObjCCommonTypesHelper &ObjCTypes) {
James Y Knight9871db02019-02-05 16:42:33 +00003048 llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
Douglas Gregor24ae22c2016-04-01 23:23:52 +00003049
3050 llvm::Value *className =
3051 CGF.CGM.GetAddrOfConstantCString(ID->getObjCRuntimeNameAsString())
3052 .getPointer();
3053 ASTContext &ctx = CGF.CGM.getContext();
3054 className =
3055 CGF.Builder.CreateBitCast(className,
3056 CGF.ConvertType(
3057 ctx.getPointerType(ctx.CharTy.withConst())));
3058 llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className);
3059 call->setDoesNotThrow();
3060 return call;
3061}
3062
Daniel Dunbarb036db82008-08-13 03:21:16 +00003063/*
Rafael Espindolaf9e1e5e2014-02-20 14:09:04 +00003064// Objective-C 1.0 extensions
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003065struct _objc_protocol {
3066struct _objc_protocol_extension *isa;
3067char *protocol_name;
3068struct _objc_protocol_list *protocol_list;
3069struct _objc__method_prototype_list *instance_methods;
3070struct _objc__method_prototype_list *class_methods
3071};
Daniel Dunbarb036db82008-08-13 03:21:16 +00003072
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003073See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00003074*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00003075llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00003076 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbarc475d422008-10-29 22:36:39 +00003077
3078 // Early exit if a defining object has already been generated.
3079 if (Entry && Entry->hasInitializer())
3080 return Entry;
3081
Douglas Gregora715bff2012-01-01 19:51:50 +00003082 // Use the protocol definition, if there is one.
3083 if (const ObjCProtocolDecl *Def = PD->getDefinition())
3084 PD = Def;
3085
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003086 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00003087 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003088 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
3089
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003090 // Construct method lists.
John McCall176f8922016-11-30 02:39:18 +00003091 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003092
John McCall176f8922016-11-30 02:39:18 +00003093 ConstantInitBuilder builder(CGM);
3094 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
3095 values.add(EmitProtocolExtension(PD, methodLists));
3096 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
3097 values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
3098 PD->protocol_begin(), PD->protocol_end()));
3099 values.add(methodLists.emitMethodList(this, PD,
3100 ProtocolMethodLists::RequiredInstanceMethods));
3101 values.add(methodLists.emitMethodList(this, PD,
3102 ProtocolMethodLists::RequiredClassMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003103
Daniel Dunbarb036db82008-08-13 03:21:16 +00003104 if (Entry) {
Rafael Espindola5d117f32014-03-06 01:10:46 +00003105 // Already created, update the initializer.
Rafael Espindolab3262952014-05-09 00:43:37 +00003106 assert(Entry->hasPrivateLinkage());
John McCall176f8922016-11-30 02:39:18 +00003107 values.finishAndSetAsInitializer(Entry);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003108 } else {
John McCall176f8922016-11-30 02:39:18 +00003109 Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(),
3110 CGM.getPointerAlign(),
3111 /*constant*/ false,
3112 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003113 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
John McCallf9582a72012-03-30 21:29:05 +00003114
3115 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00003116 }
Rafael Espindola060062a2014-03-06 22:15:10 +00003117 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00003118
3119 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00003120}
3121
Daniel Dunbarc475d422008-10-29 22:36:39 +00003122llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003123 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
3124
3125 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00003126 // We use the initializer as a marker of whether this is a forward
3127 // reference or not. At module finalization we add the empty
3128 // contents for protocols which were referenced but never defined.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003129 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
3130 false, llvm::GlobalValue::PrivateLinkage,
3131 nullptr, "OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00003132 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00003133 // FIXME: Is this necessary? Why only for protocol?
Guillaume Chateletc79099e2019-10-03 13:00:29 +00003134 Entry->setAlignment(llvm::Align(4));
Daniel Dunbarb036db82008-08-13 03:21:16 +00003135 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003136
Daniel Dunbarb036db82008-08-13 03:21:16 +00003137 return Entry;
3138}
3139
3140/*
3141 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003142 uint32_t size;
3143 struct objc_method_description_list *optional_instance_methods;
3144 struct objc_method_description_list *optional_class_methods;
3145 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003146 const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00003147 struct objc_property_list *class_properties;
Daniel Dunbarb036db82008-08-13 03:21:16 +00003148 };
3149*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003150llvm::Constant *
3151CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
John McCall176f8922016-11-30 02:39:18 +00003152 const ProtocolMethodLists &methodLists) {
3153 auto optInstanceMethods =
3154 methodLists.emitMethodList(this, PD,
3155 ProtocolMethodLists::OptionalInstanceMethods);
3156 auto optClassMethods =
3157 methodLists.emitMethodList(this, PD,
3158 ProtocolMethodLists::OptionalClassMethods);
3159
3160 auto extendedMethodTypes =
3161 EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
3162 methodLists.emitExtendedTypesArray(this),
3163 ObjCTypes);
3164
3165 auto instanceProperties =
3166 EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD,
3167 ObjCTypes, false);
3168 auto classProperties =
3169 EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr,
3170 PD, ObjCTypes, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003171
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003172 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00003173 if (optInstanceMethods->isNullValue() &&
3174 optClassMethods->isNullValue() &&
3175 extendedMethodTypes->isNullValue() &&
3176 instanceProperties->isNullValue() &&
3177 classProperties->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003178 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003179 }
Daniel Dunbarb036db82008-08-13 03:21:16 +00003180
John McCall176f8922016-11-30 02:39:18 +00003181 uint64_t size =
3182 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3183
3184 ConstantInitBuilder builder(CGM);
3185 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3186 values.addInt(ObjCTypes.IntTy, size);
3187 values.add(optInstanceMethods);
3188 values.add(optClassMethods);
3189 values.add(instanceProperties);
3190 values.add(extendedMethodTypes);
3191 values.add(classProperties);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003192
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003193 // No special section, but goes in llvm.used
Akira Hatanaka187770d2019-05-09 17:43:52 +00003194 return CreateMetadataVar("_OBJC_PROTOCOLEXT_" + PD->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00003195 StringRef(), CGM.getPointerAlign(), true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003196}
3197
3198/*
3199 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00003200 struct objc_protocol_list *next;
3201 long count;
3202 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00003203 };
3204*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00003205llvm::Constant *
Zachary Turner41a9ee92017-10-11 23:54:34 +00003206CGObjCMac::EmitProtocolList(Twine name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00003207 ObjCProtocolDecl::protocol_iterator begin,
3208 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003209 // Just return null for empty protocol lists
John McCall176f8922016-11-30 02:39:18 +00003210 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00003211 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003212
John McCall176f8922016-11-30 02:39:18 +00003213 ConstantInitBuilder builder(CGM);
3214 auto values = builder.beginStruct();
Daniel Dunbarb036db82008-08-13 03:21:16 +00003215
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003216 // This field is only used by the runtime.
John McCall176f8922016-11-30 02:39:18 +00003217 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003218
John McCall176f8922016-11-30 02:39:18 +00003219 // Reserve a slot for the count.
3220 auto countSlot = values.addPlaceholder();
3221
3222 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3223 for (; begin != end; ++begin) {
3224 refsArray.add(GetProtocolRef(*begin));
3225 }
3226 auto count = refsArray.size();
3227
3228 // This list is null terminated.
3229 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3230
3231 refsArray.finishAndAddTo(values);
3232 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3233
3234 StringRef section;
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003235 if (CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00003236 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003237
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003238 llvm::GlobalVariable *GV =
Zachary Turner41a9ee92017-10-11 23:54:34 +00003239 CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false);
Owen Andersonade90fd2009-07-29 18:54:39 +00003240 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003241}
3242
Fangrui Song6907ce22018-07-30 19:24:48 +00003243static void
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003244PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
John McCall176f8922016-11-30 02:39:18 +00003245 SmallVectorImpl<const ObjCPropertyDecl *> &Properties,
Aaron Ballmandc4bea42014-03-13 18:47:37 +00003246 const ObjCProtocolDecl *Proto,
Manman Renad0e7912016-01-29 19:22:54 +00003247 bool IsClassProperty) {
Manman Renad0e7912016-01-29 19:22:54 +00003248 for (const auto *PD : Proto->properties()) {
3249 if (IsClassProperty != PD->isClassProperty())
3250 continue;
David Blaikie82e95a32014-11-19 07:49:47 +00003251 if (!PropertySet.insert(PD->getIdentifier()).second)
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003252 continue;
John McCall176f8922016-11-30 02:39:18 +00003253 Properties.push_back(PD);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003254 }
Akira Hatanaka20f005d2020-01-04 08:32:49 -08003255
3256 for (const auto *P : Proto->protocols())
3257 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003258}
3259
Daniel Dunbarb036db82008-08-13 03:21:16 +00003260/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003261 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00003262 const char * const name;
3263 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003264 };
3265
3266 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00003267 uint32_t entsize; // sizeof (struct _objc_property)
3268 uint32_t prop_count;
3269 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003270 };
3271*/
Zachary Turner41a9ee92017-10-11 23:54:34 +00003272llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
3273 const Decl *Container,
3274 const ObjCContainerDecl *OCD,
3275 const ObjCCommonTypesHelper &ObjCTypes,
3276 bool IsClassProperty) {
Manman Ren01b705e2016-04-19 19:05:03 +00003277 if (IsClassProperty) {
3278 // Make this entry NULL for OS X with deployment target < 10.11, for iOS
3279 // with deployment target < 9.0.
3280 const llvm::Triple &Triple = CGM.getTarget().getTriple();
3281 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3282 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3283 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3284 }
3285
John McCall176f8922016-11-30 02:39:18 +00003286 SmallVector<const ObjCPropertyDecl *, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00003287 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Nico Weber08c93332015-12-03 17:44:51 +00003288
Nico Weber08c93332015-12-03 17:44:51 +00003289 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3290 for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
Manman Renad0e7912016-01-29 19:22:54 +00003291 for (auto *PD : ClassExt->properties()) {
3292 if (IsClassProperty != PD->isClassProperty())
3293 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003294 PropertySet.insert(PD->getIdentifier());
John McCall176f8922016-11-30 02:39:18 +00003295 Properties.push_back(PD);
Nico Weber08c93332015-12-03 17:44:51 +00003296 }
Manman Renad0e7912016-01-29 19:22:54 +00003297
3298 for (const auto *PD : OCD->properties()) {
3299 if (IsClassProperty != PD->isClassProperty())
3300 continue;
Nico Weber08c93332015-12-03 17:44:51 +00003301 // Don't emit duplicate metadata for properties that were already in a
3302 // class extension.
3303 if (!PropertySet.insert(PD->getIdentifier()).second)
3304 continue;
John McCall176f8922016-11-30 02:39:18 +00003305 Properties.push_back(PD);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003306 }
Nico Weber08c93332015-12-03 17:44:51 +00003307
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003308 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Aaron Ballmana9f49e32014-03-13 20:55:22 +00003309 for (const auto *P : OID->all_referenced_protocols())
John McCall176f8922016-11-30 02:39:18 +00003310 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003311 }
3312 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
Aaron Ballman19a41762014-03-14 12:55:57 +00003313 for (const auto *P : CD->protocols())
John McCall176f8922016-11-30 02:39:18 +00003314 PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00003315 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003316
3317 // Return null for empty list.
3318 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003319 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003320
John McCall176f8922016-11-30 02:39:18 +00003321 unsigned propertySize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00003322 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
John McCall176f8922016-11-30 02:39:18 +00003323
3324 ConstantInitBuilder builder(CGM);
3325 auto values = builder.beginStruct();
3326 values.addInt(ObjCTypes.IntTy, propertySize);
3327 values.addInt(ObjCTypes.IntTy, Properties.size());
3328 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3329 for (auto PD : Properties) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08003330 if (PD->isDirectProperty())
3331 continue;
John McCall176f8922016-11-30 02:39:18 +00003332 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3333 property.add(GetPropertyName(PD->getIdentifier()));
3334 property.add(GetPropertyTypeString(PD, Container));
3335 property.finishAndAddTo(propertiesArray);
3336 }
3337 propertiesArray.finishAndAddTo(values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003338
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003339 StringRef Section;
3340 if (CGM.getTriple().isOSBinFormatMachO())
3341 Section = (ObjCABI == 2) ? "__DATA, __objc_const"
3342 : "__OBJC,__property,regular,no_dead_strip";
3343
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003344 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003345 CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003346 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003347}
3348
Zachary Turner41a9ee92017-10-11 23:54:34 +00003349llvm::Constant *
3350CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
3351 ArrayRef<llvm::Constant*> MethodTypes,
3352 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003353 // Return null for empty list.
3354 if (MethodTypes.empty())
3355 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3356
3357 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3358 MethodTypes.size());
3359 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
3360
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00003361 StringRef Section;
3362 if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3363 Section = "__DATA, __objc_const";
3364
3365 llvm::GlobalVariable *GV =
3366 CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00003367 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
3368}
3369
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003370/*
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003371 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003372 char *category_name;
3373 char *class_name;
3374 struct _objc_method_list *instance_methods;
3375 struct _objc_method_list *class_methods;
3376 struct _objc_protocol_list *protocols;
3377 uint32_t size; // <rdar://4585769>
3378 struct _objc_property_list *instance_properties;
Manman Ren96df0b32016-01-29 23:45:01 +00003379 struct _objc_property_list *class_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003380 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003381*/
Daniel Dunbar92992502008-08-15 22:20:32 +00003382void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00003383 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003384
Mike Stump18bb9282009-05-16 07:57:57 +00003385 // FIXME: This is poor design, the OCD should have a pointer to the category
3386 // decl. Additionally, note that Category can be null for the @implementation
3387 // w/o an @interface case. Sema should just create one for us as it does for
3388 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003389 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003390 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003391 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003392
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003393 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003394 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
3395 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003396
John McCall176f8922016-11-30 02:39:18 +00003397 ConstantInitBuilder Builder(CGM);
3398 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
Aaron Ballmanf26acce2014-03-13 19:50:17 +00003399
John McCall176f8922016-11-30 02:39:18 +00003400 enum {
3401 InstanceMethods,
3402 ClassMethods,
3403 NumMethodLists
3404 };
3405 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3406 for (const auto *MD : OCD->methods()) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08003407 if (!MD->isDirectMethod())
3408 Methods[unsigned(MD->isClassMethod())].push_back(MD);
John McCall176f8922016-11-30 02:39:18 +00003409 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003410
John McCall176f8922016-11-30 02:39:18 +00003411 Values.add(GetClassName(OCD->getName()));
3412 Values.add(GetClassName(Interface->getObjCRuntimeNameAsString()));
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00003413 LazySymbols.insert(Interface->getIdentifier());
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003414
John McCall176f8922016-11-30 02:39:18 +00003415 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3416 Methods[InstanceMethods]));
3417 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3418 Methods[ClassMethods]));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003419 if (Category) {
John McCall176f8922016-11-30 02:39:18 +00003420 Values.add(
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003421 EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003422 Category->protocol_begin(), Category->protocol_end()));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003423 } else {
John McCall176f8922016-11-30 02:39:18 +00003424 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003425 }
John McCall176f8922016-11-30 02:39:18 +00003426 Values.addInt(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003427
3428 // If there is no category @interface then there can be no properties.
3429 if (Category) {
Akira Hatanaka187770d2019-05-09 17:43:52 +00003430 Values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003431 OCD, Category, ObjCTypes, false));
Akira Hatanaka187770d2019-05-09 17:43:52 +00003432 Values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00003433 OCD, Category, ObjCTypes, true));
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003434 } else {
John McCall176f8922016-11-30 02:39:18 +00003435 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3436 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00003437 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003438
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003439 llvm::GlobalVariable *GV =
John McCall176f8922016-11-30 02:39:18 +00003440 CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values,
John McCall7f416cc2015-09-08 08:05:57 +00003441 "__OBJC,__category,regular,no_dead_strip",
3442 CGM.getPointerAlign(), true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003443 DefinedCategories.push_back(GV);
Justin Lebar5e83dfe2016-10-21 21:45:01 +00003444 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003445 // method definition entries must be clear for next implementation.
3446 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003447}
3448
John McCallef19dbb2012-10-17 04:53:23 +00003449enum FragileClassFlags {
John McCall460ce582015-10-22 18:38:17 +00003450 /// Apparently: is not a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003451 FragileABI_Class_Factory = 0x00001,
John McCall460ce582015-10-22 18:38:17 +00003452
3453 /// Is a meta-class.
John McCallef19dbb2012-10-17 04:53:23 +00003454 FragileABI_Class_Meta = 0x00002,
John McCall460ce582015-10-22 18:38:17 +00003455
3456 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003457 FragileABI_Class_HasCXXStructors = 0x02000,
John McCall460ce582015-10-22 18:38:17 +00003458
3459 /// Has hidden visibility.
John McCall09ec1ec2015-10-21 22:06:03 +00003460 FragileABI_Class_Hidden = 0x20000,
John McCall460ce582015-10-22 18:38:17 +00003461
3462 /// Class implementation was compiled under ARC.
3463 FragileABI_Class_CompiledByARC = 0x04000000,
3464
3465 /// Class implementation was compiled under MRC and has MRC weak ivars.
3466 /// Exclusive with CompiledByARC.
3467 FragileABI_Class_HasMRCWeakIvars = 0x08000000,
John McCallef19dbb2012-10-17 04:53:23 +00003468};
3469
3470enum NonFragileClassFlags {
3471 /// Is a meta-class.
3472 NonFragileABI_Class_Meta = 0x00001,
3473
3474 /// Is a root class.
3475 NonFragileABI_Class_Root = 0x00002,
3476
John McCall460ce582015-10-22 18:38:17 +00003477 /// Has a non-trivial constructor or destructor.
John McCallef19dbb2012-10-17 04:53:23 +00003478 NonFragileABI_Class_HasCXXStructors = 0x00004,
3479
3480 /// Has hidden visibility.
3481 NonFragileABI_Class_Hidden = 0x00010,
3482
3483 /// Has the exception attribute.
3484 NonFragileABI_Class_Exception = 0x00020,
3485
3486 /// (Obsolete) ARC-specific: this class has a .release_ivars method
3487 NonFragileABI_Class_HasIvarReleaser = 0x00040,
3488
3489 /// Class implementation was compiled under ARC.
John McCall0d54a172012-10-17 04:53:31 +00003490 NonFragileABI_Class_CompiledByARC = 0x00080,
3491
3492 /// Class has non-trivial destructors, but zero-initialization is okay.
John McCall460ce582015-10-22 18:38:17 +00003493 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100,
3494
3495 /// Class implementation was compiled under MRC and has MRC weak ivars.
3496 /// Exclusive with CompiledByARC.
3497 NonFragileABI_Class_HasMRCWeakIvars = 0x00200,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003498};
3499
John McCall460ce582015-10-22 18:38:17 +00003500static bool hasWeakMember(QualType type) {
3501 if (type.getObjCLifetime() == Qualifiers::OCL_Weak) {
3502 return true;
3503 }
3504
3505 if (auto recType = type->getAs<RecordType>()) {
3506 for (auto field : recType->getDecl()->fields()) {
3507 if (hasWeakMember(field->getType()))
3508 return true;
3509 }
3510 }
3511
3512 return false;
3513}
3514
3515/// For compatibility, we only want to set the "HasMRCWeakIvars" flag
3516/// (and actually fill in a layout string) if we really do have any
3517/// __weak ivars.
3518static bool hasMRCWeakIvars(CodeGenModule &CGM,
3519 const ObjCImplementationDecl *ID) {
3520 if (!CGM.getLangOpts().ObjCWeak) return false;
3521 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
3522
3523 for (const ObjCIvarDecl *ivar =
3524 ID->getClassInterface()->all_declared_ivar_begin();
3525 ivar; ivar = ivar->getNextIvar()) {
3526 if (hasWeakMember(ivar->getType()))
3527 return true;
3528 }
3529
3530 return false;
3531}
3532
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003533/*
3534 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003535 Class isa;
3536 Class super_class;
3537 const char *name;
3538 long version;
3539 long info;
3540 long instance_size;
3541 struct _objc_ivar_list *ivars;
3542 struct _objc_method_list *methods;
3543 struct _objc_cache *cache;
3544 struct _objc_protocol_list *protocols;
3545 // Objective-C 1.0 extensions (<rdr://4585769>)
3546 const char *ivar_layout;
3547 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003548 };
3549
3550 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003551*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003552void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Akira Hatanaka0c194462018-04-03 22:50:16 +00003553 IdentifierInfo *RuntimeName =
3554 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
3555 DefinedSymbols.insert(RuntimeName);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003556
Chris Lattner86d7d912008-11-24 03:54:41 +00003557 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003558 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003559 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003560 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003561 llvm::Constant *Protocols =
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003562 EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(),
3563 Interface->all_referenced_protocol_begin(),
3564 Interface->all_referenced_protocol_end());
John McCallef19dbb2012-10-17 04:53:23 +00003565 unsigned Flags = FragileABI_Class_Factory;
John McCall0d54a172012-10-17 04:53:31 +00003566 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCallef19dbb2012-10-17 04:53:23 +00003567 Flags |= FragileABI_Class_HasCXXStructors;
John McCall09ec1ec2015-10-21 22:06:03 +00003568
John McCall460ce582015-10-22 18:38:17 +00003569 bool hasMRCWeak = false;
3570
John McCall09ec1ec2015-10-21 22:06:03 +00003571 if (CGM.getLangOpts().ObjCAutoRefCount)
3572 Flags |= FragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00003573 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
3574 Flags |= FragileABI_Class_HasMRCWeakIvars;
John McCall09ec1ec2015-10-21 22:06:03 +00003575
John McCall3fd13f062015-10-21 18:06:47 +00003576 CharUnits Size =
3577 CGM.getContext().getASTObjCImplementationLayout(ID).getSize();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003578
3579 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00003580 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003581 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003582
John McCall176f8922016-11-30 02:39:18 +00003583 enum {
3584 InstanceMethods,
3585 ClassMethods,
3586 NumMethodLists
3587 };
3588 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3589 for (const auto *MD : ID->methods()) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08003590 if (!MD->isDirectMethod())
3591 Methods[unsigned(MD->isClassMethod())].push_back(MD);
John McCall176f8922016-11-30 02:39:18 +00003592 }
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003593
Aaron Ballmand85eff42014-03-14 15:02:45 +00003594 for (const auto *PID : ID->property_impls()) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003595 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08003596 if (PID->getPropertyDecl()->isDirectProperty())
3597 continue;
Adrian Prantl2073dd22019-11-04 14:28:14 -08003598 if (ObjCMethodDecl *MD = PID->getGetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003599 if (GetMethodDefinition(MD))
3600 Methods[InstanceMethods].push_back(MD);
Adrian Prantl2073dd22019-11-04 14:28:14 -08003601 if (ObjCMethodDecl *MD = PID->getSetterMethodDecl())
John McCall176f8922016-11-30 02:39:18 +00003602 if (GetMethodDefinition(MD))
3603 Methods[InstanceMethods].push_back(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003604 }
3605 }
3606
John McCall176f8922016-11-30 02:39:18 +00003607 ConstantInitBuilder builder(CGM);
3608 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3609 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003610 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003611 // Record a reference to the super class.
3612 LazySymbols.insert(Super->getIdentifier());
3613
John McCall176f8922016-11-30 02:39:18 +00003614 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3615 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003616 } else {
John McCall176f8922016-11-30 02:39:18 +00003617 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003618 }
John McCall176f8922016-11-30 02:39:18 +00003619 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003620 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003621 values.addInt(ObjCTypes.LongTy, 0);
3622 values.addInt(ObjCTypes.LongTy, Flags);
3623 values.addInt(ObjCTypes.LongTy, Size.getQuantity());
3624 values.add(EmitIvarList(ID, false));
3625 values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods,
3626 Methods[InstanceMethods]));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003627 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003628 values.addNullPointer(ObjCTypes.CachePtrTy);
3629 values.add(Protocols);
3630 values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size));
3631 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3632 /*isMetaclass*/ false));
3633
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003634 std::string Name("OBJC_CLASS_");
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003635 Name += ClassName;
3636 const char *Section = "__OBJC,__class,regular,no_dead_strip";
3637 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003638 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003639 if (GV) {
3640 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3641 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003642 values.finishAndSetAsInitializer(GV);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003643 GV->setSection(Section);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00003644 GV->setAlignment(CGM.getPointerAlign().getAsAlign());
Rafael Espindola060062a2014-03-06 22:15:10 +00003645 CGM.addCompilerUsedGlobal(GV);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003646 } else
John McCall176f8922016-11-30 02:39:18 +00003647 GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003648 DefinedClasses.push_back(GV);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00003649 ImplementedClasses.push_back(Interface);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003650 // method definition entries must be clear for next implementation.
3651 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003652}
3653
3654llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3655 llvm::Constant *Protocols,
John McCall176f8922016-11-30 02:39:18 +00003656 ArrayRef<const ObjCMethodDecl*> Methods) {
John McCallef19dbb2012-10-17 04:53:23 +00003657 unsigned Flags = FragileABI_Class_Meta;
Micah Villmowdd31ca12012-10-08 16:25:52 +00003658 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003659
John McCall457a04e2010-10-22 21:05:15 +00003660 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003661 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003662
John McCall176f8922016-11-30 02:39:18 +00003663 ConstantInitBuilder builder(CGM);
3664 auto values = builder.beginStruct(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003665 // The isa for the metaclass is the root of the hierarchy.
3666 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3667 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3668 Root = Super;
John McCall176f8922016-11-30 02:39:18 +00003669 values.addBitCast(GetClassName(Root->getObjCRuntimeNameAsString()),
3670 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003671 // The super class for the metaclass is emitted as the name of the
3672 // super class. The runtime fixes this up to point to the
3673 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003674 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
John McCall176f8922016-11-30 02:39:18 +00003675 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3676 ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003677 } else {
John McCall176f8922016-11-30 02:39:18 +00003678 values.addNullPointer(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003679 }
John McCall176f8922016-11-30 02:39:18 +00003680 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003681 // Version is always 0.
John McCall176f8922016-11-30 02:39:18 +00003682 values.addInt(ObjCTypes.LongTy, 0);
3683 values.addInt(ObjCTypes.LongTy, Flags);
3684 values.addInt(ObjCTypes.LongTy, Size);
3685 values.add(EmitIvarList(ID, true));
3686 values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods,
3687 Methods));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003688 // cache is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003689 values.addNullPointer(ObjCTypes.CachePtrTy);
3690 values.add(Protocols);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003691 // ivar_layout for metaclass is always NULL.
John McCall176f8922016-11-30 02:39:18 +00003692 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Renad0e7912016-01-29 19:22:54 +00003693 // The class extension is used to store class properties for metaclasses.
John McCall176f8922016-11-30 02:39:18 +00003694 values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/,
3695 /*isMetaclass*/true));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003696
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003697 std::string Name("OBJC_METACLASS_");
Benjamin Kramer1bbcbd02012-07-31 11:45:39 +00003698 Name += ID->getName();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003699
3700 // Check for a forward reference.
Rafael Espindola554256c2014-02-26 22:25:45 +00003701 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003702 if (GV) {
3703 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3704 "Forward metaclass reference has incorrect type.");
John McCall176f8922016-11-30 02:39:18 +00003705 values.finishAndSetAsInitializer(GV);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003706 } else {
John McCall176f8922016-11-30 02:39:18 +00003707 GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
3708 /*constant*/ false,
3709 llvm::GlobalValue::PrivateLinkage);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003710 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003711 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Rafael Espindola060062a2014-03-06 22:15:10 +00003712 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003713
3714 return GV;
3715}
3716
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003717llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003718 std::string Name = "OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003719
Mike Stump18bb9282009-05-16 07:57:57 +00003720 // FIXME: Should we look these up somewhere other than the module. Its a bit
3721 // silly since we only generate these while processing an implementation, so
3722 // exactly one pointer would work if know when we entered/exitted an
3723 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003724
3725 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00003726 // Previously, metaclass with internal linkage may have been defined.
3727 // pass 'true' as 2nd argument so it is returned.
Rafael Espindola21039aa2014-02-27 16:26:32 +00003728 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3729 if (!GV)
3730 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003731 llvm::GlobalValue::PrivateLinkage, nullptr,
3732 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003733
3734 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3735 "Forward metaclass reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003736 return GV;
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003737}
3738
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003739llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003740 std::string Name = "OBJC_CLASS_" + ID->getNameAsString();
Rafael Espindola21039aa2014-02-27 16:26:32 +00003741 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
3742
3743 if (!GV)
3744 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Craig Topper8a13c412014-05-21 05:09:00 +00003745 llvm::GlobalValue::PrivateLinkage, nullptr,
3746 Name);
Rafael Espindola21039aa2014-02-27 16:26:32 +00003747
3748 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3749 "Forward class metadata reference has incorrect type.");
Rafael Espindola21039aa2014-02-27 16:26:32 +00003750 return GV;
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003751}
3752
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003753/*
John McCall3fd13f062015-10-21 18:06:47 +00003754 Emit a "class extension", which in this specific context means extra
3755 data that doesn't fit in the normal fragile-ABI class structure, and
3756 has nothing to do with the language concept of a class extension.
3757
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003758 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003759 uint32_t size;
3760 const char *weak_ivar_layout;
3761 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003762 };
3763*/
3764llvm::Constant *
John McCall3fd13f062015-10-21 18:06:47 +00003765CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
Manman Renad0e7912016-01-29 19:22:54 +00003766 CharUnits InstanceSize, bool hasMRCWeakIvars,
John McCall176f8922016-11-30 02:39:18 +00003767 bool isMetaclass) {
3768 // Weak ivar layout.
3769 llvm::Constant *layout;
3770 if (isMetaclass) {
3771 layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
3772 } else {
3773 layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
3774 hasMRCWeakIvars);
3775 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003776
John McCall176f8922016-11-30 02:39:18 +00003777 // Properties.
3778 llvm::Constant *propertyList =
Akira Hatanaka187770d2019-05-09 17:43:52 +00003779 EmitPropertyList((isMetaclass ? Twine("_OBJC_$_CLASS_PROP_LIST_")
3780 : Twine("_OBJC_$_PROP_LIST_"))
John McCall176f8922016-11-30 02:39:18 +00003781 + ID->getName(),
3782 ID, ID->getClassInterface(), ObjCTypes, isMetaclass);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003783
3784 // Return null if no extension bits are used.
John McCall176f8922016-11-30 02:39:18 +00003785 if (layout->isNullValue() && propertyList->isNullValue()) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003786 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003787 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003788
John McCall176f8922016-11-30 02:39:18 +00003789 uint64_t size =
3790 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3791
3792 ConstantInitBuilder builder(CGM);
3793 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3794 values.addInt(ObjCTypes.IntTy, size);
3795 values.add(layout);
3796 values.add(propertyList);
3797
3798 return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values,
John McCall7f416cc2015-09-08 08:05:57 +00003799 "__OBJC,__class_ext,regular,no_dead_strip",
3800 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003801}
3802
3803/*
3804 struct objc_ivar {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003805 char *ivar_name;
3806 char *ivar_type;
3807 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003808 };
3809
3810 struct objc_ivar_list {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003811 int ivar_count;
3812 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003813 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003814*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003815llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003816 bool ForClass) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003817 // When emitting the root class GCC emits ivar entries for the
3818 // actual class structure. It is not clear if we need to follow this
3819 // behavior; for now lets try and get away with not doing it. If so,
3820 // the cleanest solution would be to make up an ObjCInterfaceDecl
3821 // for the class.
3822 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00003823 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003824
Jordy Rosea91768e2011-07-22 02:08:32 +00003825 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003826
John McCall176f8922016-11-30 02:39:18 +00003827 ConstantInitBuilder builder(CGM);
3828 auto ivarList = builder.beginStruct();
3829 auto countSlot = ivarList.addPlaceholder();
3830 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3831
Fangrui Song6907ce22018-07-30 19:24:48 +00003832 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00003833 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00003834 // Ignore unnamed bit-fields.
3835 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003836 continue;
John McCall176f8922016-11-30 02:39:18 +00003837
3838 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3839 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3840 ivar.add(GetMethodVarType(IVD));
3841 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3842 ivar.finishAndAddTo(ivars);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003843 }
3844
3845 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00003846 auto count = ivars.size();
3847 if (count == 0) {
3848 ivars.abandon();
3849 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00003850 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
John McCall176f8922016-11-30 02:39:18 +00003851 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003852
John McCall176f8922016-11-30 02:39:18 +00003853 ivars.finishAndAddTo(ivarList);
3854 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003855
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003856 llvm::GlobalVariable *GV;
3857 if (ForClass)
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00003858 GV =
John McCall176f8922016-11-30 02:39:18 +00003859 CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003860 "__OBJC,__class_vars,regular,no_dead_strip",
3861 CGM.getPointerAlign(), true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003862 else
John McCall176f8922016-11-30 02:39:18 +00003863 GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList,
John McCall7f416cc2015-09-08 08:05:57 +00003864 "__OBJC,__instance_vars,regular,no_dead_strip",
3865 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003866 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003867}
3868
John McCall176f8922016-11-30 02:39:18 +00003869/// Build a struct objc_method_description constant for the given method.
3870///
3871/// struct objc_method_description {
3872/// SEL method_name;
3873/// char *method_types;
3874/// };
3875void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
3876 const ObjCMethodDecl *MD) {
3877 auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy);
3878 description.addBitCast(GetMethodVarName(MD->getSelector()),
3879 ObjCTypes.SelectorPtrTy);
3880 description.add(GetMethodVarType(MD));
3881 description.finishAndAddTo(builder);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003882}
3883
John McCall176f8922016-11-30 02:39:18 +00003884/// Build a struct objc_method constant for the given method.
3885///
3886/// struct objc_method {
3887/// SEL method_name;
3888/// char *method_types;
3889/// void *method;
3890/// };
3891void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
3892 const ObjCMethodDecl *MD) {
3893 llvm::Function *fn = GetMethodDefinition(MD);
3894 assert(fn && "no definition registered for method");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003895
John McCall176f8922016-11-30 02:39:18 +00003896 auto method = builder.beginStruct(ObjCTypes.MethodTy);
3897 method.addBitCast(GetMethodVarName(MD->getSelector()),
3898 ObjCTypes.SelectorPtrTy);
3899 method.add(GetMethodVarType(MD));
3900 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
3901 method.finishAndAddTo(builder);
3902}
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003903
John McCall176f8922016-11-30 02:39:18 +00003904/// Build a struct objc_method_list or struct objc_method_description_list,
3905/// as appropriate.
3906///
3907/// struct objc_method_list {
3908/// struct objc_method_list *obsolete;
3909/// int count;
3910/// struct objc_method methods_list[count];
3911/// };
3912///
3913/// struct objc_method_description_list {
3914/// int count;
3915/// struct objc_method_description list[count];
3916/// };
Zachary Turner41a9ee92017-10-11 23:54:34 +00003917llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3918 ArrayRef<const ObjCMethodDecl *> methods) {
John McCall176f8922016-11-30 02:39:18 +00003919 StringRef prefix;
3920 StringRef section;
3921 bool forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003922 switch (MLT) {
3923 case MethodListType::CategoryInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003924 prefix = "OBJC_CATEGORY_INSTANCE_METHODS_";
3925 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3926 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003927 break;
3928 case MethodListType::CategoryClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003929 prefix = "OBJC_CATEGORY_CLASS_METHODS_";
3930 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3931 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003932 break;
3933 case MethodListType::InstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003934 prefix = "OBJC_INSTANCE_METHODS_";
3935 section = "__OBJC,__inst_meth,regular,no_dead_strip";
3936 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003937 break;
3938 case MethodListType::ClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003939 prefix = "OBJC_CLASS_METHODS_";
3940 section = "__OBJC,__cls_meth,regular,no_dead_strip";
3941 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003942 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003943 case MethodListType::ProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003944 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_";
3945 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3946 forProtocol = true;
3947 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003948 case MethodListType::ProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003949 prefix = "OBJC_PROTOCOL_CLASS_METHODS_";
3950 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3951 forProtocol = true;
3952 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003953 case MethodListType::OptionalProtocolInstanceMethods:
John McCall176f8922016-11-30 02:39:18 +00003954 prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3955 section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
3956 forProtocol = true;
3957 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003958 case MethodListType::OptionalProtocolClassMethods:
John McCall176f8922016-11-30 02:39:18 +00003959 prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3960 section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
3961 forProtocol = true;
3962 break;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00003963 }
3964
John McCall176f8922016-11-30 02:39:18 +00003965 // Return null for empty list.
3966 if (methods.empty())
3967 return llvm::Constant::getNullValue(forProtocol
3968 ? ObjCTypes.MethodDescriptionListPtrTy
3969 : ObjCTypes.MethodListPtrTy);
3970
3971 // For protocols, this is an objc_method_description_list, which has
3972 // a slightly different structure.
3973 if (forProtocol) {
3974 ConstantInitBuilder builder(CGM);
3975 auto values = builder.beginStruct();
3976 values.addInt(ObjCTypes.IntTy, methods.size());
3977 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3978 for (auto MD : methods) {
3979 emitMethodDescriptionConstant(methodArray, MD);
3980 }
3981 methodArray.finishAndAddTo(values);
3982
Zachary Turner41a9ee92017-10-11 23:54:34 +00003983 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
John McCall176f8922016-11-30 02:39:18 +00003984 CGM.getPointerAlign(), true);
3985 return llvm::ConstantExpr::getBitCast(GV,
3986 ObjCTypes.MethodDescriptionListPtrTy);
3987 }
3988
3989 // Otherwise, it's an objc_method_list.
3990 ConstantInitBuilder builder(CGM);
3991 auto values = builder.beginStruct();
3992 values.addNullPointer(ObjCTypes.Int8PtrTy);
3993 values.addInt(ObjCTypes.IntTy, methods.size());
3994 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3995 for (auto MD : methods) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08003996 if (!MD->isDirectMethod())
3997 emitMethodConstant(methodArray, MD);
John McCall176f8922016-11-30 02:39:18 +00003998 }
3999 methodArray.finishAndAddTo(values);
4000
Zachary Turner41a9ee92017-10-11 23:54:34 +00004001 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00004002 CGM.getPointerAlign(), true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00004003 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004004}
4005
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004006llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004007 const ObjCContainerDecl *CD) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08004008 llvm::Function *Method;
4009
4010 if (OMD->isDirectMethod()) {
4011 Method = GenerateDirectMethod(OMD, CD);
4012 } else {
4013 SmallString<256> Name;
4014 GetNameForMethod(OMD, CD, Name);
4015
4016 CodeGenTypes &Types = CGM.getTypes();
4017 llvm::FunctionType *MethodTy =
4018 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
4019 Method =
4020 llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage,
4021 Name.str(), &CGM.getModule());
4022 }
4023
4024 MethodDefinitions.insert(std::make_pair(OMD, Method));
4025
4026 return Method;
4027}
4028
4029llvm::Function *
4030CGObjCCommonMac::GenerateDirectMethod(const ObjCMethodDecl *OMD,
4031 const ObjCContainerDecl *CD) {
Alex Lorenzf3efd692019-12-06 14:24:37 -08004032 auto I = DirectMethodDefinitions.find(OMD->getCanonicalDecl());
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08004033 if (I != DirectMethodDefinitions.end())
4034 return I->second;
4035
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00004036 SmallString<256> Name;
Pierre Habouzit42f9d0c2019-12-19 01:25:03 -08004037 GetNameForMethod(OMD, CD, Name, /*ignoreCategoryNamespace*/true);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004038
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00004039 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00004040 llvm::FunctionType *MethodTy =
John McCalla729c622012-02-17 03:33:10 +00004041 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004042 llvm::Function *Method =
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08004043 llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4044 Name.str(), &CGM.getModule());
Alex Lorenzf3efd692019-12-06 14:24:37 -08004045 DirectMethodDefinitions.insert(std::make_pair(OMD->getCanonicalDecl(), Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004046
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004047 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00004048}
4049
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08004050void CGObjCCommonMac::GenerateDirectMethodPrologue(
4051 CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD,
4052 const ObjCContainerDecl *CD) {
4053 auto &Builder = CGF.Builder;
4054 bool ReceiverCanBeNull = true;
4055 auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl());
4056 auto selfValue = Builder.CreateLoad(selfAddr);
4057
4058 // Generate:
4059 //
4060 // /* for class methods only to force class lazy initialization */
4061 // self = [self self];
4062 //
4063 // /* unless the receiver is never NULL */
4064 // if (self == nil) {
4065 // return (ReturnType){ };
4066 // }
4067 //
4068 // _cmd = @selector(...)
4069 // ...
4070
4071 if (OMD->isClassMethod()) {
4072 const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);
4073 assert(OID &&
4074 "GenerateDirectMethod() should be called with the Class Interface");
4075 Selector SelfSel = GetNullarySelector("self", CGM.getContext());
4076 auto ResultType = CGF.getContext().getObjCIdType();
4077 RValue result;
4078 CallArgList Args;
4079
4080 // TODO: If this method is inlined, the caller might know that `self` is
4081 // already initialized; for example, it might be an ordinary Objective-C
4082 // method which always receives an initialized `self`, or it might have just
4083 // forced initialization on its own.
4084 //
4085 // We should find a way to eliminate this unnecessary initialization in such
4086 // cases in LLVM.
4087 result = GeneratePossiblySpecializedMessageSend(
4088 CGF, ReturnValueSlot(), ResultType, SelfSel, selfValue, Args, OID,
4089 nullptr, true);
4090 Builder.CreateStore(result.getScalarVal(), selfAddr);
4091
Pierre Habouzit42f9d0c2019-12-19 01:25:03 -08004092 // Nullable `Class` expressions cannot be messaged with a direct method
4093 // so the only reason why the receive can be null would be because
4094 // of weak linking.
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08004095 ReceiverCanBeNull = isWeakLinkedClass(OID);
4096 }
4097
4098 if (ReceiverCanBeNull) {
4099 llvm::BasicBlock *SelfIsNilBlock =
4100 CGF.createBasicBlock("objc_direct_method.self_is_nil");
4101 llvm::BasicBlock *ContBlock =
4102 CGF.createBasicBlock("objc_direct_method.cont");
4103
4104 // if (self == nil) {
4105 auto selfTy = cast<llvm::PointerType>(selfValue->getType());
4106 auto Zero = llvm::ConstantPointerNull::get(selfTy);
4107
4108 llvm::MDBuilder MDHelper(CGM.getLLVMContext());
4109 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock,
4110 ContBlock, MDHelper.createBranchWeights(1, 1 << 20));
4111
4112 CGF.EmitBlock(SelfIsNilBlock);
4113
4114 // return (ReturnType){ };
4115 auto retTy = OMD->getReturnType();
4116 Builder.SetInsertPoint(SelfIsNilBlock);
4117 if (!retTy->isVoidType()) {
4118 CGF.EmitNullInitialization(CGF.ReturnValue, retTy);
4119 }
4120 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
4121 // }
4122
4123 // rest of the body
4124 CGF.EmitBlock(ContBlock);
4125 Builder.SetInsertPoint(ContBlock);
4126 }
4127
4128 // only synthesize _cmd if it's referenced
4129 if (OMD->getCmdDecl()->isUsed()) {
4130 Builder.CreateStore(GetSelector(CGF, OMD),
4131 CGF.GetAddrOfLocalVar(OMD->getCmdDecl()));
4132 }
4133}
4134
Zachary Turner41a9ee92017-10-11 23:54:34 +00004135llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4136 ConstantStructBuilder &Init,
4137 StringRef Section,
4138 CharUnits Align,
4139 bool AddToUsed) {
Akira Hatanaka187770d2019-05-09 17:43:52 +00004140 llvm::GlobalValue::LinkageTypes LT =
4141 getLinkageTypeForObjCMetadata(CGM, Section);
John McCall176f8922016-11-30 02:39:18 +00004142 llvm::GlobalVariable *GV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00004143 Init.finishAndCreateGlobal(Name, Align, /*constant*/ false, LT);
John McCall176f8922016-11-30 02:39:18 +00004144 if (!Section.empty())
4145 GV->setSection(Section);
4146 if (AddToUsed)
4147 CGM.addCompilerUsedGlobal(GV);
4148 return GV;
4149}
4150
Zachary Turner41a9ee92017-10-11 23:54:34 +00004151llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
Alp Toker541d5072014-06-07 23:30:53 +00004152 llvm::Constant *Init,
4153 StringRef Section,
John McCall7f416cc2015-09-08 08:05:57 +00004154 CharUnits Align,
Alp Toker541d5072014-06-07 23:30:53 +00004155 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004156 llvm::Type *Ty = Init->getType();
Akira Hatanaka187770d2019-05-09 17:43:52 +00004157 llvm::GlobalValue::LinkageTypes LT =
4158 getLinkageTypeForObjCMetadata(CGM, Section);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004159 llvm::GlobalVariable *GV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00004160 new llvm::GlobalVariable(CGM.getModule(), Ty, false, LT, Init, Name);
Alp Toker541d5072014-06-07 23:30:53 +00004161 if (!Section.empty())
Daniel Dunbar30c65362009-03-09 20:09:19 +00004162 GV->setSection(Section);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00004163 GV->setAlignment(Align.getAsAlign());
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00004164 if (AddToUsed)
Rafael Espindola060062a2014-03-06 22:15:10 +00004165 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00004166 return GV;
4167}
4168
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004169llvm::GlobalVariable *
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004170CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type,
4171 bool ForceNonFragileABI,
4172 bool NullTerminate) {
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004173 StringRef Label;
4174 switch (Type) {
4175 case ObjCLabelType::ClassName: Label = "OBJC_CLASS_NAME_"; break;
4176 case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break;
4177 case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break;
4178 case ObjCLabelType::PropertyName: Label = "OBJC_PROP_NAME_ATTR_"; break;
4179 }
4180
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004181 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
4182
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004183 StringRef Section;
4184 switch (Type) {
4185 case ObjCLabelType::ClassName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004186 Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals"
4187 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004188 break;
4189 case ObjCLabelType::MethodVarName:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004190 Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
4191 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004192 break;
4193 case ObjCLabelType::MethodVarType:
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004194 Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals"
4195 : "__TEXT,__cstring,cstring_literals";
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004196 break;
4197 case ObjCLabelType::PropertyName:
4198 Section = "__TEXT,__cstring,cstring_literals";
4199 break;
4200 }
4201
Saleem Abdulrasool82f6add2016-09-20 18:38:54 +00004202 llvm::Constant *Value =
4203 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004204 llvm::GlobalVariable *GV =
Saleem Abdulrasool0c54dc82016-09-18 16:12:04 +00004205 new llvm::GlobalVariable(CGM.getModule(), Value->getType(),
4206 /*isConstant=*/true,
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004207 llvm::GlobalValue::PrivateLinkage, Value, Label);
Saleem Abdulrasool3f307512016-09-18 16:12:14 +00004208 if (CGM.getTriple().isOSBinFormatMachO())
4209 GV->setSection(Section);
4210 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00004211 GV->setAlignment(CharUnits::One().getAsAlign());
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00004212 CGM.addCompilerUsedGlobal(GV);
4213
4214 return GV;
4215}
4216
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004217llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004218 // Abuse this interface function as a place to finalize.
4219 FinishModule();
Craig Topper8a13c412014-05-21 05:09:00 +00004220 return nullptr;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00004221}
4222
James Y Knight9871db02019-02-05 16:42:33 +00004223llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00004224 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00004225}
4226
James Y Knight9871db02019-02-05 16:42:33 +00004227llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00004228 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00004229}
4230
James Y Knight9871db02019-02-05 16:42:33 +00004231llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
4232 bool copy) {
Ted Kremeneke65b0862012-03-06 20:05:56 +00004233 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
4234}
4235
James Y Knight9871db02019-02-05 16:42:33 +00004236llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
David Chisnall168b80f2010-12-26 22:13:16 +00004237 return ObjCTypes.getCopyStructFn();
4238}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004239
James Y Knight9871db02019-02-05 16:42:33 +00004240llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00004241 return ObjCTypes.getCopyStructFn();
4242}
4243
James Y Knight9871db02019-02-05 16:42:33 +00004244llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
David Chisnall0d75e062012-12-17 18:54:24 +00004245 return ObjCTypes.getCppAtomicObjectFunction();
4246}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004247
James Y Knight9871db02019-02-05 16:42:33 +00004248llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00004249 return ObjCTypes.getCppAtomicObjectFunction();
4250}
4251
James Y Knight9871db02019-02-05 16:42:33 +00004252llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00004253 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00004254}
4255
John McCallbd309292010-07-06 01:34:17 +00004256void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
4257 return EmitTryOrSynchronizedStmt(CGF, S);
4258}
4259
4260void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
4261 const ObjCAtSynchronizedStmt &S) {
4262 return EmitTryOrSynchronizedStmt(CGF, S);
4263}
4264
John McCall65bea082010-07-21 06:59:36 +00004265namespace {
David Blaikie7e70d682015-08-18 22:40:54 +00004266 struct PerformFragileFinally final : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00004267 const Stmt &S;
John McCall7f416cc2015-09-08 08:05:57 +00004268 Address SyncArgSlot;
4269 Address CallTryExitVar;
4270 Address ExceptionData;
John McCall65bea082010-07-21 06:59:36 +00004271 ObjCTypesHelper &ObjCTypes;
4272 PerformFragileFinally(const Stmt *S,
John McCall7f416cc2015-09-08 08:05:57 +00004273 Address SyncArgSlot,
4274 Address CallTryExitVar,
4275 Address ExceptionData,
John McCall65bea082010-07-21 06:59:36 +00004276 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00004277 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00004278 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4279
Craig Topper4f12f102014-03-12 06:41:41 +00004280 void Emit(CodeGenFunction &CGF, Flags flags) override {
John McCall65bea082010-07-21 06:59:36 +00004281 // Check whether we need to call objc_exception_try_exit.
4282 // In optimized code, this branch will always be folded.
4283 llvm::BasicBlock *FinallyCallExit =
4284 CGF.createBasicBlock("finally.call_exit");
4285 llvm::BasicBlock *FinallyNoCallExit =
4286 CGF.createBasicBlock("finally.no_call_exit");
4287 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
4288 FinallyCallExit, FinallyNoCallExit);
4289
4290 CGF.EmitBlock(FinallyCallExit);
John McCall882987f2013-02-28 19:01:20 +00004291 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004292 ExceptionData.getPointer());
John McCall65bea082010-07-21 06:59:36 +00004293
4294 CGF.EmitBlock(FinallyNoCallExit);
4295
4296 if (isa<ObjCAtTryStmt>(S)) {
4297 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00004298 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
John McCall638d4f52013-04-03 00:56:07 +00004299 // Don't try to do the @finally if this is an EH cleanup.
4300 if (flags.isForEHCleanup()) return;
4301
John McCallcebe0ca2010-08-11 00:16:14 +00004302 // Save the current cleanup destination in case there's
4303 // control flow inside the finally statement.
4304 llvm::Value *CurCleanupDest =
4305 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
4306
John McCall65bea082010-07-21 06:59:36 +00004307 CGF.EmitStmt(FinallyStmt->getFinallyBody());
4308
John McCallcebe0ca2010-08-11 00:16:14 +00004309 if (CGF.HaveInsertPoint()) {
4310 CGF.Builder.CreateStore(CurCleanupDest,
4311 CGF.getNormalCleanupDestSlot());
4312 } else {
4313 // Currently, the end of the cleanup must always exist.
4314 CGF.EnsureInsertPoint();
4315 }
4316 }
John McCall65bea082010-07-21 06:59:36 +00004317 } else {
4318 // Emit objc_sync_exit(expr); as finally's sole statement for
4319 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00004320 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall882987f2013-02-28 19:01:20 +00004321 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg);
John McCall65bea082010-07-21 06:59:36 +00004322 }
4323 }
4324 };
John McCall42227ed2010-07-31 23:20:56 +00004325
4326 class FragileHazards {
4327 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004328 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00004329 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
4330
4331 llvm::InlineAsm *ReadHazard;
4332 llvm::InlineAsm *WriteHazard;
4333
4334 llvm::FunctionType *GetAsmFnType();
4335
4336 void collectLocals();
4337 void emitReadHazard(CGBuilderTy &Builder);
4338
4339 public:
4340 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00004341
John McCall42227ed2010-07-31 23:20:56 +00004342 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00004343 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004344 };
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00004345} // end anonymous namespace
John McCall42227ed2010-07-31 23:20:56 +00004346
4347/// Create the fragile-ABI read and write hazards based on the current
4348/// state of the function, which is presumed to be immediately prior
4349/// to a @try block. These hazards are used to maintain correct
4350/// semantics in the face of optimization and the fragile ABI's
4351/// cavalier use of setjmp/longjmp.
4352FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
4353 collectLocals();
4354
4355 if (Locals.empty()) return;
4356
4357 // Collect all the blocks in the function.
4358 for (llvm::Function::iterator
4359 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
4360 BlocksBeforeTry.insert(&*I);
4361
4362 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4363
4364 // Create a read hazard for the allocas. This inhibits dead-store
4365 // optimizations and forces the values to memory. This hazard is
4366 // inserted before any 'throwing' calls in the protected scope to
4367 // reflect the possibility that the variables might be read from the
4368 // catch block if the call throws.
4369 {
4370 std::string Constraint;
4371 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
4372 if (I) Constraint += ',';
4373 Constraint += "*m";
4374 }
4375
4376 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
4377 }
4378
4379 // Create a write hazard for the allocas. This inhibits folding
4380 // loads across the hazard. This hazard is inserted at the
4381 // beginning of the catch path to reflect the possibility that the
4382 // variables might have been written within the protected scope.
4383 {
4384 std::string Constraint;
4385 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
4386 if (I) Constraint += ',';
4387 Constraint += "=*m";
4388 }
4389
4390 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
4391 }
4392}
4393
4394/// Emit a write hazard at the current location.
4395void FragileHazards::emitWriteHazard() {
4396 if (Locals.empty()) return;
4397
John McCall882987f2013-02-28 19:01:20 +00004398 CGF.EmitNounwindRuntimeCall(WriteHazard, Locals);
John McCall42227ed2010-07-31 23:20:56 +00004399}
4400
John McCall42227ed2010-07-31 23:20:56 +00004401void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
4402 assert(!Locals.empty());
John McCall882987f2013-02-28 19:01:20 +00004403 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4404 call->setDoesNotThrow();
4405 call->setCallingConv(CGF.getRuntimeCC());
John McCall42227ed2010-07-31 23:20:56 +00004406}
4407
4408/// Emit read hazards in all the protected blocks, i.e. all the blocks
4409/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00004410void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00004411 if (Locals.empty()) return;
4412
John McCall7f416cc2015-09-08 08:05:57 +00004413 CGBuilderTy Builder(CGF, CGF.getLLVMContext());
John McCall42227ed2010-07-31 23:20:56 +00004414
4415 // Iterate through all blocks, skipping those prior to the try.
4416 for (llvm::Function::iterator
4417 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
4418 llvm::BasicBlock &BB = *FI;
4419 if (BlocksBeforeTry.count(&BB)) continue;
4420
4421 // Walk through all the calls in the block.
4422 for (llvm::BasicBlock::iterator
4423 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
4424 llvm::Instruction &I = *BI;
4425
4426 // Ignore instructions that aren't non-intrinsic calls.
4427 // These are the only calls that can possibly call longjmp.
James Y Knight3933add2019-01-30 02:54:28 +00004428 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
4429 continue;
John McCall42227ed2010-07-31 23:20:56 +00004430 if (isa<llvm::IntrinsicInst>(I))
4431 continue;
4432
4433 // Ignore call sites marked nounwind. This may be questionable,
4434 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
James Y Knight3933add2019-01-30 02:54:28 +00004435 if (cast<llvm::CallBase>(I).doesNotThrow())
4436 continue;
John McCall42227ed2010-07-31 23:20:56 +00004437
John McCall2dd7d442010-08-04 05:59:32 +00004438 // Insert a read hazard before the call. This will ensure that
4439 // any writes to the locals are performed before making the
4440 // call. If the call throws, then this is sufficient to
4441 // guarantee correctness as long as it doesn't also write to any
4442 // locals.
John McCall42227ed2010-07-31 23:20:56 +00004443 Builder.SetInsertPoint(&BB, BI);
4444 emitReadHazard(Builder);
4445 }
4446 }
4447}
4448
John McCall7f416cc2015-09-08 08:05:57 +00004449static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) {
4450 if (V.isValid()) S.insert(V.getPointer());
4451}
4452
John McCall42227ed2010-07-31 23:20:56 +00004453void FragileHazards::collectLocals() {
4454 // Compute a set of allocas to ignore.
4455 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
4456 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
4457 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00004458
4459 // Collect all the allocas currently in the function. This is
4460 // probably way too aggressive.
4461 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
4462 for (llvm::BasicBlock::iterator
4463 I = Entry.begin(), E = Entry.end(); I != E; ++I)
4464 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
4465 Locals.push_back(&*I);
4466}
4467
4468llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004469 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00004470 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
4471 tys[i] = Locals[i]->getType();
4472 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00004473}
4474
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004475/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004476
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004477 Objective-C setjmp-longjmp (sjlj) Exception Handling
4478 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004479
John McCallbd309292010-07-06 01:34:17 +00004480 A catch buffer is a setjmp buffer plus:
4481 - a pointer to the exception that was caught
4482 - a pointer to the previous exception data buffer
4483 - two pointers of reserved storage
4484 Therefore catch buffers form a stack, with a pointer to the top
4485 of the stack kept in thread-local storage.
4486
4487 objc_exception_try_enter pushes a catch buffer onto the EH stack.
4488 objc_exception_try_exit pops the given catch buffer, which is
4489 required to be the top of the EH stack.
4490 objc_exception_throw pops the top of the EH stack, writes the
4491 thrown exception into the appropriate field, and longjmps
4492 to the setjmp buffer. It crashes the process (with a printf
4493 and an abort()) if there are no catch buffers on the stack.
4494 objc_exception_extract just reads the exception pointer out of the
4495 catch buffer.
4496
4497 There's no reason an implementation couldn't use a light-weight
4498 setjmp here --- something like __builtin_setjmp, but API-compatible
4499 with the heavyweight setjmp. This will be more important if we ever
4500 want to implement correct ObjC/C++ exception interactions for the
4501 fragile ABI.
4502
4503 Note that for this use of setjmp/longjmp to be correct, we may need
4504 to mark some local variables volatile: if a non-volatile local
4505 variable is modified between the setjmp and the longjmp, it has
4506 indeterminate value. For the purposes of LLVM IR, it may be
4507 sufficient to make loads and stores within the @try (to variables
4508 declared outside the @try) volatile. This is necessary for
4509 optimized correctness, but is not currently being done; this is
4510 being tracked as rdar://problem/8160285
4511
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004512 The basic framework for a @try-catch-finally is as follows:
4513 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004514 objc_exception_data d;
4515 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00004516 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004517
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004518 objc_exception_try_enter(&d);
4519 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004520 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004521 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004522 // exception path
4523 id _caught = objc_exception_extract(&d);
4524
4525 // enter new try scope for handlers
4526 if (!setjmp(d.jmp_buf)) {
4527 ... match exception and execute catch blocks ...
4528
4529 // fell off end, rethrow.
4530 _rethrow = _caught;
4531 ... jump-through-finally to finally_rethrow ...
4532 } else {
4533 // exception in catch block
4534 _rethrow = objc_exception_extract(&d);
4535 _call_try_exit = false;
4536 ... jump-through-finally to finally_rethrow ...
4537 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004538 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004539 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004540
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004541 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00004542 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004543 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00004544
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004545 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004546 ... dispatch to finally destination ...
4547
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004548 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004549 objc_exception_throw(_rethrow);
4550
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004551 finally_end:
4552 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004553
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004554 This framework differs slightly from the one gcc uses, in that gcc
4555 uses _rethrow to determine if objc_exception_try_exit should be called
4556 and if the object should be rethrown. This breaks in the face of
4557 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004558
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004559 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004560
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004561 - If there are no catch blocks, then we avoid emitting the second
4562 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004563
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004564 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
4565 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004566
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004567 - FIXME: If there is no @finally block we can do a few more
4568 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004569
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004570 Rethrows and Jumps-Through-Finally
4571 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004572
John McCallbd309292010-07-06 01:34:17 +00004573 '@throw;' is supported by pushing the currently-caught exception
4574 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004575
John McCallbd309292010-07-06 01:34:17 +00004576 Branches through the @finally block are handled with an ordinary
4577 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
4578 exceptions are not compatible with C++ exceptions, and this is
4579 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004580
John McCallbd309292010-07-06 01:34:17 +00004581 @synchronized(expr) { stmt; } is emitted as if it were:
4582 id synch_value = expr;
4583 objc_sync_enter(synch_value);
4584 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004585*/
4586
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00004587void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
4588 const Stmt &S) {
4589 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00004590
4591 // A destination for the fall-through edges of the catch handlers to
4592 // jump to.
4593 CodeGenFunction::JumpDest FinallyEnd =
4594 CGF.getJumpDestInCurrentScope("finally.end");
4595
4596 // A destination for the rethrow edge of the catch handlers to jump
4597 // to.
4598 CodeGenFunction::JumpDest FinallyRethrow =
4599 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004600
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004601 // For @synchronized, call objc_sync_enter(sync.expr). The
4602 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00004603 // @synchronized. We can't avoid a temp here because we need the
4604 // value to be preserved. If the backend ever does liveness
4605 // correctly after setjmp, this will be unnecessary.
John McCall7f416cc2015-09-08 08:05:57 +00004606 Address SyncArgSlot = Address::invalid();
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004607 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00004608 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004609 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4610 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004611 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);
John McCall2dd7d442010-08-04 05:59:32 +00004612
John McCall7f416cc2015-09-08 08:05:57 +00004613 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(),
4614 CGF.getPointerAlign(), "sync.arg");
John McCall2dd7d442010-08-04 05:59:32 +00004615 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00004616 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004617
John McCall2dd7d442010-08-04 05:59:32 +00004618 // Allocate memory for the setjmp buffer. This needs to be kept
4619 // live throughout the try and catch blocks.
John McCall7f416cc2015-09-08 08:05:57 +00004620 Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
4621 CGF.getPointerAlign(),
4622 "exceptiondata.ptr");
John McCall2dd7d442010-08-04 05:59:32 +00004623
John McCall42227ed2010-07-31 23:20:56 +00004624 // Create the fragile hazards. Note that this will not capture any
4625 // of the allocas required for exception processing, but will
4626 // capture the current basic block (which extends all the way to the
4627 // setjmp call) as "before the @try".
4628 FragileHazards Hazards(CGF);
4629
John McCallbd309292010-07-06 01:34:17 +00004630 // Create a flag indicating whether the cleanup needs to call
4631 // objc_exception_try_exit. This is true except when
4632 // - no catches match and we're branching through the cleanup
4633 // just to rethrow the exception, or
4634 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00004635 // The setjmp-safety rule here is that we should always store to this
4636 // variable in a place that dominates the branch through the cleanup
4637 // without passing through any setjmps.
John McCall7f416cc2015-09-08 08:05:57 +00004638 Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
4639 CharUnits::One(),
4640 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004641
John McCall9916e3f2010-10-04 23:42:51 +00004642 // A slot containing the exception to rethrow. Only needed when we
4643 // have both a @catch and a @finally.
John McCall7f416cc2015-09-08 08:05:57 +00004644 Address PropagatingExnVar = Address::invalid();
John McCall9916e3f2010-10-04 23:42:51 +00004645
John McCallbd309292010-07-06 01:34:17 +00004646 // Push a normal cleanup to leave the try scope.
John McCall638d4f52013-04-03 00:56:07 +00004647 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00004648 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00004649 CallTryExitVar,
4650 ExceptionData,
4651 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00004652
4653 // Enter a try block:
4654 // - Call objc_exception_try_enter to push ExceptionData on top of
4655 // the EH stack.
Nico Weber6307cf02015-02-26 20:43:00 +00004656 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004657 ExceptionData.getPointer());
John McCallbd309292010-07-06 01:34:17 +00004658
4659 // - Call setjmp on the exception data buffer.
4660 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
4661 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
David Blaikie6b2a8302015-04-03 17:47:16 +00004662 llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
John McCall7f416cc2015-09-08 08:05:57 +00004663 ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes,
4664 "setjmp_buffer");
Nico Weber6307cf02015-02-26 20:43:00 +00004665 llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
4666 ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004667 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00004668
4669 // If setjmp returned 0, enter the protected block; otherwise,
4670 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00004671 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
4672 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00004673 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00004674 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4675 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004676
John McCallbd309292010-07-06 01:34:17 +00004677 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004678 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00004679 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004680 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00004681 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00004682
4683 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004684
John McCallbd309292010-07-06 01:34:17 +00004685 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00004686 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004687
John McCall42227ed2010-07-31 23:20:56 +00004688 // Don't optimize loads of the in-scope locals across this point.
4689 Hazards.emitWriteHazard();
4690
John McCallbd309292010-07-06 01:34:17 +00004691 // For a @synchronized (or a @try with no catches), just branch
4692 // through the cleanup to the rethrow block.
4693 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4694 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00004695 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004696 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00004697
4698 // Otherwise, we have to match against the caught exceptions.
4699 } else {
John McCall2dd7d442010-08-04 05:59:32 +00004700 // Retrieve the exception object. We may emit multiple blocks but
4701 // nothing can cross this so the value is already in SSA form.
4702 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004703 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004704 ExceptionData.getPointer(), "caught");
John McCall2dd7d442010-08-04 05:59:32 +00004705
John McCallbd309292010-07-06 01:34:17 +00004706 // Push the exception to rethrow onto the EH value stack for the
4707 // benefit of any @throws in the handlers.
4708 CGF.ObjCEHValueStack.push_back(Caught);
4709
Douglas Gregor96c79492010-04-23 22:50:49 +00004710 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004711
Craig Topper8a13c412014-05-21 05:09:00 +00004712 bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr);
John McCallbd309292010-07-06 01:34:17 +00004713
Craig Topper8a13c412014-05-21 05:09:00 +00004714 llvm::BasicBlock *CatchBlock = nullptr;
4715 llvm::BasicBlock *CatchHandler = nullptr;
John McCall2dd7d442010-08-04 05:59:32 +00004716 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00004717 // Save the currently-propagating exception before
4718 // objc_exception_try_enter clears the exception slot.
4719 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
John McCall7f416cc2015-09-08 08:05:57 +00004720 CGF.getPointerAlign(),
John McCall9916e3f2010-10-04 23:42:51 +00004721 "propagating_exception");
4722 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
4723
John McCall2dd7d442010-08-04 05:59:32 +00004724 // Enter a new exception try block (in case a @catch block
4725 // throws an exception).
John McCall882987f2013-02-28 19:01:20 +00004726 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004727 ExceptionData.getPointer());
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004728
John McCall2dd7d442010-08-04 05:59:32 +00004729 llvm::CallInst *SetJmpResult =
John McCall882987f2013-02-28 19:01:20 +00004730 CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(),
4731 SetJmpBuffer, "setjmp.result");
Bill Wendlingbd26cf92011-12-19 23:53:28 +00004732 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004733
John McCall2dd7d442010-08-04 05:59:32 +00004734 llvm::Value *Threw =
4735 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
4736
4737 CatchBlock = CGF.createBasicBlock("catch");
4738 CatchHandler = CGF.createBasicBlock("catch_for_catch");
4739 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4740
4741 CGF.EmitBlock(CatchBlock);
4742 }
4743
4744 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004745
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004746 // Handle catch list. As a special case we check if everything is
4747 // matched and avoid generating code for falling off the end if
4748 // so.
4749 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00004750 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
4751 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004752
Douglas Gregor46a572b2010-04-26 16:46:50 +00004753 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Craig Topper8a13c412014-05-21 05:09:00 +00004754 const ObjCObjectPointerType *OPT = nullptr;
Daniel Dunbar523208f2008-09-27 07:36:24 +00004755
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004756 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004757 if (!CatchParam) {
4758 AllMatched = true;
4759 } else {
John McCall9dd450b2009-09-21 23:43:11 +00004760 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004761
John McCallbd309292010-07-06 01:34:17 +00004762 // catch(id e) always matches under this ABI, since only
4763 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00004764 // FIXME: For the time being we also match id<X>; this should
4765 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00004766 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004767 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004768 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004769
John McCallbd309292010-07-06 01:34:17 +00004770 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004771 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00004772 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4773
Anders Carlsson9396a892008-09-11 09:15:33 +00004774 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00004775 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004776 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00004777
4778 // These types work out because ConvertType(id) == i8*.
John McCall17f02752015-10-30 00:56:02 +00004779 EmitInitOfCatchParam(CGF, Caught, CatchParam);
Anders Carlsson9396a892008-09-11 09:15:33 +00004780 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004781
Anders Carlsson9396a892008-09-11 09:15:33 +00004782 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004783
4784 // The scope of the catch variable ends right here.
4785 CatchVarCleanups.ForceCleanup();
4786
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004787 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004788 break;
4789 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004790
Steve Naroff7cae42b2009-07-10 23:34:53 +00004791 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00004792 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00004793
4794 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00004795 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
4796 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004797
4798 // Check if the @catch block matches the exception object.
John McCall882987f2013-02-28 19:01:20 +00004799 llvm::Value *Class = EmitClassRef(CGF, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004800
John McCall882987f2013-02-28 19:01:20 +00004801 llvm::Value *matchArgs[] = { Class, Caught };
John McCallbd309292010-07-06 01:34:17 +00004802 llvm::CallInst *Match =
John McCall882987f2013-02-28 19:01:20 +00004803 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(),
4804 matchArgs, "match");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004805
John McCallbd309292010-07-06 01:34:17 +00004806 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
4807 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004808
4809 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00004810 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004811
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004812 // Emit the @catch block.
4813 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00004814
4815 // Collect any cleanups for the catch variable. The scope lasts until
4816 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00004817 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00004818
John McCall1c9c3fd2010-10-15 04:57:14 +00004819 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004820 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004821
John McCallbd309292010-07-06 01:34:17 +00004822 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004823 llvm::Value *Tmp =
4824 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004825 CGF.ConvertType(CatchParam->getType()));
John McCall17f02752015-10-30 00:56:02 +00004826 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004827
Anders Carlsson9396a892008-09-11 09:15:33 +00004828 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00004829
4830 // We're done with the catch variable.
4831 CatchVarCleanups.ForceCleanup();
4832
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004833 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004834
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004835 CGF.EmitBlock(NextCatchBlock);
4836 }
4837
John McCallbd309292010-07-06 01:34:17 +00004838 CGF.ObjCEHValueStack.pop_back();
4839
John McCall2dd7d442010-08-04 05:59:32 +00004840 // If nothing wanted anything to do with the caught exception,
4841 // kill the extract call.
4842 if (Caught->use_empty())
4843 Caught->eraseFromParent();
4844
4845 if (!AllMatched)
4846 CGF.EmitBranchThroughCleanup(FinallyRethrow);
4847
4848 if (HasFinally) {
4849 // Emit the exception handler for the @catch blocks.
4850 CGF.EmitBlock(CatchHandler);
4851
4852 // In theory we might now need a write hazard, but actually it's
4853 // unnecessary because there's no local-accessing code between
4854 // the try's write hazard and here.
4855 //Hazards.emitWriteHazard();
4856
John McCall9916e3f2010-10-04 23:42:51 +00004857 // Extract the new exception and save it to the
4858 // propagating-exception slot.
John McCall7f416cc2015-09-08 08:05:57 +00004859 assert(PropagatingExnVar.isValid());
John McCall9916e3f2010-10-04 23:42:51 +00004860 llvm::CallInst *NewCaught =
John McCall882987f2013-02-28 19:01:20 +00004861 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004862 ExceptionData.getPointer(), "caught");
John McCall9916e3f2010-10-04 23:42:51 +00004863 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4864
John McCall2dd7d442010-08-04 05:59:32 +00004865 // Don't pop the catch handler; the throw already did.
4866 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004867 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004868 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004869 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004870
John McCall42227ed2010-07-31 23:20:56 +00004871 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00004872 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004873
John McCallbd309292010-07-06 01:34:17 +00004874 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00004875 CGF.Builder.restoreIP(TryFallthroughIP);
4876 if (CGF.HaveInsertPoint())
4877 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00004878 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00004879 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004880
John McCallbd309292010-07-06 01:34:17 +00004881 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00004882 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00004883 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00004884 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00004885 // If we have a propagating-exception variable, check it.
4886 llvm::Value *PropagatingExn;
John McCall7f416cc2015-09-08 08:05:57 +00004887 if (PropagatingExnVar.isValid()) {
John McCall9916e3f2010-10-04 23:42:51 +00004888 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00004889
John McCall9916e3f2010-10-04 23:42:51 +00004890 // Otherwise, just look in the buffer for the exception to throw.
4891 } else {
4892 llvm::CallInst *Caught =
John McCall882987f2013-02-28 19:01:20 +00004893 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004894 ExceptionData.getPointer());
John McCall9916e3f2010-10-04 23:42:51 +00004895 PropagatingExn = Caught;
4896 }
4897
John McCall882987f2013-02-28 19:01:20 +00004898 CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(),
4899 PropagatingExn);
John McCallbd309292010-07-06 01:34:17 +00004900 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00004901 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004902
John McCall42227ed2010-07-31 23:20:56 +00004903 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004904}
4905
4906void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004907 const ObjCAtThrowStmt &S,
4908 bool ClearInsertionPoint) {
Anders Carlssone005aa12008-09-09 16:16:55 +00004909 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004910
Anders Carlssone005aa12008-09-09 16:16:55 +00004911 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00004912 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004913 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004914 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00004915 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004916 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004917 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00004918 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00004919 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004920
John McCall882987f2013-02-28 19:01:20 +00004921 CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
John McCallbd309292010-07-06 01:34:17 +00004922 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004923 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004924
4925 // Clear the insertion point to indicate we are in unreachable code.
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004926 if (ClearInsertionPoint)
4927 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004928}
4929
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004930/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004931/// object: objc_read_weak (id *src)
4932///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004933llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004934 Address AddrWeakObj) {
4935 llvm::Type* DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004936 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4937 ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00004938 llvm::Value *read_weak =
4939 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00004940 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00004941 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004942 return read_weak;
4943}
4944
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004945/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4946/// objc_assign_weak (id src, id *dst)
4947///
4948void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004949 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004950 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004951 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004952 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004953 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004954 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4955 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004956 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4957 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004958 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4959 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004960 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00004961 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4962 args, "weakassign");
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004963}
4964
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004965/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4966/// objc_assign_global (id src, id *dst)
4967///
4968void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004969 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00004970 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004971 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004972 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004973 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004974 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00004975 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4976 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004977 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4978 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004979 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4980 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00004981 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00004982 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00004983 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4984 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00004985 else
John McCall882987f2013-02-28 19:01:20 +00004986 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4987 args, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004988}
4989
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004990/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004991/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004992///
4993void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00004994 llvm::Value *src, Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004995 llvm::Value *ivarOffset) {
4996 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00004997 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004998 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004999 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005000 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00005001 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
5002 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005003 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5004 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00005005 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5006 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00005007 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00005008 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00005009}
5010
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00005011/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5012/// objc_assign_strongCast (id src, id *dst)
5013///
5014void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00005015 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00005016 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005017 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00005018 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005019 assert(Size <= 8 && "does not support size > 8");
John McCall176f8922016-11-30 02:39:18 +00005020 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
5021 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005022 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5023 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00005024 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5025 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00005026 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00005027 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
John McCall7f416cc2015-09-08 08:05:57 +00005028 args, "strongassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00005029}
5030
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005031void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00005032 Address DestPtr,
5033 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00005034 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005035 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5036 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00005037 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size };
John McCall882987f2013-02-28 19:01:20 +00005038 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005039}
5040
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00005041/// EmitObjCValueForIvar - Code Gen for ivar reference.
5042///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00005043LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
5044 QualType ObjectTy,
5045 llvm::Value *BaseValue,
5046 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00005047 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00005048 const ObjCInterfaceDecl *ID =
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00005049 ObjectTy->castAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00005050 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5051 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00005052}
5053
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005054llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00005055 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005056 const ObjCIvarDecl *Ivar) {
Eli Friedman8cbca202012-11-06 22:15:52 +00005057 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
5058 return llvm::ConstantInt::get(
5059 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
5060 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005061}
5062
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005063/* *** Private Interface *** */
5064
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005065std::string CGObjCCommonMac::GetSectionName(StringRef Section,
5066 StringRef MachOAttributes) {
5067 switch (CGM.getTriple().getObjectFormat()) {
Hubert Tong53a83b72019-07-04 21:40:28 +00005068 case llvm::Triple::UnknownObjectFormat:
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005069 llvm_unreachable("unexpected object file format");
5070 case llvm::Triple::MachO: {
5071 if (MachOAttributes.empty())
5072 return ("__DATA," + Section).str();
5073 return ("__DATA," + Section + "," + MachOAttributes).str();
5074 }
5075 case llvm::Triple::ELF:
5076 assert(Section.substr(0, 2) == "__" &&
5077 "expected the name to begin with __");
5078 return Section.substr(2).str();
5079 case llvm::Triple::COFF:
5080 assert(Section.substr(0, 2) == "__" &&
5081 "expected the name to begin with __");
5082 return ("." + Section.substr(2) + "$B").str();
Hubert Tong53a83b72019-07-04 21:40:28 +00005083 case llvm::Triple::Wasm:
5084 case llvm::Triple::XCOFF:
5085 llvm::report_fatal_error(
5086 "Objective-C support is unimplemented for object file format.");
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005087 }
Mikael Holmenc72cb1f2019-07-05 06:12:24 +00005088
5089 llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType enum");
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005090}
5091
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005092/// EmitImageInfo - Emit the image info marker used to encode some module
5093/// level information.
5094///
5095/// See: <rdr://4810609&4810587&4810587>
5096/// struct IMAGE_INFO {
5097/// unsigned version;
5098/// unsigned flags;
5099/// };
5100enum ImageInfoFlags {
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00005101 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005102 eImageInfo_GarbageCollected = (1 << 1),
5103 eImageInfo_GCOnly = (1 << 2),
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00005104 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
Daniel Dunbar75e909f2009-04-20 07:11:47 +00005105
Daniel Dunbar5e639272010-04-25 20:39:01 +00005106 // A flag indicating that the module has no instances of a @synthesize of a
5107 // superclass variable. <rdar://problem/6803242>
Fariborz Jahanian39c17a82014-01-14 22:01:08 +00005108 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
Manman Ren96df0b32016-01-29 23:45:01 +00005109 eImageInfo_ImageIsSimulated = (1 << 5),
5110 eImageInfo_ClassProperties = (1 << 6)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005111};
5112
Daniel Dunbar5e639272010-04-25 20:39:01 +00005113void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005114 unsigned version = 0; // Version is unused?
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005115 std::string Section =
5116 (ObjCABI == 1)
5117 ? "__OBJC,__image_info,regular"
5118 : GetSectionName("__objc_imageinfo", "regular,no_dead_strip");
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005119
Bill Wendlingb6f795e2012-02-16 01:13:30 +00005120 // Generate module-level named metadata to convey this information to the
5121 // linker and code-gen.
5122 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005123
Bill Wendlingb6f795e2012-02-16 01:13:30 +00005124 // Add the ObjC ABI version to the module flags.
5125 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
5126 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
5127 version);
5128 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00005129 llvm::MDString::get(VMContext, Section));
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005130
David Blaikiebbafb8a2012-03-11 07:00:24 +00005131 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00005132 // Non-GC overrides those files which specify GC.
5133 Mod.addModuleFlag(llvm::Module::Override,
5134 "Objective-C Garbage Collection", (uint32_t)0);
5135 } else {
5136 // Add the ObjC garbage collection value.
5137 Mod.addModuleFlag(llvm::Module::Error,
5138 "Objective-C Garbage Collection",
5139 eImageInfo_GarbageCollected);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005140
David Blaikiebbafb8a2012-03-11 07:00:24 +00005141 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00005142 // Add the ObjC GC Only value.
5143 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
5144 eImageInfo_GCOnly);
5145
5146 // Require that GC be specified and set to eImageInfo_GarbageCollected.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +00005147 llvm::Metadata *Ops[2] = {
5148 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
5149 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
5150 llvm::Type::getInt32Ty(VMContext), eImageInfo_GarbageCollected))};
Bill Wendlingb6f795e2012-02-16 01:13:30 +00005151 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
5152 llvm::MDNode::get(VMContext, Ops));
5153 }
5154 }
Bill Wendling1e60a2c2012-04-24 11:04:57 +00005155
5156 // Indicate whether we're compiling this to run on a simulator.
Alex Lorenz6cdef0e2017-12-07 19:04:10 +00005157 if (CGM.getTarget().getTriple().isSimulatorEnvironment())
Bill Wendling1e60a2c2012-04-24 11:04:57 +00005158 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
5159 eImageInfo_ImageIsSimulated);
Manman Ren96df0b32016-01-29 23:45:01 +00005160
5161 // Indicate whether we are generating class properties.
5162 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Class Properties",
5163 eImageInfo_ClassProperties);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005164}
5165
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005166// struct objc_module {
5167// unsigned long version;
5168// unsigned long size;
5169// const char *name;
5170// Symtab symtab;
5171// };
5172
5173// FIXME: Get from somewhere
5174static const int ModuleVersion = 7;
5175
5176void CGObjCMac::EmitModuleInfo() {
Micah Villmowdd31ca12012-10-08 16:25:52 +00005177 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005178
John McCall176f8922016-11-30 02:39:18 +00005179 ConstantInitBuilder builder(CGM);
5180 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
5181 values.addInt(ObjCTypes.LongTy, ModuleVersion);
5182 values.addInt(ObjCTypes.LongTy, Size);
5183 // This used to be the filename, now it is unused. <rdr://4327263>
5184 values.add(GetClassName(StringRef("")));
5185 values.add(EmitModuleSymbols());
5186 CreateMetadataVar("OBJC_MODULES", values,
John McCall7f416cc2015-09-08 08:05:57 +00005187 "__OBJC,__module_info,regular,no_dead_strip",
5188 CGM.getPointerAlign(), true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005189}
5190
5191llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005192 unsigned NumClasses = DefinedClasses.size();
5193 unsigned NumCategories = DefinedCategories.size();
5194
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005195 // Return null if no symbols were defined.
5196 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00005197 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005198
John McCall176f8922016-11-30 02:39:18 +00005199 ConstantInitBuilder builder(CGM);
5200 auto values = builder.beginStruct();
5201 values.addInt(ObjCTypes.LongTy, 0);
5202 values.addNullPointer(ObjCTypes.SelectorPtrTy);
5203 values.addInt(ObjCTypes.ShortTy, NumClasses);
5204 values.addInt(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005205
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005206 // The runtime expects exactly the list of defined classes followed
5207 // by the list of defined categories, in a single array.
John McCall176f8922016-11-30 02:39:18 +00005208 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005209 for (unsigned i=0; i<NumClasses; i++) {
5210 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5211 assert(ID);
5212 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5213 // We are implementing a weak imported interface. Give it external linkage
5214 if (ID->isWeakImported() && !IMP->isWeakImported())
5215 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
John McCall176f8922016-11-30 02:39:18 +00005216
5217 array.addBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy);
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00005218 }
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005219 for (unsigned i=0; i<NumCategories; i++)
John McCall176f8922016-11-30 02:39:18 +00005220 array.addBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005221
John McCall176f8922016-11-30 02:39:18 +00005222 array.finishAndAddTo(values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005223
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005224 llvm::GlobalVariable *GV = CreateMetadataVar(
John McCall176f8922016-11-30 02:39:18 +00005225 "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip",
John McCall7f416cc2015-09-08 08:05:57 +00005226 CGM.getPointerAlign(), true);
Owen Andersonade90fd2009-07-29 18:54:39 +00005227 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005228}
5229
John McCall882987f2013-02-28 19:01:20 +00005230llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
5231 IdentifierInfo *II) {
John McCall31168b02011-06-15 23:02:42 +00005232 LazySymbols.insert(II);
Fangrui Song6907ce22018-07-30 19:24:48 +00005233
John McCall31168b02011-06-15 23:02:42 +00005234 llvm::GlobalVariable *&Entry = ClassReferences[II];
Fangrui Song6907ce22018-07-30 19:24:48 +00005235
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005236 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005237 llvm::Constant *Casted =
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00005238 llvm::ConstantExpr::getBitCast(GetClassName(II->getName()),
John McCall31168b02011-06-15 23:02:42 +00005239 ObjCTypes.ClassPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005240 Entry = CreateMetadataVar(
5241 "OBJC_CLASS_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00005242 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
5243 CGM.getPointerAlign(), true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005244 }
Fangrui Song6907ce22018-07-30 19:24:48 +00005245
John McCall7f416cc2015-09-08 08:05:57 +00005246 return CGF.Builder.CreateAlignedLoad(Entry, CGF.getPointerAlign());
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005247}
5248
John McCall882987f2013-02-28 19:01:20 +00005249llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00005250 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00005251 // If the class has the objc_runtime_visible attribute, we need to
5252 // use the Objective-C runtime to get the class.
5253 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
5254 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
5255
Akira Hatanaka0c194462018-04-03 22:50:16 +00005256 IdentifierInfo *RuntimeName =
5257 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
5258 return EmitClassRefFromId(CGF, RuntimeName);
John McCall31168b02011-06-15 23:02:42 +00005259}
5260
John McCall882987f2013-02-28 19:01:20 +00005261llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00005262 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
John McCall882987f2013-02-28 19:01:20 +00005263 return EmitClassRefFromId(CGF, II);
John McCall31168b02011-06-15 23:02:42 +00005264}
5265
John McCall7f416cc2015-09-08 08:05:57 +00005266llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
Erik Pilkingtond5e66f0e2019-12-10 16:43:39 -08005267 return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
John McCall7f416cc2015-09-08 08:05:57 +00005268}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005269
Erik Pilkingtond5e66f0e2019-12-10 16:43:39 -08005270Address CGObjCMac::EmitSelectorAddr(Selector Sel) {
5271 CharUnits Align = CGM.getPointerAlign();
John McCall7f416cc2015-09-08 08:05:57 +00005272
5273 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005274 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005275 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00005276 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005277 ObjCTypes.SelectorPtrTy);
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005278 Entry = CreateMetadataVar(
5279 "OBJC_SELECTOR_REFERENCES_", Casted,
John McCall7f416cc2015-09-08 08:05:57 +00005280 "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true);
Michael Gottesman5c205962013-02-05 23:08:45 +00005281 Entry->setExternallyInitialized(true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005282 }
5283
John McCall7f416cc2015-09-08 08:05:57 +00005284 return Address(Entry, Align);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005285}
5286
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00005287llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
5288 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
5289 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005290 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00005291 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005292}
5293
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005294llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
5295 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
5296 I = MethodDefinitions.find(MD);
5297 if (I != MethodDefinitions.end())
5298 return I->second;
5299
Craig Topper8a13c412014-05-21 05:09:00 +00005300 return nullptr;
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005301}
5302
Fariborz Jahanian01dff422009-03-05 19:17:31 +00005303/// GetIvarLayoutName - Returns a unique constant for the given
5304/// ivar layout bitmap.
5305llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005306 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00005307 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00005308}
5309
John McCall3fd13f062015-10-21 18:06:47 +00005310void IvarLayoutBuilder::visitRecord(const RecordType *RT,
5311 CharUnits offset) {
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005312 const RecordDecl *RD = RT->getDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005313
John McCall3fd13f062015-10-21 18:06:47 +00005314 // If this is a union, remember that we had one, because it might mess
5315 // up the ordering of layout entries.
5316 if (RD->isUnion())
5317 IsDisordered = true;
5318
5319 const ASTRecordLayout *recLayout = nullptr;
5320 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5321 [&](const FieldDecl *field) -> CharUnits {
5322 if (!recLayout)
5323 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5324 auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
5325 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5326 });
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005327}
5328
John McCall3fd13f062015-10-21 18:06:47 +00005329template <class Iterator, class GetOffsetFn>
Fangrui Song6907ce22018-07-30 19:24:48 +00005330void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
John McCall3fd13f062015-10-21 18:06:47 +00005331 CharUnits aggregateOffset,
5332 const GetOffsetFn &getOffset) {
5333 for (; begin != end; ++begin) {
5334 auto field = *begin;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005335
John McCall3fd13f062015-10-21 18:06:47 +00005336 // Skip over bitfields.
5337 if (field->isBitField()) {
5338 continue;
5339 }
5340
5341 // Compute the offset of the field within the aggregate.
5342 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5343
5344 visitField(field, fieldOffset);
5345 }
5346}
5347
5348/// Collect layout information for the given fields into IvarsInfo.
5349void IvarLayoutBuilder::visitField(const FieldDecl *field,
5350 CharUnits fieldOffset) {
5351 QualType fieldType = field->getType();
5352
5353 // Drill down into arrays.
5354 uint64_t numElts = 1;
Volodymyr Sapsai636ed472017-10-27 00:56:23 +00005355 if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
5356 numElts = 0;
5357 fieldType = arrayType->getElementType();
5358 }
5359 // Unlike incomplete arrays, constant arrays can be nested.
John McCall3fd13f062015-10-21 18:06:47 +00005360 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5361 numElts *= arrayType->getSize().getZExtValue();
5362 fieldType = arrayType->getElementType();
5363 }
5364
5365 assert(!fieldType->isArrayType() && "ivar of non-constant array type?");
5366
5367 // If we ended up with a zero-sized array, we've done what we can do within
5368 // the limits of this layout encoding.
5369 if (numElts == 0) return;
5370
5371 // Recurse if the base element type is a record type.
5372 if (auto recType = fieldType->getAs<RecordType>()) {
5373 size_t oldEnd = IvarsInfo.size();
5374
5375 visitRecord(recType, fieldOffset);
5376
5377 // If we have an array, replicate the first entry's layout information.
5378 auto numEltEntries = IvarsInfo.size() - oldEnd;
5379 if (numElts != 1 && numEltEntries != 0) {
5380 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5381 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5382 // Copy the last numEltEntries onto the end of the array, adjusting
5383 // each for the element size.
5384 for (size_t i = 0; i != numEltEntries; ++i) {
5385 auto firstEntry = IvarsInfo[oldEnd + i];
5386 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5387 firstEntry.SizeInWords));
5388 }
5389 }
5390 }
5391
Fariborz Jahanian524bb202009-03-10 16:22:08 +00005392 return;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00005393 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00005394
John McCall3fd13f062015-10-21 18:06:47 +00005395 // Classify the element type.
5396 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005397
John McCall3fd13f062015-10-21 18:06:47 +00005398 // If it matches what we're looking for, add an entry.
5399 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
5400 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5401 assert(CGM.getContext().getTypeSizeInChars(fieldType)
5402 == CGM.getPointerSize());
5403 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5404 }
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00005405}
5406
John McCall3fd13f062015-10-21 18:06:47 +00005407/// buildBitmap - This routine does the horsework of taking the offsets of
5408/// strong/weak references and creating a bitmap. The bitmap is also
5409/// returned in the given buffer, suitable for being passed to \c dump().
5410llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5411 llvm::SmallVectorImpl<unsigned char> &buffer) {
5412 // The bitmap is a series of skip/scan instructions, aligned to word
5413 // boundaries. The skip is performed first.
5414 const unsigned char MaxNibble = 0xF;
5415 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5416 const unsigned char ScanMask = 0x0F, ScanShift = 0;
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00005417
John McCall3fd13f062015-10-21 18:06:47 +00005418 assert(!IvarsInfo.empty() && "generating bitmap for no data");
5419
5420 // Sort the ivar info on byte position in case we encounterred a
5421 // union nested in the ivar list.
5422 if (IsDisordered) {
5423 // This isn't a stable sort, but our algorithm should handle it fine.
5424 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5425 } else {
Craig Toppera3467052016-01-03 19:43:20 +00005426 assert(std::is_sorted(IvarsInfo.begin(), IvarsInfo.end()));
John McCall3fd13f062015-10-21 18:06:47 +00005427 }
5428 assert(IvarsInfo.back().Offset < InstanceEnd);
5429
5430 assert(buffer.empty());
5431
5432 // Skip the next N words.
5433 auto skip = [&](unsigned numWords) {
5434 assert(numWords > 0);
5435
5436 // Try to merge into the previous byte. Since scans happen second, we
5437 // can't do this if it includes a scan.
5438 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5439 unsigned lastSkip = buffer.back() >> SkipShift;
5440 if (lastSkip < MaxNibble) {
5441 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5442 numWords -= claimed;
5443 lastSkip += claimed;
5444 buffer.back() = (lastSkip << SkipShift);
5445 }
5446 }
5447
5448 while (numWords >= MaxNibble) {
5449 buffer.push_back(MaxNibble << SkipShift);
5450 numWords -= MaxNibble;
5451 }
5452 if (numWords) {
5453 buffer.push_back(numWords << SkipShift);
5454 }
5455 };
5456
5457 // Scan the next N words.
5458 auto scan = [&](unsigned numWords) {
5459 assert(numWords > 0);
5460
5461 // Try to merge into the previous byte. Since scans happen second, we can
5462 // do this even if it includes a skip.
5463 if (!buffer.empty()) {
5464 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5465 if (lastScan < MaxNibble) {
5466 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5467 numWords -= claimed;
5468 lastScan += claimed;
5469 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5470 }
5471 }
5472
5473 while (numWords >= MaxNibble) {
5474 buffer.push_back(MaxNibble << ScanShift);
5475 numWords -= MaxNibble;
5476 }
5477 if (numWords) {
5478 buffer.push_back(numWords << ScanShift);
5479 }
5480 };
5481
5482 // One past the end of the last scan.
5483 unsigned endOfLastScanInWords = 0;
5484 const CharUnits WordSize = CGM.getPointerSize();
5485
5486 // Consider all the scan requests.
5487 for (auto &request : IvarsInfo) {
5488 CharUnits beginOfScan = request.Offset - InstanceBegin;
5489
5490 // Ignore scan requests that don't start at an even multiple of the
5491 // word size. We can't encode them.
5492 if ((beginOfScan % WordSize) != 0) continue;
5493
5494 // Ignore scan requests that start before the instance start.
5495 // This assumes that scans never span that boundary. The boundary
5496 // isn't the true start of the ivars, because in the fragile-ARC case
5497 // it's rounded up to word alignment, but the test above should leave
5498 // us ignoring that possibility.
5499 if (beginOfScan.isNegative()) {
5500 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5501 continue;
5502 }
5503
5504 unsigned beginOfScanInWords = beginOfScan / WordSize;
5505 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5506
5507 // If the scan starts some number of words after the last one ended,
5508 // skip forward.
5509 if (beginOfScanInWords > endOfLastScanInWords) {
5510 skip(beginOfScanInWords - endOfLastScanInWords);
5511
5512 // Otherwise, start scanning where the last left off.
5513 } else {
5514 beginOfScanInWords = endOfLastScanInWords;
5515
5516 // If that leaves us with nothing to scan, ignore this request.
5517 if (beginOfScanInWords >= endOfScanInWords) continue;
5518 }
5519
5520 // Scan to the end of the request.
5521 assert(beginOfScanInWords < endOfScanInWords);
5522 scan(endOfScanInWords - beginOfScanInWords);
5523 endOfLastScanInWords = endOfScanInWords;
5524 }
5525
John McCallf5ea0722015-10-29 23:36:14 +00005526 if (buffer.empty())
5527 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5528
John McCall3fd13f062015-10-21 18:06:47 +00005529 // For GC layouts, emit a skip to the end of the allocation so that we
5530 // have precise information about the entire thing. This isn't useful
5531 // or necessary for the ARC-style layout strings.
5532 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5533 unsigned lastOffsetInWords =
5534 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5535 if (lastOffsetInWords > endOfLastScanInWords) {
5536 skip(lastOffsetInWords - endOfLastScanInWords);
5537 }
5538 }
5539
5540 // Null terminate the string.
5541 buffer.push_back(0);
5542
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005543 auto *Entry = CGObjC.CreateCStringLiteral(
5544 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
John McCall3fd13f062015-10-21 18:06:47 +00005545 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005546}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005547
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005548/// BuildIvarLayout - Builds ivar layout bitmap for the class
5549/// implementation for the __strong or __weak case.
5550/// The layout map displays which words in ivar list must be skipped
5551/// and which must be scanned by GC (see below). String is built of bytes.
5552/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
5553/// of words to skip and right nibble is count of words to scan. So, each
5554/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
5555/// represented by a 0x00 byte which also ends the string.
5556/// 1. when ForStrongLayout is true, following ivars are scanned:
5557/// - id, Class
5558/// - object *
5559/// - __strong anything
5560///
5561/// 2. When ForStrongLayout is false, following ivars are scanned:
5562/// - __weak anything
5563///
John McCall3fd13f062015-10-21 18:06:47 +00005564llvm::Constant *
5565CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5566 CharUnits beginOffset, CharUnits endOffset,
John McCall460ce582015-10-22 18:38:17 +00005567 bool ForStrongLayout, bool HasMRCWeakIvars) {
5568 // If this is MRC, and we're either building a strong layout or there
5569 // are no weak ivars, bail out early.
Chris Lattnerece04092012-02-07 00:39:47 +00005570 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikiebbafb8a2012-03-11 07:00:24 +00005571 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
John McCall460ce582015-10-22 18:38:17 +00005572 !CGM.getLangOpts().ObjCAutoRefCount &&
5573 (ForStrongLayout || !HasMRCWeakIvars))
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005574 return llvm::Constant::getNullValue(PtrTy);
5575
Jordy Rosea91768e2011-07-22 02:08:32 +00005576 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
John McCall3fd13f062015-10-21 18:06:47 +00005577 SmallVector<const ObjCIvarDecl*, 32> ivars;
5578
5579 // GC layout strings include the complete object layout, possibly
5580 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5581 // up.
5582 //
5583 // ARC layout strings only include the class's ivars. In non-fragile
John McCallf5ea0722015-10-29 23:36:14 +00005584 // runtimes, that means starting at InstanceStart, rounded up to word
5585 // alignment. In fragile runtimes, there's no InstanceStart, so it means
John McCalld80218f2015-11-19 02:27:55 +00005586 // starting at the offset of the first ivar, rounded up to word alignment.
John McCall460ce582015-10-22 18:38:17 +00005587 //
5588 // MRC weak layout strings follow the ARC style.
John McCall3fd13f062015-10-21 18:06:47 +00005589 CharUnits baseOffset;
John McCall460ce582015-10-22 18:38:17 +00005590 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Fangrui Song6907ce22018-07-30 19:24:48 +00005591 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005592 IVD; IVD = IVD->getNextIvar())
John McCall3fd13f062015-10-21 18:06:47 +00005593 ivars.push_back(IVD);
5594
5595 if (isNonFragileABI()) {
5596 baseOffset = beginOffset; // InstanceStart
John McCalld80218f2015-11-19 02:27:55 +00005597 } else if (!ivars.empty()) {
5598 baseOffset =
5599 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
John McCall3fd13f062015-10-21 18:06:47 +00005600 } else {
5601 baseOffset = CharUnits::Zero();
5602 }
John McCallf5ea0722015-10-29 23:36:14 +00005603
Rui Ueyama83aa9792016-01-14 21:00:27 +00005604 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005605 }
5606 else {
John McCall3fd13f062015-10-21 18:06:47 +00005607 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005608
John McCall3fd13f062015-10-21 18:06:47 +00005609 baseOffset = CharUnits::Zero();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005610 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005611
John McCall3fd13f062015-10-21 18:06:47 +00005612 if (ivars.empty())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005613 return llvm::Constant::getNullValue(PtrTy);
5614
John McCall3fd13f062015-10-21 18:06:47 +00005615 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005616
John McCall3fd13f062015-10-21 18:06:47 +00005617 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5618 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5619 return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
5620 });
5621
5622 if (!builder.hasBitmapData())
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005623 return llvm::Constant::getNullValue(PtrTy);
John McCall3fd13f062015-10-21 18:06:47 +00005624
5625 llvm::SmallVector<unsigned char, 4> buffer;
5626 llvm::Constant *C = builder.buildBitmap(*this, buffer);
Fangrui Song6907ce22018-07-30 19:24:48 +00005627
John McCallf5ea0722015-10-29 23:36:14 +00005628 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005629 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005630 ForStrongLayout ? "strong" : "weak",
Ben Langmuire013bdc2014-07-11 00:43:47 +00005631 OMD->getClassInterface()->getName().str().c_str());
John McCall3fd13f062015-10-21 18:06:47 +00005632 builder.dump(buffer);
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00005633 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00005634 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00005635}
5636
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005637llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005638 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
Chris Lattner3def9ae2012-02-06 22:16:34 +00005639 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005640 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005641 Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
Owen Anderson170229f2009-07-14 23:10:40 +00005642 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005643}
5644
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005645// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005646llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005647 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5648}
5649
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005650llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005651 std::string TypeStr;
5652 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5653
5654 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005655 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005656 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005657 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00005658}
5659
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005660llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5661 bool Extended) {
John McCall843dfcc2016-11-29 21:57:00 +00005662 std::string TypeStr =
5663 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00005664
5665 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbar3241fae2009-04-14 23:14:47 +00005666 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005667 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
Owen Anderson170229f2009-07-14 23:10:40 +00005668 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005669}
5670
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005671// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005672llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005673 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005674 if (!Entry)
Saleem Abdulrasool271106c2016-09-16 23:41:13 +00005675 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
Owen Anderson170229f2009-07-14 23:10:40 +00005676 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005677}
5678
5679// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00005680// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00005681llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005682CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5683 const Decl *Container) {
John McCall843dfcc2016-11-29 21:57:00 +00005684 std::string TypeStr =
5685 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00005686 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5687}
5688
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005689void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00005690 const ObjCContainerDecl *CD,
Pierre Habouzit42f9d0c2019-12-19 01:25:03 -08005691 SmallVectorImpl<char> &Name,
5692 bool ignoreCategoryNamespace) {
Daniel Dunbard2386812009-10-19 01:21:19 +00005693 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00005694 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00005695 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
5696 << '[' << CD->getName();
Pierre Habouzit42f9d0c2019-12-19 01:25:03 -08005697 if (!ignoreCategoryNamespace)
5698 if (const ObjCCategoryImplDecl *CID =
5699 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
5700 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00005701 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00005702}
5703
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005704void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005705 EmitModuleInfo();
5706
Daniel Dunbarc475d422008-10-29 22:36:39 +00005707 // Emit the dummy bodies for any protocols which were referenced but
5708 // never defined.
John McCall176f8922016-11-30 02:39:18 +00005709 for (auto &entry : Protocols) {
5710 llvm::GlobalVariable *global = entry.second;
5711 if (global->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00005712 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005713
John McCall176f8922016-11-30 02:39:18 +00005714 ConstantInitBuilder builder(CGM);
5715 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5716 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5717 values.add(GetClassName(entry.first->getName()));
5718 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5719 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5720 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5721 values.finishAndSetAsInitializer(global);
5722 CGM.addCompilerUsedGlobal(global);
Daniel Dunbarc475d422008-10-29 22:36:39 +00005723 }
5724
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005725 // Add assembler directives to add lazy undefined symbol references
5726 // for classes which are referenced but not defined. This is
5727 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00005728 //
5729 // FIXME: It would be nice if we had an LLVM construct for this.
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005730 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5731 CGM.getTriple().isOSBinFormatMachO()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005732 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00005733 Asm += CGM.getModule().getModuleInlineAsm();
5734 if (!Asm.empty() && Asm.back() != '\n')
5735 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005736
Daniel Dunbard027a922009-09-07 00:20:42 +00005737 llvm::raw_svector_ostream OS(Asm);
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005738 for (const auto *Sym : DefinedSymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005739 OS << "\t.objc_class_name_" << Sym->getName() << "=0\n"
5740 << "\t.globl .objc_class_name_" << Sym->getName() << "\n";
Saleem Abdulrasool39217d42016-09-16 14:24:26 +00005741 for (const auto *Sym : LazySymbols)
Saleem Abdulrasool62c07eb2016-09-12 21:15:23 +00005742 OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n";
5743 for (const auto &Category : DefinedCategoryNames)
5744 OS << "\t.objc_category_name_" << Category << "=0\n"
5745 << "\t.globl .objc_category_name_" << Category << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00005746
Daniel Dunbard027a922009-09-07 00:20:42 +00005747 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00005748 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005749}
5750
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005751CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00005752 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5753 ObjCEmptyVtableVar(nullptr) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005754 ObjCABI = 2;
5755}
5756
Daniel Dunbar3ad53482008-08-11 21:35:06 +00005757/* *** */
5758
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005759ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Craig Topper8a13c412014-05-21 05:09:00 +00005760 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00005761{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005762 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5763 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005764
John McCall176f8922016-11-30 02:39:18 +00005765 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5766 IntTy = CGM.IntTy;
5767 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
Chris Lattnerece04092012-02-07 00:39:47 +00005768 Int8PtrTy = CGM.Int8PtrTy;
5769 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005770
Tim Northover238b5082014-03-29 13:42:40 +00005771 // arm64 targets use "int" ivar offset variables. All others,
5772 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
Tim Northover40956e62014-07-23 12:32:58 +00005773 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
Tim Northover238b5082014-03-29 13:42:40 +00005774 IvarOffsetVarTy = IntTy;
5775 else
5776 IvarOffsetVarTy = LongTy;
5777
John McCall176f8922016-11-30 02:39:18 +00005778 ObjectPtrTy =
5779 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5780 PtrObjectPtrTy =
5781 llvm::PointerType::getUnqual(ObjectPtrTy);
5782 SelectorPtrTy =
5783 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005784
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005785 // I'm not sure I like this. The implicit coordination is a bit
5786 // gross. We should solve this in a reasonable fashion because this
5787 // is a pretty common task (match some runtime data structure with
5788 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005789
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005790 // FIXME: This is leaked.
5791 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005792
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005793 // struct _objc_super {
5794 // id self;
5795 // Class cls;
5796 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00005797 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005798 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005799 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005800 &Ctx.Idents.get("_objc_super"));
Craig Topper8a13c412014-05-21 05:09:00 +00005801 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5802 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5803 false, ICIS_NoInit));
5804 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5805 nullptr, Ctx.getObjCClassType(), nullptr,
5806 nullptr, false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005807 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005808
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005809 SuperCTy = Ctx.getTagDeclType(RD);
5810 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005811
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005812 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005813 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5814
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005815 // struct _prop_t {
5816 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005817 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005818 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005819 PropertyTy = llvm::StructType::create("struct._prop_t", Int8PtrTy, Int8PtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005820
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005821 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005822 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005823 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005824 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005825 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005826 PropertyListTy = llvm::StructType::create(
5827 "struct._prop_list_t", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0));
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005828 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005829 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005830
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005831 // struct _objc_method {
5832 // SEL _cmd;
5833 // char *method_type;
5834 // char *_imp;
5835 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005836 MethodTy = llvm::StructType::create("struct._objc_method", SelectorPtrTy,
5837 Int8PtrTy, Int8PtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005838
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005839 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00005840 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005841 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005842}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005843
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005844ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005845 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005846 // struct _objc_method_description {
5847 // SEL name;
5848 // char *types;
5849 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005850 MethodDescriptionTy = llvm::StructType::create(
5851 "struct._objc_method_description", SelectorPtrTy, Int8PtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005852
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005853 // struct _objc_method_description_list {
5854 // int count;
5855 // struct _objc_method_description[1];
5856 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005857 MethodDescriptionListTy =
5858 llvm::StructType::create("struct._objc_method_description_list", IntTy,
5859 llvm::ArrayType::get(MethodDescriptionTy, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005860
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005861 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005862 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005863 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005864
Daniel Dunbarb036db82008-08-13 03:21:16 +00005865 // Protocol description structures
5866
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005867 // struct _objc_protocol_extension {
5868 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5869 // struct _objc_method_description_list *optional_instance_methods;
5870 // struct _objc_method_description_list *optional_class_methods;
5871 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005872 // const char ** extendedMethodTypes;
Manman Rence7bff52016-01-29 23:46:55 +00005873 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005874 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005875 ProtocolExtensionTy = llvm::StructType::create(
5876 "struct._objc_protocol_extension", IntTy, MethodDescriptionListPtrTy,
5877 MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy,
5878 PropertyListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005879
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005880 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005881 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005882
Daniel Dunbarc475d422008-10-29 22:36:39 +00005883 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00005884
Chris Lattnera5f58b02011-07-09 17:41:47 +00005885 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005886 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00005887
Chris Lattnera5f58b02011-07-09 17:41:47 +00005888 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005889 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Serge Guelton1d993272017-05-09 19:31:30 +00005890 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), LongTy,
5891 llvm::ArrayType::get(ProtocolTy, 0));
Daniel Dunbarb036db82008-08-13 03:21:16 +00005892
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005893 // struct _objc_protocol {
5894 // struct _objc_protocol_extension *isa;
5895 // char *protocol_name;
5896 // struct _objc_protocol **_objc_protocol_list;
5897 // struct _objc_method_description_list *instance_methods;
5898 // struct _objc_method_description_list *class_methods;
5899 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005900 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5901 llvm::PointerType::getUnqual(ProtocolListTy),
Serge Guelton1d993272017-05-09 19:31:30 +00005902 MethodDescriptionListPtrTy, MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005903
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005904 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005905 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005906
Owen Anderson9793f0e2009-07-29 22:16:19 +00005907 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005908
5909 // Class description structures
5910
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005911 // struct _objc_ivar {
5912 // char *ivar_name;
5913 // char *ivar_type;
5914 // int ivar_offset;
5915 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005916 IvarTy = llvm::StructType::create("struct._objc_ivar", Int8PtrTy, Int8PtrTy,
5917 IntTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005918
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005919 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005920 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005921 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005922 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005923
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005924 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005925 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005926 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005927 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005928
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005929 // struct _objc_class_extension *
Serge Guelton1d993272017-05-09 19:31:30 +00005930 ClassExtensionTy = llvm::StructType::create(
5931 "struct._objc_class_extension", IntTy, Int8PtrTy, PropertyListPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005932 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005933
Chris Lattner5ec04a52011-08-12 17:43:31 +00005934 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005935
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005936 // struct _objc_class {
5937 // Class isa;
5938 // Class super_class;
5939 // char *name;
5940 // long version;
5941 // long info;
5942 // long instance_size;
5943 // struct _objc_ivar_list *ivars;
5944 // struct _objc_method_list *methods;
5945 // struct _objc_cache *cache;
5946 // struct _objc_protocol_list *protocols;
5947 // char *ivar_layout;
5948 // struct _objc_class_ext *ext;
5949 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005950 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
Serge Guelton1d993272017-05-09 19:31:30 +00005951 llvm::PointerType::getUnqual(ClassTy), Int8PtrTy, LongTy,
5952 LongTy, LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy,
5953 ProtocolListPtrTy, Int8PtrTy, ClassExtensionPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005954
Owen Anderson9793f0e2009-07-29 22:16:19 +00005955 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005956
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005957 // struct _objc_category {
5958 // char *category_name;
5959 // char *class_name;
5960 // struct _objc_method_list *instance_method;
5961 // struct _objc_method_list *class_method;
Manman Renb3736772016-01-25 22:37:47 +00005962 // struct _objc_protocol_list *protocols;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005963 // uint32_t size; // sizeof(struct _objc_category)
5964 // struct _objc_property_list *instance_properties;// category's @property
Manman Ren96df0b32016-01-29 23:45:01 +00005965 // struct _objc_property_list *class_properties;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005966 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005967 CategoryTy = llvm::StructType::create(
5968 "struct._objc_category", Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5969 MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy,
5970 PropertyListPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005971
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005972 // Global metadata structures
5973
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005974 // struct _objc_symtab {
5975 // long sel_ref_cnt;
5976 // SEL *refs;
5977 // short cls_def_cnt;
5978 // short cat_def_cnt;
5979 // char *defs[cls_def_cnt + cat_def_cnt];
5980 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005981 SymtabTy = llvm::StructType::create("struct._objc_symtab", LongTy,
5982 SelectorPtrTy, ShortTy, ShortTy,
5983 llvm::ArrayType::get(Int8PtrTy, 0));
Owen Anderson9793f0e2009-07-29 22:16:19 +00005984 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005985
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00005986 // struct _objc_module {
5987 // long version;
5988 // long size; // sizeof(struct _objc_module)
5989 // char *name;
5990 // struct _objc_symtab* symtab;
5991 // }
Serge Guelton1d993272017-05-09 19:31:30 +00005992 ModuleTy = llvm::StructType::create("struct._objc_module", LongTy, LongTy,
5993 Int8PtrTy, SymtabPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005994
Mike Stump18bb9282009-05-16 07:57:57 +00005995 // FIXME: This is the size of the setjmp buffer and should be target
5996 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00005997 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005998
Anders Carlsson9ff22482008-09-09 10:10:21 +00005999 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00006000 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006001
Serge Guelton1d993272017-05-09 19:31:30 +00006002 ExceptionDataTy = llvm::StructType::create(
6003 "struct._objc_exception_data",
6004 llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00006005}
6006
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006007ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00006008 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006009 // struct _method_list_t {
6010 // uint32_t entsize; // sizeof(struct _objc_method)
6011 // uint32_t method_count;
6012 // struct _objc_method method_list[method_count];
6013 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00006014 MethodListnfABITy =
Serge Guelton1d993272017-05-09 19:31:30 +00006015 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
6016 llvm::ArrayType::get(MethodTy, 0));
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006017 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00006018 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006019
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006020 // struct _protocol_t {
6021 // id isa; // NULL
6022 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006023 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006024 // const struct method_list_t * const instance_methods;
6025 // const struct method_list_t * const class_methods;
6026 // const struct method_list_t *optionalInstanceMethods;
6027 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006028 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006029 // const uint32_t size; // sizeof(struct _protocol_t)
6030 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006031 // const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00006032 // const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00006033 // const struct _prop_list_t * class_properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006034 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006035
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006036 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00006037 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00006038 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006039
Serge Guelton1d993272017-05-09 19:31:30 +00006040 ProtocolnfABITy = llvm::StructType::create(
6041 "struct._protocol_t", ObjectPtrTy, Int8PtrTy,
6042 llvm::PointerType::getUnqual(ProtocolListnfABITy), MethodListnfABIPtrTy,
6043 MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy,
6044 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy,
6045 PropertyListPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006046
6047 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00006048 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006049
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006050 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006051 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006052 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006053 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00006054 ProtocolListnfABITy->setBody(LongTy,
Serge Guelton1d993272017-05-09 19:31:30 +00006055 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006056
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006057 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00006058 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006059
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006060 // struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00006061 // unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006062 // char *name;
6063 // char *type;
6064 // uint32_t alignment;
6065 // uint32_t size;
6066 // }
Tim Northover238b5082014-03-29 13:42:40 +00006067 IvarnfABITy = llvm::StructType::create(
6068 "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy),
Serge Guelton1d993272017-05-09 19:31:30 +00006069 Int8PtrTy, Int8PtrTy, IntTy, IntTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006070
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006071 // struct _ivar_list_t {
6072 // uint32 entsize; // sizeof(struct _ivar_t)
6073 // uint32 count;
6074 // struct _iver_t list[count];
6075 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00006076 IvarListnfABITy =
Serge Guelton1d993272017-05-09 19:31:30 +00006077 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
6078 llvm::ArrayType::get(IvarnfABITy, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006079
Owen Anderson9793f0e2009-07-29 22:16:19 +00006080 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006081
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006082 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006083 // uint32_t const flags;
6084 // uint32_t const instanceStart;
6085 // uint32_t const instanceSize;
6086 // uint32_t const reserved; // only when building for 64bit targets
6087 // const uint8_t * const ivarLayout;
6088 // const char *const name;
6089 // const struct _method_list_t * const baseMethods;
6090 // const struct _objc_protocol_list *const baseProtocols;
6091 // const struct _ivar_list_t *const ivars;
6092 // const uint8_t * const weakIvarLayout;
6093 // const struct _prop_list_t * const properties;
6094 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006095
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006096 // FIXME. Add 'reserved' field in 64bit abi mode!
Serge Guelton1d993272017-05-09 19:31:30 +00006097 ClassRonfABITy = llvm::StructType::create(
6098 "struct._class_ro_t", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy,
6099 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy,
6100 Int8PtrTy, PropertyListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006101
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006102 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00006103 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00006104 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
6105 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006106
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006107 // struct _class_t {
6108 // struct _class_t *isa;
6109 // struct _class_t * const superclass;
6110 // void *cache;
6111 // IMP *vtable;
6112 // struct class_ro_t *ro;
6113 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006114
Chris Lattner5ec04a52011-08-12 17:43:31 +00006115 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00006116 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
Serge Guelton1d993272017-05-09 19:31:30 +00006117 llvm::PointerType::getUnqual(ClassnfABITy), CachePtrTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00006118 llvm::PointerType::getUnqual(ImpnfABITy),
Serge Guelton1d993272017-05-09 19:31:30 +00006119 llvm::PointerType::getUnqual(ClassRonfABITy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006120
Fariborz Jahanian71394042009-01-23 23:53:38 +00006121 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00006122 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006123
Fariborz Jahanian0232c052009-01-23 01:46:23 +00006124 // struct _category_t {
6125 // const char * const name;
6126 // struct _class_t *const cls;
6127 // const struct _method_list_t * const instance_methods;
6128 // const struct _method_list_t * const class_methods;
6129 // const struct _protocol_list_t * const protocols;
6130 // const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00006131 // const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00006132 // const uint32_t size;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00006133 // }
Serge Guelton1d993272017-05-09 19:31:30 +00006134 CategorynfABITy = llvm::StructType::create(
6135 "struct._category_t", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy,
6136 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy,
6137 PropertyListPtrTy, IntTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006138
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006139 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006140 CodeGen::CodeGenTypes &Types = CGM.getTypes();
6141 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006142
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006143 // MessageRefTy - LLVM for:
6144 // struct _message_ref_t {
6145 // IMP messenger;
6146 // SEL name;
6147 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006148
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006149 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00006150 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00006151 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00006152 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006153 &Ctx.Idents.get("_message_ref_t"));
Craig Topper8a13c412014-05-21 05:09:00 +00006154 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6155 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
Richard Smith2b013182012-06-10 03:12:00 +00006156 ICIS_NoInit));
Craig Topper8a13c412014-05-21 05:09:00 +00006157 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6158 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
6159 false, ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00006160 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006161
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006162 MessageRefCTy = Ctx.getTagDeclType(RD);
6163 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
6164 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006165
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006166 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00006167 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006168
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006169 // SuperMessageRefTy - LLVM for:
6170 // struct _super_message_ref_t {
6171 // SUPER_IMP messenger;
6172 // SEL name;
6173 // };
Serge Guelton1d993272017-05-09 19:31:30 +00006174 SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t",
6175 ImpnfABITy, SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006176
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00006177 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006178 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fangrui Song6907ce22018-07-30 19:24:48 +00006179
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006180
6181 // struct objc_typeinfo {
6182 // const void** vtable; // objc_ehtype_vtable + 2
6183 // const char* name; // c++ typeinfo string
6184 // Class cls;
6185 // };
Serge Guelton1d993272017-05-09 19:31:30 +00006186 EHTypeTy = llvm::StructType::create("struct._objc_typeinfo",
6187 llvm::PointerType::getUnqual(Int8PtrTy),
6188 Int8PtrTy, ClassnfABIPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00006189 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00006190}
6191
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006192llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00006193 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006194
Craig Topper8a13c412014-05-21 05:09:00 +00006195 return nullptr;
Fariborz Jahanian71394042009-01-23 23:53:38 +00006196}
6197
Saleem Abdulrasool1e6c4062016-05-16 05:06:49 +00006198void CGObjCNonFragileABIMac::AddModuleClassList(
6199 ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
6200 StringRef SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00006201 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006202
Daniel Dunbar19573e72009-05-15 21:48:48 +00006203 if (!NumClasses)
6204 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006205
Chris Lattner3def9ae2012-02-06 22:16:34 +00006206 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00006207 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00006208 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00006209 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00006210 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00006211 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00006212 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00006213 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006214
Akira Hatanaka187770d2019-05-09 17:43:52 +00006215 // Section name is obtained by calling GetSectionName, which returns
6216 // sections in the __DATA segment on MachO.
6217 assert((!CGM.getTriple().isOSBinFormatMachO() ||
6218 SectionName.startswith("__DATA")) &&
6219 "SectionName expected to start with __DATA on MachO");
6220 llvm::GlobalValue::LinkageTypes LT =
6221 getLinkageTypeForObjCMetadata(CGM, SectionName);
Daniel Dunbar19573e72009-05-15 21:48:48 +00006222 llvm::GlobalVariable *GV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00006223 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, LT, Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006224 SymbolName);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006225 GV->setAlignment(
6226 llvm::Align(CGM.getDataLayout().getABITypeAlignment(Init->getType())));
Daniel Dunbar19573e72009-05-15 21:48:48 +00006227 GV->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00006228 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00006229}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006230
Fariborz Jahanian71394042009-01-23 23:53:38 +00006231void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
6232 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006233
Daniel Dunbar19573e72009-05-15 21:48:48 +00006234 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006235 // L_OBJC_LABEL_CLASS_$.
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00006236
6237 for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) {
6238 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
6239 assert(ID);
6240 if (ObjCImplementationDecl *IMP = ID->getImplementation())
6241 // We are implementing a weak imported interface. Give it external linkage
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00006242 if (ID->isWeakImported() && !IMP->isWeakImported()) {
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00006243 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
Fariborz Jahanianbc94c942014-07-15 17:14:34 +00006244 DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
6245 }
Fariborz Jahanianf322f2f2014-03-11 00:25:05 +00006246 }
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006247
6248 AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006249 GetSectionName("__objc_classlist",
6250 "regular,no_dead_strip"));
Rafael Espindola554256c2014-02-26 22:25:45 +00006251
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006252 AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006253 GetSectionName("__objc_nlclslist",
6254 "regular,no_dead_strip"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006255
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006256 // Build list of all implemented category addresses in array
6257 // L_OBJC_LABEL_CATEGORY_$.
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006258 AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006259 GetSectionName("__objc_catlist",
6260 "regular,no_dead_strip"));
John McCall2c91c3b2019-05-30 04:09:01 +00006261 AddModuleClassList(DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$",
6262 GetSectionName("__objc_catlist2",
6263 "regular,no_dead_strip"));
Rafael Espindola8b27bdb2014-11-06 13:30:38 +00006264 AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$",
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006265 GetSectionName("__objc_nlcatlist",
6266 "regular,no_dead_strip"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006267
Daniel Dunbar5e639272010-04-25 20:39:01 +00006268 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00006269}
6270
John McCall9e8bb002011-05-14 03:10:52 +00006271/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
6272/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006273/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006274/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00006275bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
6276 // At various points we've experimented with using vtable-based
6277 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006278 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006279 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00006280 return false;
John McCall9e8bb002011-05-14 03:10:52 +00006281 case CodeGenOptions::NonLegacy:
6282 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006283 case CodeGenOptions::Mixed:
6284 break;
6285 }
6286
6287 // If so, see whether this selector is in the white-list of things which must
6288 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00006289 if (VTableDispatchMethods.empty()) {
6290 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
6291 VTableDispatchMethods.insert(GetNullarySelector("class"));
6292 VTableDispatchMethods.insert(GetNullarySelector("self"));
6293 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
6294 VTableDispatchMethods.insert(GetNullarySelector("length"));
6295 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006296
John McCall9e8bb002011-05-14 03:10:52 +00006297 // These are vtable-based if GC is disabled.
6298 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006299 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00006300 VTableDispatchMethods.insert(GetNullarySelector("retain"));
6301 VTableDispatchMethods.insert(GetNullarySelector("release"));
6302 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
6303 }
6304
6305 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
6306 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
6307 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
6308 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
6309 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
6310 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
6311 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
6312
6313 // These are vtable-based if GC is enabled.
6314 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006315 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00006316 VTableDispatchMethods.insert(GetNullarySelector("hash"));
6317 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
Fangrui Song6907ce22018-07-30 19:24:48 +00006318
John McCall9e8bb002011-05-14 03:10:52 +00006319 // "countByEnumeratingWithState:objects:count"
6320 IdentifierInfo *KeyIdents[] = {
6321 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
6322 &CGM.getContext().Idents.get("objects"),
6323 &CGM.getContext().Idents.get("count")
6324 };
6325 VTableDispatchMethods.insert(
6326 CGM.getContext().Selectors.getSelector(3, KeyIdents));
6327 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006328 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00006329
John McCall9e8bb002011-05-14 03:10:52 +00006330 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006331}
6332
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006333/// BuildClassRoTInitializer - generate meta-data for:
6334/// struct _class_ro_t {
6335/// uint32_t const flags;
6336/// uint32_t const instanceStart;
6337/// uint32_t const instanceSize;
6338/// uint32_t const reserved; // only when building for 64bit targets
6339/// const uint8_t * const ivarLayout;
6340/// const char *const name;
6341/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006342/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006343/// const struct _ivar_list_t *const ivars;
6344/// const uint8_t * const weakIvarLayout;
6345/// const struct _prop_list_t * const properties;
6346/// }
6347///
6348llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006349 unsigned flags,
6350 unsigned InstanceStart,
6351 unsigned InstanceSize,
6352 const ObjCImplementationDecl *ID) {
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006353 std::string ClassName = ID->getObjCRuntimeNameAsString();
John McCall31168b02011-06-15 23:02:42 +00006354
John McCall3fd13f062015-10-21 18:06:47 +00006355 CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
6356 CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
6357
John McCall460ce582015-10-22 18:38:17 +00006358 bool hasMRCWeak = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00006359 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCallef19dbb2012-10-17 04:53:23 +00006360 flags |= NonFragileABI_Class_CompiledByARC;
John McCall460ce582015-10-22 18:38:17 +00006361 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
6362 flags |= NonFragileABI_Class_HasMRCWeakIvars;
John McCall31168b02011-06-15 23:02:42 +00006363
John McCall176f8922016-11-30 02:39:18 +00006364 ConstantInitBuilder builder(CGM);
6365 auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
6366
6367 values.addInt(ObjCTypes.IntTy, flags);
6368 values.addInt(ObjCTypes.IntTy, InstanceStart);
6369 values.addInt(ObjCTypes.IntTy, InstanceSize);
6370 values.add((flags & NonFragileABI_Class_Meta)
6371 ? GetIvarLayoutName(nullptr, ObjCTypes)
6372 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
6373 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
6374
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006375 // const struct _method_list_t * const baseMethods;
John McCall176f8922016-11-30 02:39:18 +00006376 SmallVector<const ObjCMethodDecl*, 16> methods;
John McCallef19dbb2012-10-17 04:53:23 +00006377 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00006378 for (const auto *MD : ID->class_methods())
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08006379 if (!MD->isDirectMethod())
6380 methods.push_back(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006381 } else {
John McCall176f8922016-11-30 02:39:18 +00006382 for (const auto *MD : ID->instance_methods())
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08006383 if (!MD->isDirectMethod())
6384 methods.push_back(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006385 }
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006386
John McCall176f8922016-11-30 02:39:18 +00006387 values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
6388 (flags & NonFragileABI_Class_Meta)
6389 ? MethodListType::ClassMethods
6390 : MethodListType::InstanceMethods,
6391 methods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006392
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006393 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6394 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Akira Hatanaka187770d2019-05-09 17:43:52 +00006395 values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006396 + OID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006397 OID->all_referenced_protocol_begin(),
6398 OID->all_referenced_protocol_end()));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006399
John McCallef19dbb2012-10-17 04:53:23 +00006400 if (flags & NonFragileABI_Class_Meta) {
John McCall176f8922016-11-30 02:39:18 +00006401 values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
6402 values.add(GetIvarLayoutName(nullptr, ObjCTypes));
6403 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00006404 "_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006405 ID, ID->getClassInterface(), ObjCTypes, true));
John McCallef19dbb2012-10-17 04:53:23 +00006406 } else {
John McCall176f8922016-11-30 02:39:18 +00006407 values.add(EmitIvarList(ID));
6408 values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
6409 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00006410 "_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00006411 ID, ID->getClassInterface(), ObjCTypes, false));
John McCallef19dbb2012-10-17 04:53:23 +00006412 }
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006413
John McCall176f8922016-11-30 02:39:18 +00006414 llvm::SmallString<64> roLabel;
6415 llvm::raw_svector_ostream(roLabel)
Akira Hatanaka187770d2019-05-09 17:43:52 +00006416 << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_"
6417 : "_OBJC_CLASS_RO_$_")
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006418 << ClassName;
6419
Akira Hatanaka187770d2019-05-09 17:43:52 +00006420 return finishAndCreateGlobal(values, roLabel, CGM);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006421}
6422
John McCalldba63a72016-11-30 23:54:50 +00006423/// Build the metaclass object for a class.
6424///
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006425/// struct _class_t {
6426/// struct _class_t *isa;
6427/// struct _class_t * const superclass;
6428/// void *cache;
6429/// IMP *vtable;
6430/// struct class_ro_t *ro;
6431/// }
6432///
John McCalldba63a72016-11-30 23:54:50 +00006433llvm::GlobalVariable *
6434CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI,
6435 bool isMetaclass,
6436 llvm::Constant *IsAGV,
6437 llvm::Constant *SuperClassGV,
6438 llvm::Constant *ClassRoGV,
6439 bool HiddenVisibility) {
John McCall176f8922016-11-30 02:39:18 +00006440 ConstantInitBuilder builder(CGM);
6441 auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
6442 values.add(IsAGV);
6443 if (SuperClassGV) {
6444 values.add(SuperClassGV);
6445 } else {
6446 values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
6447 }
6448 values.add(ObjCEmptyCacheVar);
6449 values.add(ObjCEmptyVtableVar);
6450 values.add(ClassRoGV);
6451
John McCalldba63a72016-11-30 23:54:50 +00006452 llvm::GlobalVariable *GV =
6453 cast<llvm::GlobalVariable>(GetClassGlobal(CI, isMetaclass, ForDefinition));
John McCall176f8922016-11-30 02:39:18 +00006454 values.finishAndSetAsInitializer(GV);
6455
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006456 if (CGM.getTriple().isOSBinFormatMachO())
6457 GV->setSection("__DATA, __objc_data");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006458 GV->setAlignment(llvm::Align(
6459 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy)));
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006460 if (!CGM.getTriple().isOSBinFormatCOFF())
6461 if (HiddenVisibility)
6462 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006463 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006464}
6465
Joe Danielsf7393d22019-02-04 23:32:55 +00006466bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(
6467 const ObjCImplDecl *OD) const {
6468 return OD->getClassMethod(GetNullarySelector("load")) != nullptr ||
Erik Pilkington1138d8c2019-04-11 17:55:34 +00006469 OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() ||
6470 OD->hasAttr<ObjCNonLazyClassAttr>();
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006471}
6472
Daniel Dunbar961202372009-05-03 12:57:56 +00006473void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00006474 uint32_t &InstanceStart,
6475 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006476 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00006477 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006478
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006479 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00006480 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00006481
6482 // If there are no fields, the start is the same as the end.
6483 if (!RL.getFieldCount())
6484 InstanceStart = InstanceSize;
6485 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00006486 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00006487}
6488
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006489static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
6490 StringRef Name) {
6491 IdentifierInfo &II = CGM.getContext().Idents.get(Name);
6492 TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
6493 DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
6494
6495 const VarDecl *VD = nullptr;
6496 for (const auto &Result : DC->lookup(&II))
6497 if ((VD = dyn_cast<VarDecl>(Result)))
6498 break;
6499
6500 if (!VD)
6501 return llvm::GlobalValue::DLLImportStorageClass;
6502 if (VD->hasAttr<DLLExportAttr>())
6503 return llvm::GlobalValue::DLLExportStorageClass;
6504 if (VD->hasAttr<DLLImportAttr>())
6505 return llvm::GlobalValue::DLLImportStorageClass;
6506 return llvm::GlobalValue::DefaultStorageClass;
6507}
6508
Fariborz Jahanian71394042009-01-23 23:53:38 +00006509void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00006510 if (!ObjCEmptyCacheVar) {
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006511 ObjCEmptyCacheVar =
6512 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false,
6513 llvm::GlobalValue::ExternalLinkage, nullptr,
6514 "_objc_empty_cache");
6515 if (CGM.getTriple().isOSBinFormatCOFF())
6516 ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache"));
Craig Topper8a13c412014-05-21 05:09:00 +00006517
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006518 // Only OS X with deployment version <10.9 use the empty vtable symbol
Fariborz Jahanian42d49552013-10-24 17:40:28 +00006519 const llvm::Triple &Triple = CGM.getTarget().getTriple();
Saleem Abdulrasool4f515a62016-07-13 02:58:44 +00006520 if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006521 ObjCEmptyVtableVar =
6522 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false,
6523 llvm::GlobalValue::ExternalLinkage, nullptr,
6524 "_objc_empty_vtable");
John McCall176f8922016-11-30 02:39:18 +00006525 else
6526 ObjCEmptyVtableVar =
6527 llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
Fariborz Jahanian71394042009-01-23 23:53:38 +00006528 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006529
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00006530 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006531 uint32_t InstanceStart =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006532 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006533 uint32_t InstanceSize = InstanceStart;
John McCallef19dbb2012-10-17 04:53:23 +00006534 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006535
John McCalldba63a72016-11-30 23:54:50 +00006536 llvm::Constant *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006537
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006538 const auto *CI = ID->getClassInterface();
6539 assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0");
6540
John McCall0d54a172012-10-17 04:53:31 +00006541 // Build the flags for the metaclass.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006542 bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
6543 ? !CI->hasAttr<DLLExportAttr>()
6544 : CI->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006545 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006546 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006547
6548 // FIXME: why is this flag set on the metaclass?
6549 // ObjC metaclasses have no fields and don't really get constructed.
6550 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006551 flags |= NonFragileABI_Class_HasCXXStructors;
John McCall0d54a172012-10-17 04:53:31 +00006552 if (!ID->hasNonZeroConstructors())
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006553 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
John McCall0d54a172012-10-17 04:53:31 +00006554 }
6555
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006556 if (!CI->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006557 // class is root
John McCallef19dbb2012-10-17 04:53:23 +00006558 flags |= NonFragileABI_Class_Root;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006559
John McCalldba63a72016-11-30 23:54:50 +00006560 SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
6561 IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006562 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006563 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00006564 const ObjCInterfaceDecl *Root = ID->getClassInterface();
6565 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
6566 Root = Super;
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006567
6568 const auto *Super = CI->getSuperClass();
John McCalldba63a72016-11-30 23:54:50 +00006569 IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
6570 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00006571 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006572
6573 llvm::GlobalVariable *CLASS_RO_GV =
6574 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6575
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006576 llvm::GlobalVariable *MetaTClass =
John McCalldba63a72016-11-30 23:54:50 +00006577 BuildClassObject(CI, /*metaclass*/ true,
6578 IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
Rafael Espindolab7350042018-03-01 00:35:47 +00006579 CGM.setGVProperties(MetaTClass, CI);
Fariborz Jahanian67260552009-11-17 21:37:35 +00006580 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00006581
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006582 // Metadata for the class
John McCallef19dbb2012-10-17 04:53:23 +00006583 flags = 0;
Fariborz Jahanian82208252009-01-31 00:59:10 +00006584 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00006585 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00006586
6587 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00006588 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006589
John McCall0d54a172012-10-17 04:53:31 +00006590 // Set a flag to enable a runtime optimization when a class has
6591 // fields that require destruction but which don't require
6592 // anything except zero-initialization during construction. This
6593 // is most notably true of __strong and __weak types, but you can
6594 // also imagine there being C++ types with non-trivial default
6595 // constructors that merely set all fields to null.
6596 if (!ID->hasNonZeroConstructors())
6597 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6598 }
6599
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006600 if (hasObjCExceptionAttribute(CGM.getContext(), CI))
John McCallef19dbb2012-10-17 04:53:23 +00006601 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006602
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006603 if (!CI->getSuperClass()) {
John McCallef19dbb2012-10-17 04:53:23 +00006604 flags |= NonFragileABI_Class_Root;
Craig Topper8a13c412014-05-21 05:09:00 +00006605 SuperClassGV = nullptr;
Chris Lattnerb433b272009-04-19 06:02:28 +00006606 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006607 // Has a root. Current class is not a root.
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006608 const auto *Super = CI->getSuperClass();
John McCalldba63a72016-11-30 23:54:50 +00006609 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00006610 }
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006611
Daniel Dunbar961202372009-05-03 12:57:56 +00006612 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006613 CLASS_RO_GV =
6614 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006615
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006616 llvm::GlobalVariable *ClassMD =
John McCalldba63a72016-11-30 23:54:50 +00006617 BuildClassObject(CI, /*metaclass*/ false,
6618 MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden);
Rafael Espindolab7350042018-03-01 00:35:47 +00006619 CGM.setGVProperties(ClassMD, CI);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00006620 DefinedClasses.push_back(ClassMD);
Saleem Abdulrasoolbc2d9992016-07-16 22:42:04 +00006621 ImplementedClasses.push_back(CI);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006622
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006623 // Determine if this class is also "non-lazy".
6624 if (ImplementationIsNonLazy(ID))
6625 DefinedNonLazyClasses.push_back(ClassMD);
6626
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006627 // Force the definition of the EHType if necessary.
John McCallef19dbb2012-10-17 04:53:23 +00006628 if (flags & NonFragileABI_Class_Exception)
John McCalldba63a72016-11-30 23:54:50 +00006629 (void) GetInterfaceEHType(CI, ForDefinition);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006630 // Make sure method definition entries are all clear for next implementation.
6631 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00006632}
6633
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006634/// GenerateProtocolRef - This routine is called to generate code for
6635/// a protocol reference expression; as in:
6636/// @code
6637/// @protocol(Proto1);
6638/// @endcode
6639/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
6640/// which will hold address of the protocol meta-data.
6641///
John McCall882987f2013-02-28 19:01:20 +00006642llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006643 const ObjCProtocolDecl *PD) {
6644
Fariborz Jahanian464423d2009-04-10 18:47:34 +00006645 // This routine is called for @protocol only. So, we must build definition
6646 // of protocol's meta-data (not a reference to it!)
6647 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006648 llvm::Constant *Init =
6649 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00006650 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006651
Akira Hatanaka187770d2019-05-09 17:43:52 +00006652 std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_");
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006653 ProtocolName += PD->getObjCRuntimeNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006654
John McCall7f416cc2015-09-08 08:05:57 +00006655 CharUnits Align = CGF.getPointerAlign();
6656
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006657 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
6658 if (PTGV)
John McCall7f416cc2015-09-08 08:05:57 +00006659 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Saleem Abdulrasool9f83f3b2017-06-29 00:54:44 +00006660 PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
6661 llvm::GlobalValue::WeakAnyLinkage, Init,
6662 ProtocolName);
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00006663 PTGV->setSection(GetSectionName("__objc_protorefs",
6664 "coalesced,no_dead_strip"));
Rafael Espindola70efc5b2014-03-06 18:54:12 +00006665 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006666 PTGV->setAlignment(Align.getAsAlign());
Saleem Abdulrasool9f83f3b2017-06-29 00:54:44 +00006667 if (!CGM.getTriple().isOSBinFormatMachO())
6668 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
Saleem Abdulrasoolbe2b5cb2018-01-23 19:35:51 +00006669 CGM.addUsedGlobal(PTGV);
John McCall7f416cc2015-09-08 08:05:57 +00006670 return CGF.Builder.CreateAlignedLoad(PTGV, Align);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006671}
6672
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006673/// GenerateCategory - Build metadata for a category implementation.
6674/// struct _category_t {
6675/// const char * const name;
6676/// struct _class_t *const cls;
6677/// const struct _method_list_t * const instance_methods;
6678/// const struct _method_list_t * const class_methods;
6679/// const struct _protocol_list_t * const protocols;
6680/// const struct _prop_list_t * const properties;
Manman Ren96df0b32016-01-29 23:45:01 +00006681/// const struct _prop_list_t * const class_properties;
Manman Ren42ff3902016-02-24 17:49:50 +00006682/// const uint32_t size;
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006683/// }
6684///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006685void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006686 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Akira Hatanaka187770d2019-05-09 17:43:52 +00006687 const char *Prefix = "_OBJC_$_CATEGORY_";
Fangrui Song6907ce22018-07-30 19:24:48 +00006688
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006689 llvm::SmallString<64> ExtCatName(Prefix);
6690 ExtCatName += Interface->getObjCRuntimeNameAsString();
6691 ExtCatName += "_$_";
6692 ExtCatName += OCD->getNameAsString();
Fangrui Song6907ce22018-07-30 19:24:48 +00006693
John McCall176f8922016-11-30 02:39:18 +00006694 ConstantInitBuilder builder(CGM);
6695 auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
6696 values.add(GetClassName(OCD->getIdentifier()->getName()));
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006697 // meta-class entry symbol
John McCalldba63a72016-11-30 23:54:50 +00006698 values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
John McCall176f8922016-11-30 02:39:18 +00006699 std::string listName =
Saleem Abdulrasool209150a2016-10-24 21:25:57 +00006700 (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006701
John McCall176f8922016-11-30 02:39:18 +00006702 SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
6703 SmallVector<const ObjCMethodDecl *, 8> classMethods;
6704 for (const auto *MD : OCD->methods()) {
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08006705 if (MD->isDirectMethod())
6706 continue;
John McCall176f8922016-11-30 02:39:18 +00006707 if (MD->isInstanceMethod()) {
6708 instanceMethods.push_back(MD);
6709 } else {
6710 classMethods.push_back(MD);
6711 }
6712 }
Fariborz Jahanian2612e142009-01-26 22:58:07 +00006713
John McCall176f8922016-11-30 02:39:18 +00006714 values.add(emitMethodList(listName, MethodListType::CategoryInstanceMethods,
6715 instanceMethods));
6716 values.add(emitMethodList(listName, MethodListType::CategoryClassMethods,
6717 classMethods));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006718
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006719 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00006720 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006721 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006722 SmallString<256> ExtName;
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006723 llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006724 << OCD->getName();
Akira Hatanaka187770d2019-05-09 17:43:52 +00006725 values.add(EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006726 + Interface->getObjCRuntimeNameAsString() + "_$_"
6727 + Category->getName(),
John McCall176f8922016-11-30 02:39:18 +00006728 Category->protocol_begin(),
6729 Category->protocol_end()));
Akira Hatanaka187770d2019-05-09 17:43:52 +00006730 values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00006731 OCD, Category, ObjCTypes, false));
Akira Hatanaka187770d2019-05-09 17:43:52 +00006732 values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
John McCall176f8922016-11-30 02:39:18 +00006733 OCD, Category, ObjCTypes, true));
Mike Stump658fe022009-07-30 22:28:39 +00006734 } else {
John McCall176f8922016-11-30 02:39:18 +00006735 values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
6736 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6737 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00006738 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006739
Manman Ren42ff3902016-02-24 17:49:50 +00006740 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
John McCall176f8922016-11-30 02:39:18 +00006741 values.addInt(ObjCTypes.IntTy, Size);
Manman Ren42ff3902016-02-24 17:49:50 +00006742
John McCall176f8922016-11-30 02:39:18 +00006743 llvm::GlobalVariable *GCATV =
Akira Hatanaka187770d2019-05-09 17:43:52 +00006744 finishAndCreateGlobal(values, ExtCatName.str(), CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00006745 CGM.addCompilerUsedGlobal(GCATV);
John McCall2c91c3b2019-05-30 04:09:01 +00006746 if (Interface->hasAttr<ObjCClassStubAttr>())
6747 DefinedStubCategories.push_back(GCATV);
6748 else
6749 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00006750
6751 // Determine if this category is also "non-lazy".
6752 if (ImplementationIsNonLazy(OCD))
6753 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00006754 // method definition entries must be clear for next implementation.
6755 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006756}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006757
John McCall176f8922016-11-30 02:39:18 +00006758/// emitMethodConstant - Return a struct objc_method constant. If
6759/// forProtocol is true, the implementation will be null; otherwise,
6760/// the method must have a definition registered with the runtime.
6761///
6762/// struct _objc_method {
6763/// SEL _cmd;
6764/// char *method_type;
6765/// char *_imp;
6766/// }
6767void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
6768 const ObjCMethodDecl *MD,
6769 bool forProtocol) {
6770 auto method = builder.beginStruct(ObjCTypes.MethodTy);
6771 method.addBitCast(GetMethodVarName(MD->getSelector()),
6772 ObjCTypes.SelectorPtrTy);
6773 method.add(GetMethodVarType(MD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006774
John McCall176f8922016-11-30 02:39:18 +00006775 if (forProtocol) {
6776 // Protocol methods have no implementation. So, this entry is always NULL.
6777 method.addNullPointer(ObjCTypes.Int8PtrTy);
6778 } else {
6779 llvm::Function *fn = GetMethodDefinition(MD);
6780 assert(fn && "no definition for method?");
6781 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
6782 }
6783
6784 method.finishAndAddTo(builder);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006785}
6786
John McCall176f8922016-11-30 02:39:18 +00006787/// Build meta-data for method declarations.
6788///
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006789/// struct _method_list_t {
6790/// uint32_t entsize; // sizeof(struct _objc_method)
6791/// uint32_t method_count;
6792/// struct _objc_method method_list[method_count];
6793/// }
6794///
Zachary Turner41a9ee92017-10-11 23:54:34 +00006795llvm::Constant *
6796CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
6797 ArrayRef<const ObjCMethodDecl *> methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006798 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006799 if (methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006800 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006801
John McCall176f8922016-11-30 02:39:18 +00006802 StringRef prefix;
6803 bool forProtocol;
6804 switch (kind) {
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006805 case MethodListType::CategoryInstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006806 prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006807 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006808 break;
6809 case MethodListType::CategoryClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006810 prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006811 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006812 break;
6813 case MethodListType::InstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006814 prefix = "_OBJC_$_INSTANCE_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006815 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006816 break;
6817 case MethodListType::ClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006818 prefix = "_OBJC_$_CLASS_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006819 forProtocol = false;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006820 break;
6821
6822 case MethodListType::ProtocolInstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006823 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006824 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006825 break;
6826 case MethodListType::ProtocolClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006827 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_";
John McCall176f8922016-11-30 02:39:18 +00006828 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006829 break;
6830 case MethodListType::OptionalProtocolInstanceMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006831 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_";
John McCall176f8922016-11-30 02:39:18 +00006832 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006833 break;
6834 case MethodListType::OptionalProtocolClassMethods:
Akira Hatanaka187770d2019-05-09 17:43:52 +00006835 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_";
John McCall176f8922016-11-30 02:39:18 +00006836 forProtocol = true;
Saleem Abdulrasoold48b0a32016-10-24 20:47:58 +00006837 break;
6838 }
6839
John McCall176f8922016-11-30 02:39:18 +00006840 ConstantInitBuilder builder(CGM);
6841 auto values = builder.beginStruct();
6842
6843 // sizeof(struct _objc_method)
6844 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
6845 values.addInt(ObjCTypes.IntTy, Size);
6846 // method_count
6847 values.addInt(ObjCTypes.IntTy, methods.size());
6848 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
Adrian Prantl2073dd22019-11-04 14:28:14 -08006849 for (auto MD : methods)
John McCall176f8922016-11-30 02:39:18 +00006850 emitMethodConstant(methodArray, MD, forProtocol);
John McCall176f8922016-11-30 02:39:18 +00006851 methodArray.finishAndAddTo(values);
6852
Akira Hatanaka187770d2019-05-09 17:43:52 +00006853 llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00006854 CGM.addCompilerUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006855 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006856}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006857
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006858/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6859/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006860llvm::GlobalVariable *
6861CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6862 const ObjCIvarDecl *Ivar) {
6863 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00006864 llvm::SmallString<64> Name("OBJC_IVAR_$_");
6865 Name += Container->getObjCRuntimeNameAsString();
6866 Name += ".";
6867 Name += Ivar->getName();
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006868 llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
6869 if (!IvarOffsetGV) {
6870 IvarOffsetGV =
6871 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy,
6872 false, llvm::GlobalValue::ExternalLinkage,
6873 nullptr, Name.str());
6874 if (CGM.getTriple().isOSBinFormatCOFF()) {
6875 bool IsPrivateOrPackage =
6876 Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6877 Ivar->getAccessControl() == ObjCIvarDecl::Package;
6878
Saleem Abdulrasoolad75c7d2017-10-25 03:58:15 +00006879 const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();
6880
6881 if (ContainingID->hasAttr<DLLImportAttr>())
6882 IvarOffsetGV
6883 ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
6884 else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
6885 IvarOffsetGV
6886 ->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006887 }
6888 }
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006889 return IvarOffsetGV;
6890}
6891
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006892llvm::Constant *
6893CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6894 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00006895 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006896 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Tim Northover238b5082014-03-29 13:42:40 +00006897 IvarOffsetGV->setInitializer(
6898 llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
Guillaume Chateletc79099e2019-10-03 13:00:29 +00006899 IvarOffsetGV->setAlignment(llvm::Align(
6900 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy)));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006901
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00006902 if (!CGM.getTriple().isOSBinFormatCOFF()) {
6903 // FIXME: This matches gcc, but shouldn't the visibility be set on the use
6904 // as well (i.e., in ObjCIvarOffsetVariable).
6905 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6906 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6907 ID->getVisibility() == HiddenVisibility)
6908 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6909 else
6910 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
6911 }
6912
Erik Pilkington2ff012d2019-01-17 18:18:53 +00006913 // If ID's layout is known, then make the global constant. This serves as a
6914 // useful assertion: we'll never use this variable to calculate ivar offsets,
6915 // so if the runtime tries to patch it then we should crash.
6916 if (isClassLayoutKnownStatically(ID))
6917 IvarOffsetGV->setConstant(true);
6918
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00006919 if (CGM.getTriple().isOSBinFormatMachO())
6920 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006921 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006922}
6923
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006924/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006925/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006926/// IvarListnfABIPtrTy.
6927/// struct _ivar_t {
Tim Northover238b5082014-03-29 13:42:40 +00006928/// unsigned [long] int *offset; // pointer to ivar offset location
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006929/// char *name;
6930/// char *type;
6931/// uint32_t alignment;
6932/// uint32_t size;
6933/// }
6934/// struct _ivar_list_t {
6935/// uint32 entsize; // sizeof(struct _ivar_t)
6936/// uint32 count;
6937/// struct _iver_t list[count];
6938/// }
6939///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00006940
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006941llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006942 const ObjCImplementationDecl *ID) {
6943
John McCall176f8922016-11-30 02:39:18 +00006944 ConstantInitBuilder builder(CGM);
6945 auto ivarList = builder.beginStruct();
6946 ivarList.addInt(ObjCTypes.IntTy,
6947 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
6948 auto ivarCountSlot = ivarList.addPlaceholder();
6949 auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006950
Jordy Rosea91768e2011-07-22 02:08:32 +00006951 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006952 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006953
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006954 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006955
Fangrui Song6907ce22018-07-30 19:24:48 +00006956 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00006957 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00006958 // Ignore unnamed bit-fields.
6959 if (!IVD->getDeclName())
6960 continue;
John McCall176f8922016-11-30 02:39:18 +00006961
6962 auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
6963 ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
6964 ComputeIvarBaseOffset(CGM, ID, IVD)));
6965 ivar.add(GetMethodVarName(IVD->getIdentifier()));
6966 ivar.add(GetMethodVarType(IVD));
Chris Lattner2192fe52011-07-18 04:24:23 +00006967 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006968 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmowdd31ca12012-10-08 16:25:52 +00006969 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006970 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006971 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006972 Align = llvm::Log2_32(Align);
John McCall176f8922016-11-30 02:39:18 +00006973 ivar.addInt(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00006974 // NOTE. Size of a bitfield does not match gcc's, because of the
6975 // way bitfields are treated special in each. But I am told that
6976 // 'size' for bitfield ivars is ignored by the runtime so it does
6977 // not matter. If it matters, there is enough info to get the
6978 // bitfield right!
John McCall176f8922016-11-30 02:39:18 +00006979 ivar.addInt(ObjCTypes.IntTy, Size);
6980 ivar.finishAndAddTo(ivars);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006981 }
6982 // Return null for empty list.
John McCall176f8922016-11-30 02:39:18 +00006983 if (ivars.empty()) {
6984 ivars.abandon();
6985 ivarList.abandon();
Owen Anderson0b75f232009-07-31 20:28:54 +00006986 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCall176f8922016-11-30 02:39:18 +00006987 }
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006988
John McCall176f8922016-11-30 02:39:18 +00006989 auto ivarCount = ivars.size();
6990 ivars.finishAndAddTo(ivarList);
6991 ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
6992
Akira Hatanaka187770d2019-05-09 17:43:52 +00006993 const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_";
6994 llvm::GlobalVariable *GV = finishAndCreateGlobal(
6995 ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00006996 CGM.addCompilerUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00006997 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006998}
6999
7000llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007001 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007002 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007003
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007004 if (!Entry) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007005 // We use the initializer as a marker of whether this is a forward
7006 // reference or not. At module finalization we add the empty
7007 // contents for protocols which were referenced but never defined.
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007008 llvm::SmallString<64> Protocol;
Akira Hatanaka6bc3a772019-03-14 15:17:37 +00007009 llvm::raw_svector_ostream(Protocol) << "_OBJC_PROTOCOL_$_"
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007010 << PD->getObjCRuntimeNameAsString();
7011
7012 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
7013 false, llvm::GlobalValue::ExternalLinkage,
7014 nullptr, Protocol);
7015 if (!CGM.getTriple().isOSBinFormatMachO())
7016 Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
7017 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007018
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007019 return Entry;
7020}
7021
7022/// GetOrEmitProtocol - Generate the protocol meta-data:
7023/// @code
7024/// struct _protocol_t {
7025/// id isa; // NULL
7026/// const char * const protocol_name;
7027/// const struct _protocol_list_t * protocol_list; // super protocols
7028/// const struct method_list_t * const instance_methods;
7029/// const struct method_list_t * const class_methods;
7030/// const struct method_list_t *optionalInstanceMethods;
7031/// const struct method_list_t *optionalClassMethods;
7032/// const struct _prop_list_t * properties;
7033/// const uint32_t size; // sizeof(struct _protocol_t)
7034/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00007035/// const char ** extendedMethodTypes;
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00007036/// const char *demangledName;
Manman Rence7bff52016-01-29 23:46:55 +00007037/// const struct _prop_list_t * class_properties;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007038/// }
7039/// @endcode
7040///
7041
7042llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007043 const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00007044 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007045
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007046 // Early exit if a defining object has already been generated.
7047 if (Entry && Entry->hasInitializer())
7048 return Entry;
7049
Douglas Gregora715bff2012-01-01 19:51:50 +00007050 // Use the protocol definition, if there is one.
Alex Lorenzb111da12018-08-17 22:18:08 +00007051 assert(PD->hasDefinition() &&
7052 "emitting protocol metadata without definition");
7053 PD = PD->getDefinition();
Fangrui Song6907ce22018-07-30 19:24:48 +00007054
John McCall176f8922016-11-30 02:39:18 +00007055 auto methodLists = ProtocolMethodLists::get(PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007056
John McCall176f8922016-11-30 02:39:18 +00007057 ConstantInitBuilder builder(CGM);
7058 auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
Douglas Gregora9d84932011-05-27 01:19:52 +00007059
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007060 // isa is NULL
John McCall176f8922016-11-30 02:39:18 +00007061 values.addNullPointer(ObjCTypes.ObjectPtrTy);
7062 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
Akira Hatanaka187770d2019-05-09 17:43:52 +00007063 values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_"
John McCall176f8922016-11-30 02:39:18 +00007064 + PD->getObjCRuntimeNameAsString(),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007065 PD->protocol_begin(),
John McCall176f8922016-11-30 02:39:18 +00007066 PD->protocol_end()));
7067 values.add(methodLists.emitMethodList(this, PD,
7068 ProtocolMethodLists::RequiredInstanceMethods));
7069 values.add(methodLists.emitMethodList(this, PD,
7070 ProtocolMethodLists::RequiredClassMethods));
7071 values.add(methodLists.emitMethodList(this, PD,
7072 ProtocolMethodLists::OptionalInstanceMethods));
7073 values.add(methodLists.emitMethodList(this, PD,
7074 ProtocolMethodLists::OptionalClassMethods));
7075 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00007076 "_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00007077 nullptr, PD, ObjCTypes, false));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007078 uint32_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00007079 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
John McCall176f8922016-11-30 02:39:18 +00007080 values.addInt(ObjCTypes.IntTy, Size);
7081 values.addInt(ObjCTypes.IntTy, 0);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007082 values.add(EmitProtocolMethodTypes("_OBJC_$_PROTOCOL_METHOD_TYPES_"
Fariborz Jahanian451b92a2014-07-16 16:16:04 +00007083 + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00007084 methodLists.emitExtendedTypesArray(this),
7085 ObjCTypes));
7086
Fariborz Jahanian6a9c46b2015-03-31 22:22:40 +00007087 // const char *demangledName;
John McCall176f8922016-11-30 02:39:18 +00007088 values.addNullPointer(ObjCTypes.Int8PtrTy);
Manman Rence7bff52016-01-29 23:46:55 +00007089
John McCall176f8922016-11-30 02:39:18 +00007090 values.add(EmitPropertyList(
Akira Hatanaka187770d2019-05-09 17:43:52 +00007091 "_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
John McCall176f8922016-11-30 02:39:18 +00007092 nullptr, PD, ObjCTypes, true));
Fangrui Song6907ce22018-07-30 19:24:48 +00007093
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007094 if (Entry) {
Rafael Espindola24615092014-09-12 20:14:20 +00007095 // Already created, fix the linkage and update the initializer.
7096 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
John McCall176f8922016-11-30 02:39:18 +00007097 values.finishAndSetAsInitializer(Entry);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007098 } else {
John McCall176f8922016-11-30 02:39:18 +00007099 llvm::SmallString<64> symbolName;
7100 llvm::raw_svector_ostream(symbolName)
Akira Hatanaka6bc3a772019-03-14 15:17:37 +00007101 << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007102
John McCall176f8922016-11-30 02:39:18 +00007103 Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
7104 /*constant*/ false,
7105 llvm::GlobalValue::WeakAnyLinkage);
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007106 if (!CGM.getTriple().isOSBinFormatMachO())
John McCall176f8922016-11-30 02:39:18 +00007107 Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
John McCallf9582a72012-03-30 21:29:05 +00007108
7109 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007110 }
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007111 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoolbe2b5cb2018-01-23 19:35:51 +00007112 CGM.addUsedGlobal(Entry);
Chris Lattnerf56501c2009-07-17 23:57:13 +00007113
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00007114 // Use this protocol meta-data to build protocol list table in section
7115 // __DATA, __objc_protolist
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007116 llvm::SmallString<64> ProtocolRef;
Akira Hatanaka6bc3a772019-03-14 15:17:37 +00007117 llvm::raw_svector_ostream(ProtocolRef) << "_OBJC_LABEL_PROTOCOL_$_"
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007118 << PD->getObjCRuntimeNameAsString();
7119
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007120 llvm::GlobalVariable *PTGV =
7121 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007122 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
Saleem Abdulrasool9ccc7ad2016-10-25 14:50:44 +00007123 ProtocolRef);
7124 if (!CGM.getTriple().isOSBinFormatMachO())
7125 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007126 PTGV->setAlignment(llvm::Align(
7127 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)));
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00007128 PTGV->setSection(GetSectionName("__objc_protolist",
7129 "coalesced,no_dead_strip"));
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007130 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoolbe2b5cb2018-01-23 19:35:51 +00007131 CGM.addUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007132 return Entry;
7133}
7134
7135/// EmitProtocolList - Generate protocol list meta-data:
7136/// @code
7137/// struct _protocol_list_t {
7138/// long protocol_count; // Note, this is 32/64 bit
7139/// struct _protocol_t[protocol_count];
7140/// }
7141/// @endcode
7142///
Zachary Turner41a9ee92017-10-11 23:54:34 +00007143llvm::Constant *
7144CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
7145 ObjCProtocolDecl::protocol_iterator begin,
7146 ObjCProtocolDecl::protocol_iterator end) {
Dmitri Gribenkof8579502013-01-12 19:30:44 +00007147 SmallVector<llvm::Constant *, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007148
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007149 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007150 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00007151 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007152
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007153 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00007154 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007155 Name.toVector(TmpName);
7156 llvm::GlobalVariable *GV =
7157 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007158 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00007159 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007160
John McCall176f8922016-11-30 02:39:18 +00007161 ConstantInitBuilder builder(CGM);
7162 auto values = builder.beginStruct();
7163 auto countSlot = values.addPlaceholder();
7164
7165 // A null-terminated array of protocols.
7166 auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007167 for (; begin != end; ++begin)
John McCall176f8922016-11-30 02:39:18 +00007168 array.add(GetProtocolRef(*begin)); // Implemented???
7169 auto count = array.size();
7170 array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007171
John McCall176f8922016-11-30 02:39:18 +00007172 array.finishAndAddTo(values);
7173 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007174
Akira Hatanaka187770d2019-05-09 17:43:52 +00007175 GV = finishAndCreateGlobal(values, Name, CGM);
Rafael Espindola060062a2014-03-06 22:15:10 +00007176 CGM.addCompilerUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007177 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00007178 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00007179}
7180
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00007181/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
7182/// This code gen. amounts to generating code for:
7183/// @code
7184/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
7185/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007186///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00007187LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00007188 CodeGen::CodeGenFunction &CGF,
7189 QualType ObjectTy,
7190 llvm::Value *BaseValue,
7191 const ObjCIvarDecl *Ivar,
7192 unsigned CVRQualifiers) {
Simon Pilgrim5a8b2292019-10-02 20:30:37 +00007193 ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00007194 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00007195 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00007196 Offset);
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00007197}
7198
Erik Pilkington2ff012d2019-01-17 18:18:53 +00007199llvm::Value *
7200CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
7201 const ObjCInterfaceDecl *Interface,
7202 const ObjCIvarDecl *Ivar) {
7203 llvm::Value *IvarOffsetValue;
7204 if (isClassLayoutKnownStatically(Interface)) {
7205 IvarOffsetValue = llvm::ConstantInt::get(
7206 ObjCTypes.IvarOffsetVarTy,
7207 ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar));
7208 } else {
7209 llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
7210 IvarOffsetValue =
7211 CGF.Builder.CreateAlignedLoad(GV, CGF.getSizeAlign(), "ivar");
7212 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
7213 cast<llvm::LoadInst>(IvarOffsetValue)
7214 ->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
7215 llvm::MDNode::get(VMContext, None));
7216 }
Tim Northover238b5082014-03-29 13:42:40 +00007217
7218 // This could be 32bit int or 64bit integer depending on the architecture.
7219 // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007220 // as this is what caller always expects.
Tim Northover238b5082014-03-29 13:42:40 +00007221 if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
7222 IvarOffsetValue = CGF.Builder.CreateIntCast(
7223 IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
7224 return IvarOffsetValue;
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00007225}
7226
John McCall234eac82011-05-13 23:16:18 +00007227static void appendSelectorForMessageRefTable(std::string &buffer,
7228 Selector selector) {
7229 if (selector.isUnarySelector()) {
7230 buffer += selector.getNameForSlot(0);
7231 return;
7232 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007233
John McCall234eac82011-05-13 23:16:18 +00007234 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
7235 buffer += selector.getNameForSlot(i);
7236 buffer += '_';
7237 }
7238}
7239
Eric Christopherd160c502016-01-29 01:35:53 +00007240/// Emit a "vtable" message send. We emit a weak hidden-visibility
John McCall9e8bb002011-05-14 03:10:52 +00007241/// struct, initially containing the selector pointer and a pointer to
7242/// a "fixup" variant of the appropriate objc_msgSend. To call, we
7243/// load and call the function pointer, passing the address of the
7244/// struct as the second parameter. The runtime determines whether
7245/// the selector is currently emitted using vtable dispatch; if so, it
7246/// substitutes a stub function which simply tail-calls through the
7247/// appropriate vtable slot, and if not, it substitues a stub function
7248/// which tail-calls objc_msgSend. Both stubs adjust the selector
7249/// argument to correctly point to the selector.
7250RValue
7251CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
7252 ReturnValueSlot returnSlot,
7253 QualType resultType,
7254 Selector selector,
7255 llvm::Value *arg0,
7256 QualType arg0Type,
7257 bool isSuper,
7258 const CallArgList &formalArgs,
7259 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00007260 // Compute the actual arguments.
7261 CallArgList args;
7262
John McCall9e8bb002011-05-14 03:10:52 +00007263 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00007264 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00007265 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
7266 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00007267
John McCall9e8bb002011-05-14 03:10:52 +00007268 // Second argument: a pointer to the message ref structure. Leave
7269 // the actual argument value blank for now.
Craig Topper8a13c412014-05-21 05:09:00 +00007270 args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
John McCall234eac82011-05-13 23:16:18 +00007271
7272 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
7273
John McCalla729c622012-02-17 03:33:10 +00007274 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCall234eac82011-05-13 23:16:18 +00007275
John McCall5880fb82011-05-14 21:12:11 +00007276 NullReturnState nullReturn;
7277
John McCall9e8bb002011-05-14 03:10:52 +00007278 // Find the function to call and the mangled name for the message
7279 // ref structure. Using a different mangled name wouldn't actually
7280 // be a problem; it would just be a waste.
7281 //
7282 // The runtime currently never uses vtable dispatch for anything
7283 // except normal, non-super message-sends.
7284 // FIXME: don't use this for that.
James Y Knight9871db02019-02-05 16:42:33 +00007285 llvm::FunctionCallee fn = nullptr;
Akira Hatanaka187770d2019-05-09 17:43:52 +00007286 std::string messageRefName("_");
Tim Northovere77cc392014-03-29 13:28:05 +00007287 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
John McCall234eac82011-05-13 23:16:18 +00007288 if (isSuper) {
7289 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
7290 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007291 } else {
John McCall5880fb82011-05-14 21:12:11 +00007292 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00007293 fn = ObjCTypes.getMessageSendStretFixupFn();
7294 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007295 }
John McCall234eac82011-05-13 23:16:18 +00007296 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
7297 fn = ObjCTypes.getMessageSendFpretFixupFn();
7298 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00007299 } else {
John McCall234eac82011-05-13 23:16:18 +00007300 if (isSuper) {
7301 fn = ObjCTypes.getMessageSendSuper2FixupFn();
7302 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007303 } else {
John McCall234eac82011-05-13 23:16:18 +00007304 fn = ObjCTypes.getMessageSendFixupFn();
7305 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00007306 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00007307 }
John McCall234eac82011-05-13 23:16:18 +00007308 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
7309 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007310
John McCall234eac82011-05-13 23:16:18 +00007311 // Append the selector name, except use underscores anywhere we
7312 // would have used colons.
7313 appendSelectorForMessageRefTable(messageRefName, selector);
7314
7315 llvm::GlobalVariable *messageRef
7316 = CGM.getModule().getGlobalVariable(messageRefName);
7317 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00007318 // Build the message ref structure.
John McCall176f8922016-11-30 02:39:18 +00007319 ConstantInitBuilder builder(CGM);
7320 auto values = builder.beginStruct();
James Y Knight9871db02019-02-05 16:42:33 +00007321 values.add(cast<llvm::Constant>(fn.getCallee()));
John McCall176f8922016-11-30 02:39:18 +00007322 values.add(GetMethodVarName(selector));
7323 messageRef = values.finishAndCreateGlobal(messageRefName,
7324 CharUnits::fromQuantity(16),
7325 /*constant*/ false,
7326 llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindola70efc5b2014-03-06 18:54:12 +00007327 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasool13d73d52017-06-03 16:18:09 +00007328 messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced"));
John McCall234eac82011-05-13 23:16:18 +00007329 }
Fangrui Song6907ce22018-07-30 19:24:48 +00007330
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00007331 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00007332 if (CGM.getLangOpts().ObjCAutoRefCount && method)
David Majnemer59f77922016-06-24 04:05:48 +00007333 for (const auto *ParamDecl : method->parameters()) {
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00007334 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
7335 if (!nullReturn.NullBB)
7336 nullReturn.init(CGF, arg0);
7337 requiresnullCheck = true;
7338 break;
7339 }
7340 }
Fangrui Song6907ce22018-07-30 19:24:48 +00007341
John McCall7f416cc2015-09-08 08:05:57 +00007342 Address mref =
7343 Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
7344 CGF.getPointerAlign());
John McCall234eac82011-05-13 23:16:18 +00007345
John McCall9e8bb002011-05-14 03:10:52 +00007346 // Update the message ref argument.
Yaxun Liu5b330e82018-03-15 15:25:19 +00007347 args[1].setRValue(RValue::get(mref.getPointer()));
John McCall234eac82011-05-13 23:16:18 +00007348
7349 // Load the function to call from the message ref table.
James Y Knight751fe282019-02-09 22:22:28 +00007350 Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0);
John McCallb92ab1a2016-10-26 23:46:34 +00007351 llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
John McCall234eac82011-05-13 23:16:18 +00007352
John McCallb92ab1a2016-10-26 23:46:34 +00007353 calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
7354 CGCallee callee(CGCalleeInfo(), calleePtr);
John McCall234eac82011-05-13 23:16:18 +00007355
John McCalla729c622012-02-17 03:33:10 +00007356 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Kuba Mracekbce5cea2017-06-30 16:28:15 +00007357 return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
Craig Topper8a13c412014-05-21 05:09:00 +00007358 requiresnullCheck ? method : nullptr);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007359}
7360
7361/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007362CodeGen::RValue
7363CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007364 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007365 QualType ResultType,
7366 Selector Sel,
7367 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007368 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00007369 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007370 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00007371 return isVTableDispatchedSelector(Sel)
7372 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007373 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00007374 false, CallArgs, Method)
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08007375 : EmitMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007376 Receiver, CGF.getContext().getObjCIdType(),
John McCall1e3157b2015-09-10 22:27:50 +00007377 false, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00007378}
7379
John McCalldba63a72016-11-30 23:54:50 +00007380llvm::Constant *
7381CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
7382 bool metaclass,
7383 ForDefinition_t isForDefinition) {
7384 auto prefix =
7385 (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
7386 return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
7387 isForDefinition,
7388 ID->isWeakImported(),
7389 !isForDefinition
7390 && CGM.getTriple().isOSBinFormatCOFF()
7391 && ID->hasAttr<DLLImportAttr>());
7392}
7393
7394llvm::Constant *
7395CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
7396 ForDefinition_t IsForDefinition,
7397 bool Weak, bool DLLImport) {
Rafael Espindola554256c2014-02-26 22:25:45 +00007398 llvm::GlobalValue::LinkageTypes L =
7399 Weak ? llvm::GlobalValue::ExternalWeakLinkage
7400 : llvm::GlobalValue::ExternalLinkage;
7401
John McCalldba63a72016-11-30 23:54:50 +00007402 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
Erik Pilkington92d8a292018-10-12 17:22:10 +00007403 if (!GV || GV->getType() != ObjCTypes.ClassnfABITy->getPointerTo()) {
7404 auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
7405 nullptr, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007406
John McCalldba63a72016-11-30 23:54:50 +00007407 if (DLLImport)
Erik Pilkington92d8a292018-10-12 17:22:10 +00007408 NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
7409
7410 if (GV) {
7411 GV->replaceAllUsesWith(
7412 llvm::ConstantExpr::getBitCast(NewGV, GV->getType()));
7413 GV->eraseFromParent();
7414 }
7415 GV = NewGV;
7416 CGM.getModule().getGlobalList().push_back(GV);
John McCalldba63a72016-11-30 23:54:50 +00007417 }
7418
Rafael Espindola554256c2014-02-26 22:25:45 +00007419 assert(GV->getLinkage() == L);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00007420 return GV;
7421}
7422
John McCall2c91c3b2019-05-30 04:09:01 +00007423llvm::Constant *
7424CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
7425 llvm::Constant *ClassGV = GetClassGlobal(ID, /*metaclass*/ false,
7426 NotForDefinition);
7427
7428 if (!ID->hasAttr<ObjCClassStubAttr>())
7429 return ClassGV;
7430
7431 ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy);
7432
7433 // Stub classes are pointer-aligned. Classrefs pointing at stub classes
7434 // must set the least significant bit set to 1.
7435 auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
7436 return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx);
7437}
7438
7439llvm::Value *
7440CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF,
7441 const ObjCInterfaceDecl *ID,
7442 llvm::GlobalVariable *Entry) {
7443 if (ID && ID->hasAttr<ObjCClassStubAttr>()) {
7444 // Classrefs pointing at Objective-C stub classes must be loaded by calling
7445 // a special runtime function.
7446 return CGF.EmitRuntimeCall(
7447 ObjCTypes.getLoadClassrefFn(), Entry, "load_classref_result");
7448 }
7449
7450 CharUnits Align = CGF.getPointerAlign();
7451 return CGF.Builder.CreateAlignedLoad(Entry, Align);
7452}
7453
John McCalldba63a72016-11-30 23:54:50 +00007454llvm::Value *
7455CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
7456 IdentifierInfo *II,
7457 const ObjCInterfaceDecl *ID) {
John McCall31168b02011-06-15 23:02:42 +00007458 llvm::GlobalVariable *&Entry = ClassReferences[II];
Fangrui Song6907ce22018-07-30 19:24:48 +00007459
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007460 if (!Entry) {
John McCalldba63a72016-11-30 23:54:50 +00007461 llvm::Constant *ClassGV;
7462 if (ID) {
John McCall2c91c3b2019-05-30 04:09:01 +00007463 ClassGV = GetClassGlobalForClassRef(ID);
John McCalldba63a72016-11-30 23:54:50 +00007464 } else {
7465 ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
7466 NotForDefinition);
John McCall2c91c3b2019-05-30 04:09:01 +00007467 assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy &&
7468 "classref was emitted with the wrong type?");
John McCalldba63a72016-11-30 23:54:50 +00007469 }
7470
Akira Hatanaka187770d2019-05-09 17:43:52 +00007471 std::string SectionName =
7472 GetSectionName("__objc_classrefs", "regular,no_dead_strip");
7473 Entry = new llvm::GlobalVariable(
John McCall2c91c3b2019-05-30 04:09:01 +00007474 CGM.getModule(), ClassGV->getType(), false,
Akira Hatanaka187770d2019-05-09 17:43:52 +00007475 getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
7476 "OBJC_CLASSLIST_REFERENCES_$_");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007477 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
John McCall2c91c3b2019-05-30 04:09:01 +00007478 if (!ID || !ID->hasAttr<ObjCClassStubAttr>())
7479 Entry->setSection(SectionName);
7480
Rafael Espindola060062a2014-03-06 22:15:10 +00007481 CGM.addCompilerUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007482 }
John McCall2c91c3b2019-05-30 04:09:01 +00007483
7484 return EmitLoadOfClassRef(CGF, ID, Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007485}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007486
John McCall882987f2013-02-28 19:01:20 +00007487llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
John McCall31168b02011-06-15 23:02:42 +00007488 const ObjCInterfaceDecl *ID) {
Douglas Gregor24ae22c2016-04-01 23:23:52 +00007489 // If the class has the objc_runtime_visible attribute, we need to
7490 // use the Objective-C runtime to get the class.
7491 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
7492 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
7493
John McCalldba63a72016-11-30 23:54:50 +00007494 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
John McCall31168b02011-06-15 23:02:42 +00007495}
7496
7497llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
John McCall882987f2013-02-28 19:01:20 +00007498 CodeGenFunction &CGF) {
John McCall31168b02011-06-15 23:02:42 +00007499 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
John McCalldba63a72016-11-30 23:54:50 +00007500 return EmitClassRefFromId(CGF, II, nullptr);
John McCall31168b02011-06-15 23:02:42 +00007501}
7502
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007503llvm::Value *
John McCall882987f2013-02-28 19:01:20 +00007504CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007505 const ObjCInterfaceDecl *ID) {
7506 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007507
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00007508 if (!Entry) {
John McCall2c91c3b2019-05-30 04:09:01 +00007509 llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007510 std::string SectionName =
7511 GetSectionName("__objc_superrefs", "regular,no_dead_strip");
7512 Entry = new llvm::GlobalVariable(
John McCall2c91c3b2019-05-30 04:09:01 +00007513 CGM.getModule(), ClassGV->getType(), false,
Akira Hatanaka187770d2019-05-09 17:43:52 +00007514 getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
7515 "OBJC_CLASSLIST_SUP_REFS_$_");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007516 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
Akira Hatanaka187770d2019-05-09 17:43:52 +00007517 Entry->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00007518 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007519 }
John McCall2c91c3b2019-05-30 04:09:01 +00007520
7521 return EmitLoadOfClassRef(CGF, ID, Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007522}
7523
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007524/// EmitMetaClassRef - Return a Value * of the address of _class_t
7525/// meta-data
7526///
John McCall882987f2013-02-28 19:01:20 +00007527llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
Fariborz Jahanian0b3bc242014-06-10 17:08:04 +00007528 const ObjCInterfaceDecl *ID,
7529 bool Weak) {
John McCall7f416cc2015-09-08 08:05:57 +00007530 CharUnits Align = CGF.getPointerAlign();
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007531 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
Rafael Espindola21039aa2014-02-27 16:26:32 +00007532 if (!Entry) {
John McCalldba63a72016-11-30 23:54:50 +00007533 auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007534 std::string SectionName =
7535 GetSectionName("__objc_superrefs", "regular,no_dead_strip");
7536 Entry = new llvm::GlobalVariable(
7537 CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
7538 getLinkageTypeForObjCMetadata(CGM, SectionName), MetaClassGV,
7539 "OBJC_CLASSLIST_SUP_REFS_$_");
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007540 Entry->setAlignment(Align.getAsAlign());
Akira Hatanaka187770d2019-05-09 17:43:52 +00007541 Entry->setSection(SectionName);
Rafael Espindola060062a2014-03-06 22:15:10 +00007542 CGM.addCompilerUsedGlobal(Entry);
Rafael Espindola21039aa2014-02-27 16:26:32 +00007543 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007544
John McCall7f416cc2015-09-08 08:05:57 +00007545 return CGF.Builder.CreateAlignedLoad(Entry, Align);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007546}
7547
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007548/// GetClass - Return a reference to the class for the given interface
7549/// decl.
John McCall882987f2013-02-28 19:01:20 +00007550llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007551 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00007552 if (ID->isWeakImported()) {
John McCalldba63a72016-11-30 23:54:50 +00007553 auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
Nick Lewycky9a441642014-02-27 00:36:00 +00007554 (void)ClassGV;
John McCalldba63a72016-11-30 23:54:50 +00007555 assert(!isa<llvm::GlobalVariable>(ClassGV) ||
7556 cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
Fariborz Jahanian95ace552009-11-17 22:42:00 +00007557 }
Fangrui Song6907ce22018-07-30 19:24:48 +00007558
John McCall882987f2013-02-28 19:01:20 +00007559 return EmitClassRef(CGF, ID);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00007560}
7561
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007562/// Generates a message send where the super is the receiver. This is
7563/// a message send to self with special delivery semantics indicating
7564/// which class's method should be called.
7565CodeGen::RValue
7566CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00007567 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007568 QualType ResultType,
7569 Selector Sel,
7570 const ObjCInterfaceDecl *Class,
7571 bool isCategoryImpl,
7572 llvm::Value *Receiver,
7573 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00007574 const CodeGen::CallArgList &CallArgs,
7575 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007576 // ...
7577 // Create and init a super structure; this is a (receiver, class)
7578 // pair we will pass to objc_msgSendSuper.
John McCall7f416cc2015-09-08 08:05:57 +00007579 Address ObjCSuper =
7580 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
7581 "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007582
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007583 llvm::Value *ReceiverAsObject =
7584 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
James Y Knight751fe282019-02-09 22:22:28 +00007585 CGF.Builder.CreateStore(ReceiverAsObject,
7586 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007587
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007588 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00007589 llvm::Value *Target;
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007590 if (IsClassMessage)
Fariborz Jahanian85b99da2014-08-28 17:05:17 +00007591 Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
Fariborz Jahanian27678b02012-10-10 23:11:18 +00007592 else
John McCall882987f2013-02-28 19:01:20 +00007593 Target = EmitSuperClassRef(CGF, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007594
Mike Stump18bb9282009-05-16 07:57:57 +00007595 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
7596 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00007597 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007598 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
7599 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
James Y Knight751fe282019-02-09 22:22:28 +00007600 CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007601
John McCall9e8bb002011-05-14 03:10:52 +00007602 return (isVTableDispatchedSelector(Sel))
7603 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
John McCall7f416cc2015-09-08 08:05:57 +00007604 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00007605 true, CallArgs, Method)
Pierre Habouzitd4e1ba32019-11-07 23:14:58 -08007606 : EmitMessageSend(CGF, Return, ResultType, Sel,
John McCall7f416cc2015-09-08 08:05:57 +00007607 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
John McCall1e3157b2015-09-10 22:27:50 +00007608 true, CallArgs, Method, Class, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00007609}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007610
John McCall882987f2013-02-28 19:01:20 +00007611llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007612 Selector Sel) {
Erik Pilkingtond5e66f0e2019-12-10 16:43:39 -08007613 Address Addr = EmitSelectorAddr(Sel);
John McCall7f416cc2015-09-08 08:05:57 +00007614
7615 llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
Fangrui Song6907ce22018-07-30 19:24:48 +00007616 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
John McCall7f416cc2015-09-08 08:05:57 +00007617 llvm::MDNode::get(VMContext, None));
7618 return LI;
7619}
7620
Erik Pilkingtond5e66f0e2019-12-10 16:43:39 -08007621Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007622 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Erik Pilkingtond5e66f0e2019-12-10 16:43:39 -08007623 CharUnits Align = CGM.getPointerAlign();
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007624 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007625 llvm::Constant *Casted =
7626 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
7627 ObjCTypes.SelectorPtrTy);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007628 std::string SectionName =
7629 GetSectionName("__objc_selrefs", "literal_pointers,no_dead_strip");
7630 Entry = new llvm::GlobalVariable(
7631 CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
7632 getLinkageTypeForObjCMetadata(CGM, SectionName), Casted,
7633 "OBJC_SELECTOR_REFERENCES_");
Michael Gottesman5c205962013-02-05 23:08:45 +00007634 Entry->setExternallyInitialized(true);
Akira Hatanaka187770d2019-05-09 17:43:52 +00007635 Entry->setSection(SectionName);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007636 Entry->setAlignment(Align.getAsAlign());
Rafael Espindola060062a2014-03-06 22:15:10 +00007637 CGM.addCompilerUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007638 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007639
John McCall7f416cc2015-09-08 08:05:57 +00007640 return Address(Entry, Align);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007641}
John McCall7f416cc2015-09-08 08:05:57 +00007642
Fariborz Jahanian06292952009-02-16 22:52:32 +00007643/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007644/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00007645///
7646void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00007647 llvm::Value *src,
John McCall7f416cc2015-09-08 08:05:57 +00007648 Address dst,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00007649 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007650 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007651 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007652 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007653 assert(Size <= 8 && "does not support size > 8");
7654 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7655 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007656 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7657 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007658 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7659 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007660 llvm::Value *args[] = { src, dst.getPointer(), ivarOffset };
John McCall882987f2013-02-28 19:01:20 +00007661 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007662}
7663
7664/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
7665/// objc_assign_strongCast (id src, id *dst)
7666///
7667void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007668 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007669 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007670 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007671 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007672 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007673 assert(Size <= 8 && "does not support size > 8");
7674 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007675 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007676 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7677 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007678 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7679 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007680 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007681 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
7682 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007683}
7684
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007685void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007686 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007687 Address DestPtr,
7688 Address SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00007689 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007690 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
7691 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007692 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size };
John McCall882987f2013-02-28 19:01:20 +00007693 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00007694}
7695
Fariborz Jahanian06292952009-02-16 22:52:32 +00007696/// EmitObjCWeakRead - Code gen for loading value of a __weak
7697/// object: objc_read_weak (id *src)
7698///
7699llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007700 CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007701 Address AddrWeakObj) {
7702 llvm::Type *DestTy = AddrWeakObj.getElementType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007703 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
John McCall882987f2013-02-28 19:01:20 +00007704 llvm::Value *read_weak =
7705 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
John McCall7f416cc2015-09-08 08:05:57 +00007706 AddrWeakObj.getPointer(), "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00007707 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00007708 return read_weak;
7709}
7710
7711/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
7712/// objc_assign_weak (id src, id *dst)
7713///
7714void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007715 llvm::Value *src, Address dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007716 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007717 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007718 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007719 assert(Size <= 8 && "does not support size > 8");
7720 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7721 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007722 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7723 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007724 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7725 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007726 llvm::Value *args[] = { src, dst.getPointer() };
John McCall882987f2013-02-28 19:01:20 +00007727 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
7728 args, "weakassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007729}
7730
7731/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
7732/// objc_assign_global (id src, id *dst)
7733///
7734void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
John McCall7f416cc2015-09-08 08:05:57 +00007735 llvm::Value *src, Address dst,
Fariborz Jahanian217af242010-07-20 20:30:03 +00007736 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00007737 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007738 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00007739 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00007740 assert(Size <= 8 && "does not support size > 8");
7741 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7742 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00007743 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7744 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00007745 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7746 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
John McCall7f416cc2015-09-08 08:05:57 +00007747 llvm::Value *args[] = { src, dst.getPointer() };
Fariborz Jahanian217af242010-07-20 20:30:03 +00007748 if (!threadlocal)
John McCall882987f2013-02-28 19:01:20 +00007749 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
7750 args, "globalassign");
Fariborz Jahanian217af242010-07-20 20:30:03 +00007751 else
John McCall882987f2013-02-28 19:01:20 +00007752 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
7753 args, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00007754}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00007755
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007756void
John McCallbd309292010-07-06 01:34:17 +00007757CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
7758 const ObjCAtSynchronizedStmt &S) {
James Y Knight9871db02019-02-05 16:42:33 +00007759 EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(),
7760 ObjCTypes.getSyncExitFn());
John McCallbd309292010-07-06 01:34:17 +00007761}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007762
John McCall2ca705e2010-07-24 00:37:23 +00007763llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00007764CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00007765 // There's a particular fixed type info for 'id'.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007766 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
7767 auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007768 if (!IDEHType) {
John McCall2ca705e2010-07-24 00:37:23 +00007769 IDEHType =
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007770 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
7771 llvm::GlobalValue::ExternalLinkage, nullptr,
7772 "OBJC_EHTYPE_id");
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007773 if (CGM.getTriple().isOSBinFormatCOFF())
7774 IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id"));
7775 }
John McCall2ca705e2010-07-24 00:37:23 +00007776 return IDEHType;
7777 }
7778
7779 // All other types should be Objective-C interface pointer types.
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007780 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
John McCall2ca705e2010-07-24 00:37:23 +00007781 assert(PT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007782
John McCall2ca705e2010-07-24 00:37:23 +00007783 const ObjCInterfaceType *IT = PT->getInterfaceType();
7784 assert(IT && "Invalid @catch type.");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007785
John McCalldba63a72016-11-30 23:54:50 +00007786 return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007787}
John McCall2ca705e2010-07-24 00:37:23 +00007788
John McCallbd309292010-07-06 01:34:17 +00007789void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
7790 const ObjCAtTryStmt &S) {
James Y Knight9871db02019-02-05 16:42:33 +00007791 EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(),
7792 ObjCTypes.getObjCEndCatchFn(),
7793 ObjCTypes.getExceptionRethrowFn());
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00007794}
7795
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007796/// EmitThrowStmt - Generate code for a throw statement.
7797void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007798 const ObjCAtThrowStmt &S,
7799 bool ClearInsertionPoint) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007800 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00007801 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00007802 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
James Y Knight3933add2019-01-30 02:54:28 +00007803 llvm::CallBase *Call =
7804 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception);
7805 Call->setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007806 } else {
James Y Knight3933add2019-01-30 02:54:28 +00007807 llvm::CallBase *Call =
7808 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn());
7809 Call->setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007810 }
7811
John McCall17afe452010-10-16 08:21:07 +00007812 CGF.Builder.CreateUnreachable();
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00007813 if (ClearInsertionPoint)
7814 CGF.Builder.ClearInsertionPoint();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00007815}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007816
John McCall2ca705e2010-07-24 00:37:23 +00007817llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007818CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
John McCalldba63a72016-11-30 23:54:50 +00007819 ForDefinition_t IsForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007820 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007821 StringRef ClassName = ID->getObjCRuntimeNameAsString();
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007822
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007823 // If we don't need a definition, return the entry if found or check
7824 // if we use an external reference.
John McCalldba63a72016-11-30 23:54:50 +00007825 if (!IsForDefinition) {
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007826 if (Entry)
7827 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00007828
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007829 // If this type (or a super class) has the __objc_exception__
7830 // attribute, emit an external reference.
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007831 if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
7832 std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str();
7833 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
7834 false, llvm::GlobalValue::ExternalLinkage,
7835 nullptr, EHTypeName);
Rafael Espindolab7350042018-03-01 00:35:47 +00007836 CGM.setGVProperties(Entry, ID);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007837 return Entry;
7838 }
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007839 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007840
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007841 // Otherwise we need to either make a new entry or fill in the initializer.
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007842 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007843
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007844 std::string VTableName = "objc_ehtype_vtable";
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007845 auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007846 if (!VTableGV) {
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007847 VTableGV =
7848 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false,
7849 llvm::GlobalValue::ExternalLinkage, nullptr,
7850 VTableName);
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007851 if (CGM.getTriple().isOSBinFormatCOFF())
7852 VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
7853 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007854
Chris Lattnerece04092012-02-07 00:39:47 +00007855 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
John McCall176f8922016-11-30 02:39:18 +00007856 ConstantInitBuilder builder(CGM);
7857 auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
Ahmed Bougacha5d0199a2017-11-17 19:46:47 +00007858 values.add(
7859 llvm::ConstantExpr::getInBoundsGetElementPtr(VTableGV->getValueType(),
7860 VTableGV, VTableIdx));
John McCalldba63a72016-11-30 23:54:50 +00007861 values.add(GetClassName(ClassName));
7862 values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007863
John McCalldba63a72016-11-30 23:54:50 +00007864 llvm::GlobalValue::LinkageTypes L = IsForDefinition
Rafael Espindola554256c2014-02-26 22:25:45 +00007865 ? llvm::GlobalValue::ExternalLinkage
7866 : llvm::GlobalValue::WeakAnyLinkage;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007867 if (Entry) {
John McCall176f8922016-11-30 02:39:18 +00007868 values.finishAndSetAsInitializer(Entry);
Guillaume Chateletc79099e2019-10-03 13:00:29 +00007869 Entry->setAlignment(CGM.getPointerAlign().getAsAlign());
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007870 } else {
John McCall176f8922016-11-30 02:39:18 +00007871 Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName,
7872 CGM.getPointerAlign(),
7873 /*constant*/ false,
7874 L);
Rafael Espindolab7350042018-03-01 00:35:47 +00007875 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
7876 CGM.setGVProperties(Entry, ID);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007877 }
Rafael Espindola554256c2014-02-26 22:25:45 +00007878 assert(Entry->getLinkage() == L);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007879
Saleem Abdulrasool7093e212016-07-17 22:27:44 +00007880 if (!CGM.getTriple().isOSBinFormatCOFF())
7881 if (ID->getVisibility() == HiddenVisibility)
7882 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Saleem Abdulrasoole5f3eae2016-07-17 22:27:38 +00007883
John McCalldba63a72016-11-30 23:54:50 +00007884 if (IsForDefinition)
Saleem Abdulrasool3c628af2016-10-25 21:43:28 +00007885 if (CGM.getTriple().isOSBinFormatMachO())
7886 Entry->setSection("__DATA,__objc_const");
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007887
7888 return Entry;
7889}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007890
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00007891/* *** */
7892
Daniel Dunbarb036db82008-08-13 03:21:16 +00007893CodeGen::CGObjCRuntime *
7894CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall5fb5df92012-06-20 06:18:46 +00007895 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7896 case ObjCRuntime::FragileMacOSX:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007897 return new CGObjCMac(CGM);
John McCall5fb5df92012-06-20 06:18:46 +00007898
7899 case ObjCRuntime::MacOSX:
7900 case ObjCRuntime::iOS:
Tim Northover756447a2015-10-30 16:30:36 +00007901 case ObjCRuntime::WatchOS:
John McCall5fb5df92012-06-20 06:18:46 +00007902 return new CGObjCNonFragileABIMac(CGM);
7903
David Chisnallb601c962012-07-03 20:49:52 +00007904 case ObjCRuntime::GNUstep:
7905 case ObjCRuntime::GCC:
John McCall775086e2012-07-12 02:07:58 +00007906 case ObjCRuntime::ObjFW:
John McCall5fb5df92012-06-20 06:18:46 +00007907 llvm_unreachable("these runtimes are not Mac runtimes");
7908 }
7909 llvm_unreachable("bad runtime");
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007910}