blob: 1b9554729248261b9ade3d8952fbc2029a63c517 [file] [log] [blame]
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattner57540c52011-04-15 05:22:18 +000010// This provides Objective-C code generation targeting the Apple runtime.
Daniel Dunbar303e2c22008-08-11 02:45:11 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000015
Daniel Dunbar034299e2010-03-31 01:09:11 +000016#include "CGRecordLayout.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000017#include "CodeGenModule.h"
Daniel Dunbara94ecd22008-08-16 03:19:19 +000018#include "CodeGenFunction.h"
John McCallad7c5c12011-02-08 08:22:06 +000019#include "CGBlocks.h"
John McCalled1ae862011-01-28 11:13:47 +000020#include "CGCleanup.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000021#include "clang/AST/ASTContext.h"
Daniel Dunbar221fa942008-08-11 04:54:23 +000022#include "clang/AST/Decl.h"
Daniel Dunbarb036db82008-08-13 03:21:16 +000023#include "clang/AST/DeclObjC.h"
Anders Carlsson15b73de2009-07-18 19:43:29 +000024#include "clang/AST/RecordLayout.h"
Chris Lattnerf0b64d72009-04-26 01:32:48 +000025#include "clang/AST/StmtObjC.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000026#include "clang/Basic/LangOptions.h"
Chandler Carruth85098242010-06-15 23:19:56 +000027#include "clang/Frontend/CodeGenOptions.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000028
John McCall42227ed2010-07-31 23:20:56 +000029#include "llvm/InlineAsm.h"
30#include "llvm/IntrinsicInst.h"
Owen Andersonae86c192009-07-13 04:10:07 +000031#include "llvm/LLVMContext.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000032#include "llvm/Module.h"
Daniel Dunbarc475d422008-10-29 22:36:39 +000033#include "llvm/ADT/DenseSet.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000034#include "llvm/ADT/SetVector.h"
35#include "llvm/ADT/SmallString.h"
Fariborz Jahanian751c1e72009-12-12 21:26:21 +000036#include "llvm/ADT/SmallPtrSet.h"
John McCall5c08ab92010-07-13 22:12:14 +000037#include "llvm/Support/CallSite.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000038#include "llvm/Support/raw_ostream.h"
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +000039#include "llvm/Target/TargetData.h"
Torok Edwindb714922009-08-24 13:25:12 +000040#include <cstdio>
Daniel Dunbar303e2c22008-08-11 02:45:11 +000041
42using namespace clang;
Daniel Dunbar41cf9de2008-09-09 01:06:48 +000043using namespace CodeGen;
Daniel Dunbar303e2c22008-08-11 02:45:11 +000044
45namespace {
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000046
Daniel Dunbar59e476b2009-08-03 17:06:42 +000047// FIXME: We should find a nicer way to make the labels for metadata, string
48// concatenation is lame.
Daniel Dunbarb036db82008-08-13 03:21:16 +000049
Fariborz Jahanian279eda62009-01-21 22:04:16 +000050class ObjCCommonTypesHelper {
Owen Anderson170229f2009-07-14 23:10:40 +000051protected:
52 llvm::LLVMContext &VMContext;
Daniel Dunbar59e476b2009-08-03 17:06:42 +000053
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000054private:
John McCall9dc0db22011-05-15 01:53:33 +000055 // The types of these functions don't really matter because we
56 // should always bitcast before calling them.
57
58 /// id objc_msgSend (id, SEL, ...)
59 ///
60 /// The default messenger, used for sends whose ABI is unchanged from
61 /// the all-integer/pointer case.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000062 llvm::Constant *getMessageSendFn() const {
John McCall31168b02011-06-15 23:02:42 +000063 // Add the non-lazy-bind attribute, since objc_msgSend is likely to
64 // be called a lot.
Chris Lattnera5f58b02011-07-09 17:41:47 +000065 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +000066 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
67 params, true),
John McCall31168b02011-06-15 23:02:42 +000068 "objc_msgSend",
69 llvm::Attribute::NonLazyBind);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000070 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000071
John McCall9dc0db22011-05-15 01:53:33 +000072 /// void objc_msgSend_stret (id, SEL, ...)
73 ///
74 /// The messenger used when the return value is an aggregate returned
75 /// by indirect reference in the first argument, and therefore the
76 /// self and selector parameters are shifted over by one.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000077 llvm::Constant *getMessageSendStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000078 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +000079 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
80 params, true),
81 "objc_msgSend_stret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000082
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000083 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000084
John McCall9dc0db22011-05-15 01:53:33 +000085 /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
86 ///
87 /// The messenger used when the return value is returned on the x87
88 /// floating-point stack; without a special entrypoint, the nil case
89 /// would be unbalanced.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000090 llvm::Constant *getMessageSendFpretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000091 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Chris Lattnerece04092012-02-07 00:39:47 +000092 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
93 params, true),
John McCall9dc0db22011-05-15 01:53:33 +000094 "objc_msgSend_fpret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000095
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.
103 llvm::Constant *getMessageSendFp2retFn() const {
104 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
105 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
106 llvm::Type *resultType =
107 llvm::StructType::get(longDoubleType, longDoubleType, NULL);
108
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.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000119 llvm::Constant *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.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000130 llvm::Constant *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.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000141 llvm::Constant *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.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000152 llvm::Constant *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
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000159 llvm::Constant *getMessageSendSuperFpretFn() const {
160 // There is no objc_msgSendSuper_fpret? How can that work?
161 return getMessageSendSuperFn();
162 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000163
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000164 llvm::Constant *getMessageSendSuperFpretFn2() const {
165 // 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:
Chris Lattnera5f58b02011-07-09 17:41:47 +0000173 llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000174 llvm::Type *Int8PtrTy, *Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000175
Daniel Dunbar5d715592008-08-12 05:28:47 +0000176 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000177 llvm::Type *ObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000178
Fariborz Jahanian406b1172008-11-18 20:18:11 +0000179 /// PtrObjectPtrTy - LLVM type for id *
Chris Lattnera5f58b02011-07-09 17:41:47 +0000180 llvm::Type *PtrObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000181
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000182 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000183 llvm::Type *SelectorPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000184
185private:
Daniel Dunbarb036db82008-08-13 03:21:16 +0000186 /// ProtocolPtrTy - LLVM type for external protocol handles
187 /// (typeof(Protocol))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000188 llvm::Type *ExternalProtocolPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000189
190public:
191 llvm::Type *getExternalProtocolPtrTy() {
192 if (!ExternalProtocolPtrTy) {
193 // FIXME: It would be nice to unify this with the opaque type, so that the
194 // IR comes out a bit cleaner.
195 CodeGen::CodeGenTypes &Types = CGM.getTypes();
196 ASTContext &Ctx = CGM.getContext();
197 llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
198 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
199 }
200
201 return ExternalProtocolPtrTy;
202 }
203
Daniel Dunbarc722b852008-08-30 03:02:31 +0000204 // SuperCTy - clang type for struct objc_super.
205 QualType SuperCTy;
206 // SuperPtrCTy - clang type for struct objc_super *.
207 QualType SuperPtrCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000208
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000209 /// SuperTy - LLVM type for struct objc_super.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000210 llvm::StructType *SuperTy;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +0000211 /// SuperPtrTy - LLVM type for struct objc_super *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000212 llvm::Type *SuperPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000213
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000214 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
215 /// in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000216 llvm::StructType *PropertyTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000217
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000218 /// PropertyListTy - LLVM type for struct objc_property_list
219 /// (_prop_list_t in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000220 llvm::StructType *PropertyListTy;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000221 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000222 llvm::Type *PropertyListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000223
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000224 // MethodTy - LLVM type for struct objc_method.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000225 llvm::StructType *MethodTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000226
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000227 /// CacheTy - LLVM type for struct objc_cache.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000228 llvm::Type *CacheTy;
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000229 /// CachePtrTy - LLVM type for struct objc_cache *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000230 llvm::Type *CachePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000231
Chris Lattnerce8754e2009-04-22 02:44:54 +0000232 llvm::Constant *getGetPropertyFn() {
233 CodeGen::CodeGenTypes &Types = CGM.getTypes();
234 ASTContext &Ctx = CGM.getContext();
235 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000236 SmallVector<CanQualType,4> Params;
John McCall2da83a32010-02-26 00:48:12 +0000237 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
238 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000239 Params.push_back(IdType);
240 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000241 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000242 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000243 llvm::FunctionType *FTy =
John McCallab26cfa2010-02-05 21:31:56 +0000244 Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000245 FunctionType::ExtInfo()),
246 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000247 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
248 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000249
Chris Lattnerce8754e2009-04-22 02:44:54 +0000250 llvm::Constant *getSetPropertyFn() {
251 CodeGen::CodeGenTypes &Types = CGM.getTypes();
252 ASTContext &Ctx = CGM.getContext();
253 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000254 SmallVector<CanQualType,6> Params;
John McCall2da83a32010-02-26 00:48:12 +0000255 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
256 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000257 Params.push_back(IdType);
258 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000259 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000260 Params.push_back(IdType);
261 Params.push_back(Ctx.BoolTy);
262 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000263 llvm::FunctionType *FTy =
John McCallab26cfa2010-02-05 21:31:56 +0000264 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000265 FunctionType::ExtInfo()),
266 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000267 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
268 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000269
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000270
271 llvm::Constant *getCopyStructFn() {
272 CodeGen::CodeGenTypes &Types = CGM.getTypes();
273 ASTContext &Ctx = CGM.getContext();
274 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000275 SmallVector<CanQualType,5> Params;
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000276 Params.push_back(Ctx.VoidPtrTy);
277 Params.push_back(Ctx.VoidPtrTy);
278 Params.push_back(Ctx.LongTy);
279 Params.push_back(Ctx.BoolTy);
280 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000281 llvm::FunctionType *FTy =
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000282 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
283 FunctionType::ExtInfo()),
284 false);
285 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
286 }
287
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000288 /// This routine declares and returns address of:
289 /// void objc_copyCppObjectAtomic(
290 /// void *dest, const void *src,
291 /// void (*copyHelper) (void *dest, const void *source));
292 llvm::Constant *getCppAtomicObjectFunction() {
293 CodeGen::CodeGenTypes &Types = CGM.getTypes();
294 ASTContext &Ctx = CGM.getContext();
295 /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
296 SmallVector<CanQualType,3> Params;
297 Params.push_back(Ctx.VoidPtrTy);
298 Params.push_back(Ctx.VoidPtrTy);
299 Params.push_back(Ctx.VoidPtrTy);
300 llvm::FunctionType *FTy =
301 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
302 FunctionType::ExtInfo()),
303 false);
304 return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
305 }
306
Chris Lattnerce8754e2009-04-22 02:44:54 +0000307 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000308 CodeGen::CodeGenTypes &Types = CGM.getTypes();
309 ASTContext &Ctx = CGM.getContext();
Chris Lattnerce8754e2009-04-22 02:44:54 +0000310 // void objc_enumerationMutation (id)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000311 SmallVector<CanQualType,1> Params;
John McCall2da83a32010-02-26 00:48:12 +0000312 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Chris Lattner2192fe52011-07-18 04:24:23 +0000313 llvm::FunctionType *FTy =
John McCallab26cfa2010-02-05 21:31:56 +0000314 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000315 FunctionType::ExtInfo()),
316 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000317 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
318 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000319
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000320 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattnerce8754e2009-04-22 02:44:54 +0000321 llvm::Constant *getGcReadWeakFn() {
322 // id objc_read_weak (id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000323 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000324 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000325 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000326 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000327 }
328
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000329 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000330 llvm::Constant *getGcAssignWeakFn() {
331 // id objc_assign_weak (id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000332 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000333 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000334 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000335 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
336 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000337
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000338 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000339 llvm::Constant *getGcAssignGlobalFn() {
340 // id objc_assign_global(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000341 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000342 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000343 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000344 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
345 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000346
Fariborz Jahanian217af242010-07-20 20:30:03 +0000347 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
348 llvm::Constant *getGcAssignThreadLocalFn() {
349 // id objc_assign_threadlocal(id src, id * dest)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000350 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian217af242010-07-20 20:30:03 +0000351 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000352 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian217af242010-07-20 20:30:03 +0000353 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
354 }
355
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000356 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000357 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000358 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000359 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
360 CGM.PtrDiffTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000361 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000362 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000363 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
364 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000365
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000366 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
367 llvm::Constant *GcMemmoveCollectableFn() {
368 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000369 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
John McCall9dc0db22011-05-15 01:53:33 +0000370 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000371 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
372 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000373
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000374 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000375 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000376 // id objc_assign_strongCast(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000377 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000378 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000379 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000380 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
381 }
Anders Carlsson9ab53d12009-02-16 22:59:18 +0000382
383 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000384 llvm::Constant *getExceptionThrowFn() {
385 // void objc_exception_throw(id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000386 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000387 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000388 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000389 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
390 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000391
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000392 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
393 llvm::Constant *getExceptionRethrowFn() {
394 // void objc_exception_rethrow(void)
John McCall9dc0db22011-05-15 01:53:33 +0000395 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000396 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
397 }
398
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000399 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerdcceee72009-04-06 16:53:45 +0000400 llvm::Constant *getSyncEnterFn() {
401 // void objc_sync_enter (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000402 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerdcceee72009-04-06 16:53:45 +0000403 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000404 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000405 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
406 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000407
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000408 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000409 llvm::Constant *getSyncExitFn() {
410 // void objc_sync_exit (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000411 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000412 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000413 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000414 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
415 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000416
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000417 llvm::Constant *getSendFn(bool IsSuper) const {
418 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
419 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000420
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000421 llvm::Constant *getSendFn2(bool IsSuper) const {
422 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
423 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000424
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000425 llvm::Constant *getSendStretFn(bool IsSuper) const {
426 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
427 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000428
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000429 llvm::Constant *getSendStretFn2(bool IsSuper) const {
430 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
431 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000432
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000433 llvm::Constant *getSendFpretFn(bool IsSuper) const {
434 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
435 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000436
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000437 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
438 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
439 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000440
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000441 llvm::Constant *getSendFp2retFn(bool IsSuper) const {
442 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
443 }
444
445 llvm::Constant *getSendFp2RetFn2(bool IsSuper) const {
446 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
447 }
448
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000449 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
450 ~ObjCCommonTypesHelper(){}
451};
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000452
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000453/// ObjCTypesHelper - Helper class that encapsulates lazy
454/// construction of varies types used during ObjC generation.
455class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000456public:
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000457 /// SymtabTy - LLVM type for struct objc_symtab.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000458 llvm::StructType *SymtabTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000459 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000460 llvm::Type *SymtabPtrTy;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000461 /// ModuleTy - LLVM type for struct objc_module.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000462 llvm::StructType *ModuleTy;
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000463
Daniel Dunbarb036db82008-08-13 03:21:16 +0000464 /// ProtocolTy - LLVM type for struct objc_protocol.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000465 llvm::StructType *ProtocolTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000466 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000467 llvm::Type *ProtocolPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000468 /// ProtocolExtensionTy - LLVM type for struct
469 /// objc_protocol_extension.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000470 llvm::StructType *ProtocolExtensionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000471 /// ProtocolExtensionTy - LLVM type for struct
472 /// objc_protocol_extension *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000473 llvm::Type *ProtocolExtensionPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000474 /// MethodDescriptionTy - LLVM type for struct
475 /// objc_method_description.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000476 llvm::StructType *MethodDescriptionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000477 /// MethodDescriptionListTy - LLVM type for struct
478 /// objc_method_description_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000479 llvm::StructType *MethodDescriptionListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000480 /// MethodDescriptionListPtrTy - LLVM type for struct
481 /// objc_method_description_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000482 llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000483 /// ProtocolListTy - LLVM type for struct objc_property_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000484 llvm::StructType *ProtocolListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000485 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000486 llvm::Type *ProtocolListPtrTy;
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000487 /// CategoryTy - LLVM type for struct objc_category.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000488 llvm::StructType *CategoryTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000489 /// ClassTy - LLVM type for struct objc_class.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000490 llvm::StructType *ClassTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000491 /// ClassPtrTy - LLVM type for struct objc_class *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000492 llvm::Type *ClassPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000493 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000494 llvm::StructType *ClassExtensionTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000495 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000496 llvm::Type *ClassExtensionPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000497 // IvarTy - LLVM type for struct objc_ivar.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000498 llvm::StructType *IvarTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000499 /// IvarListTy - LLVM type for struct objc_ivar_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000500 llvm::Type *IvarListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000501 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000502 llvm::Type *IvarListPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000503 /// MethodListTy - LLVM type for struct objc_method_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000504 llvm::Type *MethodListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000505 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000506 llvm::Type *MethodListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000507
Anders Carlsson9ff22482008-09-09 10:10:21 +0000508 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000509 llvm::Type *ExceptionDataTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000510
Anders Carlsson9ff22482008-09-09 10:10:21 +0000511 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000512 llvm::Constant *getExceptionTryEnterFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000513 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000514 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000515 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000516 "objc_exception_try_enter");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000517 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000518
519 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000520 llvm::Constant *getExceptionTryExitFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000521 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000522 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000523 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000524 "objc_exception_try_exit");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000525 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000526
527 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000528 llvm::Constant *getExceptionExtractFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000529 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000530 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000531 params, false),
Chris Lattnerc6406db2009-04-22 02:26:14 +0000532 "objc_exception_extract");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000533 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000534
Anders Carlsson9ff22482008-09-09 10:10:21 +0000535 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000536 llvm::Constant *getExceptionMatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000537 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000538 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000539 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000540 "objc_exception_match");
541
Chris Lattnerc6406db2009-04-22 02:26:14 +0000542 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000543
Anders Carlsson9ff22482008-09-09 10:10:21 +0000544 /// SetJmpFn - LLVM _setjmp function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000545 llvm::Constant *getSetJmpFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000546 // This is specifically the prototype for x86.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000547 llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
John McCall9dc0db22011-05-15 01:53:33 +0000548 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty,
549 params, false),
Bill Wendlingbcefeae2011-11-29 00:10:10 +0000550 "_setjmp",
551 llvm::Attribute::ReturnsTwice);
Chris Lattnerc6406db2009-04-22 02:26:14 +0000552 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000553
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000554public:
555 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000556 ~ObjCTypesHelper() {}
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000557};
558
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000559/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000560/// modern abi
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000561class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000562public:
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000563
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000564 // MethodListnfABITy - LLVM for struct _method_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000565 llvm::StructType *MethodListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000566
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000567 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000568 llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000569
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000570 // ProtocolnfABITy = LLVM for struct _protocol_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000571 llvm::StructType *ProtocolnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000572
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000573 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000574 llvm::Type *ProtocolnfABIPtrTy;
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000575
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000576 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
Chris Lattnera5f58b02011-07-09 17:41:47 +0000577 llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000578
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000579 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000580 llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000581
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000582 // ClassnfABITy - LLVM for struct _class_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000583 llvm::StructType *ClassnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000584
Fariborz Jahanian71394042009-01-23 23:53:38 +0000585 // ClassnfABIPtrTy - LLVM for struct _class_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000586 llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000587
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000588 // IvarnfABITy - LLVM for struct _ivar_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000589 llvm::StructType *IvarnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000590
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000591 // IvarListnfABITy - LLVM for struct _ivar_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000592 llvm::StructType *IvarListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000593
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000594 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000595 llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000596
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000597 // ClassRonfABITy - LLVM for struct _class_ro_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000598 llvm::StructType *ClassRonfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000599
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000600 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000601 llvm::Type *ImpnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000602
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000603 // CategorynfABITy - LLVM for struct _category_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000604 llvm::StructType *CategorynfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000605
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000606 // New types for nonfragile abi messaging.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000607
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000608 // MessageRefTy - LLVM for:
609 // struct _message_ref_t {
610 // IMP messenger;
611 // SEL name;
612 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000613 llvm::StructType *MessageRefTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000614 // MessageRefCTy - clang type for struct _message_ref_t
615 QualType MessageRefCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000616
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000617 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000618 llvm::Type *MessageRefPtrTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000619 // MessageRefCPtrTy - clang type for struct _message_ref_t*
620 QualType MessageRefCPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000621
Fariborz Jahanian4e87c832009-02-05 01:13:09 +0000622 // MessengerTy - Type of the messenger (shown as IMP above)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000623 llvm::FunctionType *MessengerTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000624
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000625 // SuperMessageRefTy - LLVM for:
626 // struct _super_message_ref_t {
627 // SUPER_IMP messenger;
628 // SEL name;
629 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000630 llvm::StructType *SuperMessageRefTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000631
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000632 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000633 llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000634
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000635 llvm::Constant *getMessageSendFixupFn() {
636 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000637 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000638 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000639 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000640 "objc_msgSend_fixup");
641 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000642
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000643 llvm::Constant *getMessageSendFpretFixupFn() {
644 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000645 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000646 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000647 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000648 "objc_msgSend_fpret_fixup");
649 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000650
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000651 llvm::Constant *getMessageSendStretFixupFn() {
652 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000653 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000654 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000655 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000656 "objc_msgSend_stret_fixup");
657 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000658
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000659 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000660 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000661 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000662 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000663 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000664 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000665 "objc_msgSendSuper2_fixup");
666 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000667
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000668 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000669 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000670 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000671 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000672 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000673 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000674 "objc_msgSendSuper2_stret_fixup");
675 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000676
Chris Lattnera7c00b42009-04-22 02:15:23 +0000677 llvm::Constant *getObjCEndCatchFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000678 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000679 "objc_end_catch");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000680
Chris Lattnera7c00b42009-04-22 02:15:23 +0000681 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000682
Chris Lattnera7c00b42009-04-22 02:15:23 +0000683 llvm::Constant *getObjCBeginCatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000684 llvm::Type *params[] = { Int8PtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000685 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000686 params, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000687 "objc_begin_catch");
688 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +0000689
Chris Lattnera5f58b02011-07-09 17:41:47 +0000690 llvm::StructType *EHTypeTy;
691 llvm::Type *EHTypePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000692
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000693 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
694 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000695};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000696
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000697class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000698public:
699 // FIXME - accessibility
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000700 class GC_IVAR {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +0000701 public:
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000702 unsigned ivar_bytepos;
703 unsigned ivar_size;
704 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000705 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar22b0ada2009-04-23 01:29:05 +0000706
707 // Allow sorting based on byte pos.
708 bool operator<(const GC_IVAR &b) const {
709 return ivar_bytepos < b.ivar_bytepos;
710 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000711 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000712
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000713 class SKIP_SCAN {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000714 public:
715 unsigned skip;
716 unsigned scan;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000717 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000718 : skip(_skip), scan(_scan) {}
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000719 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000720
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000721protected:
722 CodeGen::CodeGenModule &CGM;
Owen Andersonae86c192009-07-13 04:10:07 +0000723 llvm::LLVMContext &VMContext;
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000724 // FIXME! May not be needing this after all.
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000725 unsigned ObjCABI;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000726
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000727 // gc ivar layout bitmap calculation helper caches.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000728 SmallVector<GC_IVAR, 16> SkipIvars;
729 SmallVector<GC_IVAR, 16> IvarsInfo;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000730
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000731 /// LazySymbols - Symbols to generate a lazy reference for. See
732 /// DefinedSymbols and FinishModule().
Daniel Dunbard027a922009-09-07 00:20:42 +0000733 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000734
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000735 /// DefinedSymbols - External symbols which are defined by this
736 /// module. The symbols in this list and LazySymbols are used to add
737 /// special linker symbols which ensure that Objective-C modules are
738 /// linked properly.
Daniel Dunbard027a922009-09-07 00:20:42 +0000739 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000740
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000741 /// ClassNames - uniqued class names.
Daniel Dunbarb036db82008-08-13 03:21:16 +0000742 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000743
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000744 /// MethodVarNames - uniqued method variable names.
745 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000746
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000747 /// DefinedCategoryNames - list of category names in form Class_Category.
748 llvm::SetVector<std::string> DefinedCategoryNames;
749
Daniel Dunbarb036db82008-08-13 03:21:16 +0000750 /// MethodVarTypes - uniqued method type signatures. We have to use
751 /// a StringMap here because have no other unique reference.
752 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000753
Daniel Dunbar3c76cb52008-08-26 21:51:14 +0000754 /// MethodDefinitions - map of methods which have been defined in
755 /// this translation unit.
756 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000757
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000758 /// PropertyNames - uniqued method variable names.
759 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000760
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000761 /// ClassReferences - uniqued class references.
762 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000763
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000764 /// SelectorReferences - uniqued selector references.
765 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000766
Daniel Dunbarb036db82008-08-13 03:21:16 +0000767 /// Protocols - Protocols for which an objc_protocol structure has
768 /// been emitted. Forward declarations are handled by creating an
769 /// empty structure whose initializer is filled in when/if defined.
770 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000771
Daniel Dunbarc475d422008-10-29 22:36:39 +0000772 /// DefinedProtocols - Protocols which have actually been
773 /// defined. We should not need this, see FIXME in GenerateProtocol.
774 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000775
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000776 /// DefinedClasses - List of defined classes.
Bill Wendling8392a472012-02-07 09:40:07 +0000777 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000778
779 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
Bill Wendling8392a472012-02-07 09:40:07 +0000780 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000781
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000782 /// DefinedCategories - List of defined categories.
Bill Wendling8392a472012-02-07 09:40:07 +0000783 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000784
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000785 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
Bill Wendling8392a472012-02-07 09:40:07 +0000786 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000787
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000788 /// GetNameForMethod - Return a name for the given method.
789 /// \param[out] NameOut - The return value.
790 void GetNameForMethod(const ObjCMethodDecl *OMD,
791 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000792 SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000793
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000794 /// GetMethodVarName - Return a unique constant for the given
795 /// selector's name. The return value has type char *.
796 llvm::Constant *GetMethodVarName(Selector Sel);
797 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000798
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000799 /// GetMethodVarType - Return a unique constant for the given
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000800 /// method's type encoding string. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000801
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000802 // FIXME: This is a horrible name.
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000803 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
804 bool Extended = false);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000805 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000806
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000807 /// GetPropertyName - Return a unique constant for the given
808 /// name. The return value has type char *.
809 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000810
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000811 // FIXME: This can be dropped once string functions are unified.
812 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
813 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000814
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000815 /// GetClassName - Return a unique constant for the given selector's
816 /// name. The return value has type char *.
817 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000818
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000819 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
820
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000821 /// BuildIvarLayout - Builds ivar layout bitmap for the class
822 /// implementation for the __strong or __weak case.
823 ///
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000824 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
825 bool ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +0000826
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +0000827 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000828
Daniel Dunbar15bd8882009-05-03 14:10:34 +0000829 void BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000830 unsigned int BytePos, bool ForStrongLayout,
831 bool &HasUnion);
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +0000832 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000833 const llvm::StructLayout *Layout,
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000834 const RecordDecl *RD,
Jordy Rosea91768e2011-07-22 02:08:32 +0000835 const SmallVectorImpl<const FieldDecl*> &RecFields,
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000836 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahaniana123b642009-04-24 16:17:09 +0000837 bool &HasUnion);
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000838
Fariborz Jahanian01dff422009-03-05 19:17:31 +0000839 /// GetIvarLayoutName - Returns a unique constant for the given
840 /// ivar layout bitmap.
841 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
842 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000843
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000844 /// EmitPropertyList - Emit the given property list. The return
845 /// value has type PropertyListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000846 llvm::Constant *EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000847 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000848 const ObjCContainerDecl *OCD,
849 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000850
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000851 /// EmitProtocolMethodTypes - Generate the array of extended method type
852 /// strings. The return value has type Int8PtrPtrTy.
853 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +0000854 ArrayRef<llvm::Constant*> MethodTypes,
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000855 const ObjCCommonTypesHelper &ObjCTypes);
856
Fariborz Jahanian751c1e72009-12-12 21:26:21 +0000857 /// PushProtocolProperties - Push protocol's property on the input stack.
Bill Wendlinga515b582012-02-09 22:16:49 +0000858 void PushProtocolProperties(
859 llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
860 llvm::SmallVectorImpl<llvm::Constant*> &Properties,
861 const Decl *Container,
862 const ObjCProtocolDecl *PROTO,
863 const ObjCCommonTypesHelper &ObjCTypes);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +0000864
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000865 /// GetProtocolRef - Return a reference to the internal protocol
866 /// description, creating an empty one if it has not been
867 /// defined. The return value has type ProtocolPtrTy.
868 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +0000869
Daniel Dunbar30c65362009-03-09 20:09:19 +0000870 /// CreateMetadataVar - Create a global variable with internal
871 /// linkage for use by the Objective-C runtime.
872 ///
873 /// This is a convenience wrapper which not only creates the
874 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +0000875 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +0000876 ///
877 /// \param Name - The variable name.
878 /// \param Init - The variable initializer; this is also used to
879 /// define the type of the variable.
880 /// \param Section - The section the variable should go into, or 0.
881 /// \param Align - The alignment for the variable, or 0.
882 /// \param AddToUsed - Whether the variable should be added to
Daniel Dunbar4527d302009-04-14 17:42:51 +0000883 /// "llvm.used".
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000884 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +0000885 llvm::Constant *Init,
886 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +0000887 unsigned Align,
888 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +0000889
John McCall9e8bb002011-05-14 03:10:52 +0000890 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
891 ReturnValueSlot Return,
892 QualType ResultType,
893 llvm::Value *Sel,
894 llvm::Value *Arg0,
895 QualType Arg0Ty,
896 bool IsSuper,
897 const CallArgList &CallArgs,
898 const ObjCMethodDecl *OMD,
899 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000900
Daniel Dunbar5e639272010-04-25 20:39:01 +0000901 /// EmitImageInfo - Emit the image info marker used to encode some module
902 /// level information.
903 void EmitImageInfo();
904
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000905public:
Owen Andersonae86c192009-07-13 04:10:07 +0000906 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
Mike Stump11289f42009-09-09 15:08:12 +0000907 CGM(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000908
David Chisnall481e3a82010-01-23 02:40:42 +0000909 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000910
Fariborz Jahanian99113fd2009-01-26 21:38:32 +0000911 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
912 const ObjCContainerDecl *CD=0);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000913
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000914 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000915
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000916 /// GetOrEmitProtocol - Get the protocol object for the given
917 /// declaration, emitting it if necessary. The return value has type
918 /// ProtocolPtrTy.
919 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000920
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000921 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
922 /// object for the given declaration, emitting it if needed. These
923 /// forward references will be filled in with empty bodies if no
924 /// definition is seen. The return value has type ProtocolPtrTy.
925 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCall351762c2011-02-07 10:33:21 +0000926 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
927 const CGBlockInfo &blockInfo);
Fariborz Jahanianc05349e2010-08-04 16:57:49 +0000928
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000929};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000930
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000931class CGObjCMac : public CGObjCCommonMac {
932private:
933 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +0000934
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000935 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000936 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000937 void EmitModuleInfo();
938
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000939 /// EmitModuleSymols - Emit module symbols, the list of defined
940 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000941 llvm::Constant *EmitModuleSymbols();
942
Daniel Dunbar3ad53482008-08-11 21:35:06 +0000943 /// FinishModule - Write out global data structures at the end of
944 /// processing a translation unit.
945 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +0000946
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000947 /// EmitClassExtension - Generate the class extension structure used
948 /// to store the weak ivar layout and properties. The return value
949 /// has type ClassExtensionPtrTy.
950 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
951
952 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
953 /// for the given class.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000954 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000955 const ObjCInterfaceDecl *ID);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +0000956
John McCall31168b02011-06-15 23:02:42 +0000957 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
958 IdentifierInfo *II);
959
960 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
961
Fariborz Jahanianeb80c982009-11-12 20:14:24 +0000962 /// EmitSuperClassRef - Emits reference to class's main metadata class.
963 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000964
965 /// EmitIvarList - Emit the ivar list for the given
966 /// implementation. If ForClass is true the list of class ivars
967 /// (i.e. metaclass ivars) is emitted, otherwise the list of
968 /// interface ivars will be emitted. The return value has type
969 /// IvarListPtrTy.
970 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +0000971 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000972
Daniel Dunbarca8531a2008-08-25 08:19:24 +0000973 /// EmitMetaClass - Emit a forward reference to the class structure
974 /// for the metaclass of the given interface. The return value has
975 /// type ClassPtrTy.
976 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
977
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000978 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +0000979 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000980 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
981 llvm::Constant *Protocols,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +0000982 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000983
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000984 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000985
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000986 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000987
988 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +0000989 /// implementation. The return value has type MethodListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000990 llvm::Constant *EmitMethodList(Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000991 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +0000992 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000993
994 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000995 /// method declarations.
Daniel Dunbarb036db82008-08-13 03:21:16 +0000996 /// - TypeName: The name for the type containing the methods.
997 /// - IsProtocol: True iff these methods are for a protocol.
998 /// - ClassMethds: True iff these are class methods.
999 /// - Required: When true, only "required" methods are
1000 /// listed. Similarly, when false only "optional" methods are
1001 /// listed. For classes this should always be true.
1002 /// - begin, end: The method list to output.
1003 ///
1004 /// The return value has type MethodDescriptionListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001005 llvm::Constant *EmitMethodDescList(Twine Name,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001006 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001007 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001008
Daniel Dunbarc475d422008-10-29 22:36:39 +00001009 /// GetOrEmitProtocol - Get the protocol object for the given
1010 /// declaration, emitting it if necessary. The return value has type
1011 /// ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001012 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001013
1014 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1015 /// object for the given declaration, emitting it if needed. These
1016 /// forward references will be filled in with empty bodies if no
1017 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001018 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001019
Daniel Dunbarb036db82008-08-13 03:21:16 +00001020 /// EmitProtocolExtension - Generate the protocol extension
1021 /// structure used to store optional instance and class methods, and
1022 /// protocol properties. The return value has type
1023 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001024 llvm::Constant *
1025 EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001026 ArrayRef<llvm::Constant*> OptInstanceMethods,
1027 ArrayRef<llvm::Constant*> OptClassMethods,
1028 ArrayRef<llvm::Constant*> MethodTypesExt);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001029
1030 /// EmitProtocolList - Generate the list of referenced
1031 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001032 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001033 ObjCProtocolDecl::protocol_iterator begin,
1034 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001035
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001036 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1037 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001038 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1039 bool lval=false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001040
1041public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001042 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001043
Fariborz Jahanian71394042009-01-23 23:53:38 +00001044 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001045
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001046 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001047 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001048 QualType ResultType,
1049 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001050 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001051 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001052 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001053 const ObjCMethodDecl *Method);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001054
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001055 virtual CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001056 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001057 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001058 QualType ResultType,
1059 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001060 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001061 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001062 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001063 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001064 const CallArgList &CallArgs,
1065 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001066
Daniel Dunbarcb463852008-11-01 01:53:16 +00001067 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001068 const ObjCInterfaceDecl *ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001069
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001070 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1071 bool lval = false);
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001072
1073 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1074 /// untyped one.
1075 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1076 const ObjCMethodDecl *Method);
1077
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001078 virtual llvm::Constant *GetEHType(QualType T);
John McCall2ca705e2010-07-24 00:37:23 +00001079
Daniel Dunbar92992502008-08-15 22:20:32 +00001080 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001081
Daniel Dunbar92992502008-08-15 22:20:32 +00001082 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001083
David Chisnall92d436b2012-01-31 18:59:20 +00001084 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {};
1085
Daniel Dunbarcb463852008-11-01 01:53:16 +00001086 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00001087 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001088
Chris Lattnerd4808922009-03-22 21:03:39 +00001089 virtual llvm::Constant *GetPropertyGetFunction();
1090 virtual llvm::Constant *GetPropertySetFunction();
David Chisnall168b80f2010-12-26 22:13:16 +00001091 virtual llvm::Constant *GetGetStructFunction();
1092 virtual llvm::Constant *GetSetStructFunction();
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001093 virtual llvm::Constant *GetCppAtomicObjectFunction();
Chris Lattnerd4808922009-03-22 21:03:39 +00001094 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001095
John McCallbd309292010-07-06 01:34:17 +00001096 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1097 const ObjCAtTryStmt &S);
1098 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1099 const ObjCAtSynchronizedStmt &S);
1100 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00001101 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1102 const ObjCAtThrowStmt &S);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001103 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001104 llvm::Value *AddrWeakObj);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001105 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001106 llvm::Value *src, llvm::Value *dst);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001107 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001108 llvm::Value *src, llvm::Value *dest,
1109 bool threadlocal = false);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00001110 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001111 llvm::Value *src, llvm::Value *dest,
1112 llvm::Value *ivarOffset);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001113 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1114 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001115 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1116 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001117 llvm::Value *size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001118
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001119 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1120 QualType ObjectTy,
1121 llvm::Value *BaseValue,
1122 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001123 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001124 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001125 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001126 const ObjCIvarDecl *Ivar);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001127
1128 /// GetClassGlobal - Return the global variable for the Objective-C
1129 /// class of the given name.
1130 virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) {
David Blaikie83d382b2011-09-23 05:06:16 +00001131 llvm_unreachable("CGObjCMac::GetClassGlobal");
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001132 }
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001133};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001134
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001135class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001136private:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001137 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001138 llvm::GlobalVariable* ObjCEmptyCacheVar;
1139 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001140
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001141 /// SuperClassReferences - uniqued super class references.
1142 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001143
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001144 /// MetaClassReferences - uniqued meta class references.
1145 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001146
1147 /// EHTypeReferences - uniqued class ehtype references.
1148 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001149
John McCall9e8bb002011-05-14 03:10:52 +00001150 /// VTableDispatchMethods - List of methods for which we generate
1151 /// vtable-based message dispatch.
1152 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001153
Fariborz Jahanian67260552009-11-17 21:37:35 +00001154 /// DefinedMetaClasses - List of defined meta-classes.
1155 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1156
John McCall9e8bb002011-05-14 03:10:52 +00001157 /// isVTableDispatchedSelector - Returns true if SEL is a
1158 /// vtable-based selector.
1159 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001160
Fariborz Jahanian71394042009-01-23 23:53:38 +00001161 /// FinishNonFragileABIModule - Write out global data structures at the end of
1162 /// processing a translation unit.
1163 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001164
Daniel Dunbar19573e72009-05-15 21:48:48 +00001165 /// AddModuleClassList - Add the given list of class pointers to the
1166 /// module with the provided symbol and section names.
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001167 void AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
Daniel Dunbar19573e72009-05-15 21:48:48 +00001168 const char *SymbolName,
1169 const char *SectionName);
1170
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001171 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1172 unsigned InstanceStart,
1173 unsigned InstanceSize,
1174 const ObjCImplementationDecl *ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001175 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001176 llvm::Constant *IsAGV,
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001177 llvm::Constant *SuperClassGV,
Fariborz Jahanian82208252009-01-31 00:59:10 +00001178 llvm::Constant *ClassRoGV,
1179 bool HiddenVisibility);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001180
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001181 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001182
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00001183 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001184
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001185 /// EmitMethodList - Emit the method list for the given
1186 /// implementation. The return value has type MethodListnfABITy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001187 llvm::Constant *EmitMethodList(Twine Name,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001188 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001189 ArrayRef<llvm::Constant*> Methods);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001190 /// EmitIvarList - Emit the ivar list for the given
1191 /// implementation. If ForClass is true the list of class ivars
1192 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1193 /// interface ivars will be emitted. The return value has type
1194 /// IvarListnfABIPtrTy.
1195 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001196
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001197 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001198 const ObjCIvarDecl *Ivar,
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00001199 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001200
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001201 /// GetOrEmitProtocol - Get the protocol object for the given
1202 /// declaration, emitting it if necessary. The return value has type
1203 /// ProtocolPtrTy.
1204 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001205
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001206 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1207 /// object for the given declaration, emitting it if needed. These
1208 /// forward references will be filled in with empty bodies if no
1209 /// definition is seen. The return value has type ProtocolPtrTy.
1210 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001211
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001212 /// EmitProtocolList - Generate the list of referenced
1213 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001214 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001215 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001216 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001217
John McCall9e8bb002011-05-14 03:10:52 +00001218 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1219 ReturnValueSlot Return,
1220 QualType ResultType,
1221 Selector Sel,
1222 llvm::Value *Receiver,
1223 QualType Arg0Ty,
1224 bool IsSuper,
1225 const CallArgList &CallArgs,
1226 const ObjCMethodDecl *Method);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001227
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001228 /// GetClassGlobal - Return the global variable for the Objective-C
1229 /// class of the given name.
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00001230 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001231
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001232 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001233 /// for the given class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001234 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001235 const ObjCInterfaceDecl *ID);
John McCall31168b02011-06-15 23:02:42 +00001236
1237 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
1238 IdentifierInfo *II);
1239
1240 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001241
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001242 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1243 /// for the given super class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001244 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1245 const ObjCInterfaceDecl *ID);
1246
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001247 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1248 /// meta-data
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001249 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001250 const ObjCInterfaceDecl *ID);
1251
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001252 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1253 /// the given ivar.
1254 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001255 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001256 const ObjCInterfaceDecl *ID,
1257 const ObjCIvarDecl *Ivar);
1258
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001259 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1260 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001261 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1262 bool lval=false);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001263
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001264 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001265 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001266 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001267 bool ForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001268
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001269 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar15894b72009-04-07 05:48:37 +00001270 return "OBJC_METACLASS_$_";
1271 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001272
Daniel Dunbar15894b72009-04-07 05:48:37 +00001273 const char *getClassSymbolPrefix() const {
1274 return "OBJC_CLASS_$_";
1275 }
1276
Daniel Dunbar961202372009-05-03 12:57:56 +00001277 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001278 uint32_t &InstanceStart,
1279 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001280
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001281 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001282 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001283 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1284 return CGM.getContext().Selectors.getSelector(0, &II);
1285 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001286
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001287 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001288 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1289 return CGM.getContext().Selectors.getSelector(1, &II);
1290 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001291
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001292 /// ImplementationIsNonLazy - Check whether the given category or
1293 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001294 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001295
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001296public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001297 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001298 // FIXME. All stubs for now!
1299 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001300
Fariborz Jahanian71394042009-01-23 23:53:38 +00001301 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001302 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001303 QualType ResultType,
1304 Selector Sel,
1305 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001306 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001307 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001308 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001309
1310 virtual CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001311 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001312 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001313 QualType ResultType,
1314 Selector Sel,
1315 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001316 bool isCategoryImpl,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001317 llvm::Value *Receiver,
1318 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001319 const CallArgList &CallArgs,
1320 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001321
Fariborz Jahanian71394042009-01-23 23:53:38 +00001322 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001323 const ObjCInterfaceDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001324
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001325 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1326 bool lvalue = false)
1327 { return EmitSelector(Builder, Sel, lvalue); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001328
1329 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1330 /// untyped one.
1331 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1332 const ObjCMethodDecl *Method)
1333 { return EmitSelector(Builder, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001334
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00001335 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001336
Fariborz Jahanian71394042009-01-23 23:53:38 +00001337 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
David Chisnall92d436b2012-01-31 18:59:20 +00001338
1339 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {};
1340
Fariborz Jahanian71394042009-01-23 23:53:38 +00001341 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian097feda2009-01-30 18:58:59 +00001342 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001343
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001344 virtual llvm::Constant *GetEHType(QualType T);
John McCall2ca705e2010-07-24 00:37:23 +00001345
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001346 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001347 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001348 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001349 virtual llvm::Constant *GetPropertySetFunction() {
1350 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001351 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001352
David Chisnall168b80f2010-12-26 22:13:16 +00001353 virtual llvm::Constant *GetSetStructFunction() {
1354 return ObjCTypes.getCopyStructFn();
1355 }
1356 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001357 return ObjCTypes.getCopyStructFn();
1358 }
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001359 virtual llvm::Constant *GetCppAtomicObjectFunction() {
1360 return ObjCTypes.getCppAtomicObjectFunction();
1361 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001362
Chris Lattnerd4808922009-03-22 21:03:39 +00001363 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001364 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001365 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001366
John McCallbd309292010-07-06 01:34:17 +00001367 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1368 const ObjCAtTryStmt &S);
1369 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1370 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001371 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlsson9ab53d12009-02-16 22:59:18 +00001372 const ObjCAtThrowStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001373 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001374 llvm::Value *AddrWeakObj);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001375 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001376 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001377 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001378 llvm::Value *src, llvm::Value *dest,
1379 bool threadlocal = false);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001380 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001381 llvm::Value *src, llvm::Value *dest,
1382 llvm::Value *ivarOffset);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001383 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001384 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001385 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1386 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001387 llvm::Value *size);
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001388 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1389 QualType ObjectTy,
1390 llvm::Value *BaseValue,
1391 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001392 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001393 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001394 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001395 const ObjCIvarDecl *Ivar);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001396};
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001397
1398/// A helper class for performing the null-initialization of a return
1399/// value.
1400struct NullReturnState {
1401 llvm::BasicBlock *NullBB;
1402 llvm::BasicBlock *callBB;
1403 NullReturnState() : NullBB(0), callBB(0) {}
1404
1405 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
1406 // Make blocks for the null-init and call edges.
1407 NullBB = CGF.createBasicBlock("msgSend.nullinit");
1408 callBB = CGF.createBasicBlock("msgSend.call");
1409
1410 // Check for a null receiver and, if there is one, jump to the
1411 // null-init test.
1412 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1413 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1414
1415 // Otherwise, start performing the call.
1416 CGF.EmitBlock(callBB);
1417 }
1418
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001419 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
1420 const CallArgList &CallArgs,
1421 const ObjCMethodDecl *Method) {
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001422 if (!NullBB) return result;
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001423
1424 llvm::Value *NullInitPtr = 0;
1425 if (result.isScalar() && !resultType->isVoidType()) {
1426 NullInitPtr = CGF.CreateTempAlloca(result.getScalarVal()->getType());
1427 CGF.Builder.CreateStore(result.getScalarVal(), NullInitPtr);
1428 }
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001429
1430 // Finish the call path.
1431 llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont");
1432 if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB);
1433
1434 // Emit the null-init block and perform the null-initialization there.
1435 CGF.EmitBlock(NullBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001436
1437 // Release consumed arguments along the null-receiver path.
1438 if (Method) {
1439 CallArgList::const_iterator I = CallArgs.begin();
1440 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1441 e = Method->param_end(); i != e; ++i, ++I) {
1442 const ParmVarDecl *ParamDecl = (*i);
1443 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1444 RValue RV = I->RV;
1445 assert(RV.isScalar() &&
1446 "NullReturnState::complete - arg not on object");
1447 CGF.EmitARCRelease(RV.getScalarVal(), true);
1448 }
1449 }
1450 }
1451
1452 if (result.isScalar()) {
1453 if (NullInitPtr)
1454 CGF.EmitNullInitialization(NullInitPtr, resultType);
1455 // Jump to the continuation block.
1456 CGF.EmitBlock(contBB);
1457 return NullInitPtr ? RValue::get(CGF.Builder.CreateLoad(NullInitPtr))
1458 : result;
1459 }
1460
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001461 if (!resultType->isAnyComplexType()) {
1462 assert(result.isAggregate() && "null init of non-aggregate result?");
1463 CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
1464 // Jump to the continuation block.
1465 CGF.EmitBlock(contBB);
1466 return result;
1467 }
1468
1469 // _Complex type
1470 // FIXME. Now easy to handle any other scalar type whose result is returned
1471 // in memory due to ABI limitations.
1472 CGF.EmitBlock(contBB);
1473 CodeGenFunction::ComplexPairTy CallCV = result.getComplexVal();
1474 llvm::Type *MemberType = CallCV.first->getType();
1475 llvm::Constant *ZeroCV = llvm::Constant::getNullValue(MemberType);
1476 // Create phi instruction for scalar complex value.
1477 llvm::PHINode *PHIReal = CGF.Builder.CreatePHI(MemberType, 2);
1478 PHIReal->addIncoming(ZeroCV, NullBB);
1479 PHIReal->addIncoming(CallCV.first, callBB);
1480 llvm::PHINode *PHIImag = CGF.Builder.CreatePHI(MemberType, 2);
1481 PHIImag->addIncoming(ZeroCV, NullBB);
1482 PHIImag->addIncoming(CallCV.second, callBB);
1483 return RValue::getComplex(PHIReal, PHIImag);
1484 }
1485};
1486
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001487} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001488
1489/* *** Helper Functions *** */
1490
1491/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001492static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001493 llvm::Constant *C,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001494 unsigned idx0,
1495 unsigned idx1) {
1496 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001497 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1498 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001499 };
Jay Foaded8db7d2011-07-21 14:31:17 +00001500 return llvm::ConstantExpr::getGetElementPtr(C, Idxs);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001501}
1502
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001503/// hasObjCExceptionAttribute - Return true if this class or any super
1504/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001505static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001506 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001507 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001508 return true;
1509 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001510 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001511 return false;
1512}
1513
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001514/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001515
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001516CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001517 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001518 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001519 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001520}
1521
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001522/// GetClass - Return a reference to the class for the given interface
1523/// decl.
Daniel Dunbarcb463852008-11-01 01:53:16 +00001524llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001525 const ObjCInterfaceDecl *ID) {
1526 return EmitClassRef(Builder, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001527}
1528
1529/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001530llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1531 bool lval) {
1532 return EmitSelector(Builder, Sel, lval);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001533}
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001534llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001535 *Method) {
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001536 return EmitSelector(Builder, Method->getSelector());
1537}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001538
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001539llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001540 if (T->isObjCIdType() ||
1541 T->isObjCQualifiedIdType()) {
1542 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001543 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001544 }
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001545 if (T->isObjCClassType() ||
1546 T->isObjCQualifiedClassType()) {
1547 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001548 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001549 }
1550 if (T->isObjCObjectPointerType())
1551 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
1552
John McCall2ca705e2010-07-24 00:37:23 +00001553 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall2ca705e2010-07-24 00:37:23 +00001554}
1555
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001556/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001557/*
1558 struct __builtin_CFString {
1559 const int *isa; // point to __CFConstantStringClassReference
1560 int flags;
1561 const char *str;
1562 long length;
1563 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001564*/
1565
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001566/// or Generate a constant NSString object.
1567/*
1568 struct __builtin_NSString {
1569 const int *isa; // point to __NSConstantStringClassReference
1570 const char *str;
1571 unsigned int length;
1572 };
1573*/
1574
Fariborz Jahanian71394042009-01-23 23:53:38 +00001575llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall481e3a82010-01-23 02:40:42 +00001576 const StringLiteral *SL) {
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001577 return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
1578 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian50c925f2010-10-19 17:19:29 +00001579 CGM.GetAddrOfConstantString(SL));
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001580}
1581
1582/// Generates a message send where the super is the receiver. This is
1583/// a message send to self with special delivery semantics indicating
1584/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001585CodeGen::RValue
1586CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001587 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001588 QualType ResultType,
1589 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001590 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001591 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001592 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001593 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001594 const CodeGen::CallArgList &CallArgs,
1595 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001596 // Create and init a super structure; this is a (receiver, class)
1597 // pair we will pass to objc_msgSendSuper.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001598 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00001599 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001600 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001601 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001602 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001603 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001604
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001605 // If this is a class message the metaclass is passed as the target.
1606 llvm::Value *Target;
1607 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001608 if (isCategoryImpl) {
1609 // Message sent to 'super' in a class method defined in a category
1610 // implementation requires an odd treatment.
1611 // If we are in a class method, we must retrieve the
1612 // _metaclass_ for the current class, pointed at by
1613 // the class's "isa" pointer. The following assumes that
1614 // isa" is the first ivar in a class (which it must be).
1615 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1616 Target = CGF.Builder.CreateStructGEP(Target, 0);
1617 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00001618 } else {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001619 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1620 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1621 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1622 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001623 }
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00001624 }
1625 else if (isCategoryImpl)
1626 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1627 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001628 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1629 ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1630 Target = CGF.Builder.CreateLoad(ClassPtr);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001631 }
Mike Stump18bb9282009-05-16 07:57:57 +00001632 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1633 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00001634 llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00001635 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00001636 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001637 CGF.Builder.CreateStore(Target,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001638 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall9e8bb002011-05-14 03:10:52 +00001639 return EmitMessageSend(CGF, Return, ResultType,
1640 EmitSelector(CGF.Builder, Sel),
1641 ObjCSuper, ObjCTypes.SuperPtrCTy,
1642 true, CallArgs, Method, ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001643}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001644
1645/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001646CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001647 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001648 QualType ResultType,
1649 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001650 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001651 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001652 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001653 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00001654 return EmitMessageSend(CGF, Return, ResultType,
1655 EmitSelector(CGF.Builder, Sel),
1656 Receiver, CGF.getContext().getObjCIdType(),
1657 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00001658}
1659
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001660CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00001661CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1662 ReturnValueSlot Return,
1663 QualType ResultType,
1664 llvm::Value *Sel,
1665 llvm::Value *Arg0,
1666 QualType Arg0Ty,
1667 bool IsSuper,
1668 const CallArgList &CallArgs,
1669 const ObjCMethodDecl *Method,
1670 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc722b852008-08-30 03:02:31 +00001671 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00001672 if (!IsSuper)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00001673 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman43dca6a2011-05-02 17:57:46 +00001674 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1675 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCall31168b02011-06-15 23:02:42 +00001676 ActualArgs.addFrom(CallArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001677
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00001678 CodeGenTypes &Types = CGM.getTypes();
John McCallab26cfa2010-02-05 21:31:56 +00001679 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindolac50c27c2010-03-30 20:24:48 +00001680 FunctionType::ExtInfo());
Chris Lattner2192fe52011-07-18 04:24:23 +00001681 llvm::FunctionType *FTy =
Daniel Dunbardf0e62d2009-09-17 04:01:40 +00001682 Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001683
Anders Carlsson280e61f12010-06-21 20:59:55 +00001684 if (Method)
1685 assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
1686 CGM.getContext().getCanonicalType(ResultType) &&
1687 "Result type mismatch!");
1688
John McCall5880fb82011-05-14 21:12:11 +00001689 NullReturnState nullReturn;
1690
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001691 llvm::Constant *Fn = NULL;
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001692 if (CGM.ReturnTypeUsesSRet(FnInfo)) {
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001693 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001694 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001695 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001696 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1697 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1698 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +00001699 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
1700 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
1701 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001702 } else {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001703 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001704 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001705 }
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001706
1707 bool requiresnullCheck = false;
1708 if (CGM.getLangOptions().ObjCAutoRefCount && Method)
1709 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1710 e = Method->param_end(); i != e; ++i) {
1711 const ParmVarDecl *ParamDecl = (*i);
1712 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1713 if (!nullReturn.NullBB)
1714 nullReturn.init(CGF, Arg0);
1715 requiresnullCheck = true;
1716 break;
1717 }
1718 }
1719
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001720 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
John McCall5880fb82011-05-14 21:12:11 +00001721 RValue rvalue = CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001722 return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
1723 requiresnullCheck ? Method : 0);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001724}
1725
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001726static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1727 if (FQT.isObjCGCStrong())
1728 return Qualifiers::Strong;
1729
John McCall31168b02011-06-15 23:02:42 +00001730 if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001731 return Qualifiers::Weak;
1732
1733 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1734 return Qualifiers::Strong;
1735
1736 if (const PointerType *PT = FQT->getAs<PointerType>())
1737 return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1738
1739 return Qualifiers::GCNone;
1740}
1741
John McCall351762c2011-02-07 10:33:21 +00001742llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1743 const CGBlockInfo &blockInfo) {
Chris Lattnerece04092012-02-07 00:39:47 +00001744 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
John McCall351762c2011-02-07 10:33:21 +00001745
Douglas Gregor79a91412011-09-13 17:21:33 +00001746 if (CGM.getLangOptions().getGC() == LangOptions::NonGC &&
John McCall31168b02011-06-15 23:02:42 +00001747 !CGM.getLangOptions().ObjCAutoRefCount)
John McCall351762c2011-02-07 10:33:21 +00001748 return nullPtr;
1749
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001750 bool hasUnion = false;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001751 SkipIvars.clear();
1752 IvarsInfo.clear();
Douglas Gregore8bbc122011-09-02 00:18:52 +00001753 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
1754 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001755
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00001756 // __isa is the first field in block descriptor and must assume by runtime's
1757 // convention that it is GC'able.
1758 IvarsInfo.push_back(GC_IVAR(0, 1));
John McCall351762c2011-02-07 10:33:21 +00001759
1760 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1761
1762 // Calculate the basic layout of the block structure.
1763 const llvm::StructLayout *layout =
1764 CGM.getTargetData().getStructLayout(blockInfo.StructureType);
1765
1766 // Ignore the optional 'this' capture: C++ objects are not assumed
1767 // to be GC'ed.
1768
1769 // Walk the captured variables.
1770 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1771 ce = blockDecl->capture_end(); ci != ce; ++ci) {
1772 const VarDecl *variable = ci->getVariable();
1773 QualType type = variable->getType();
1774
1775 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1776
1777 // Ignore constant captures.
1778 if (capture.isConstant()) continue;
1779
1780 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
1781
1782 // __block variables are passed by their descriptor address.
1783 if (ci->isByRef()) {
1784 IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00001785 continue;
John McCall351762c2011-02-07 10:33:21 +00001786 }
1787
1788 assert(!type->isArrayType() && "array variable should not be caught");
1789 if (const RecordType *record = type->getAs<RecordType>()) {
1790 BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00001791 continue;
1792 }
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001793
John McCall351762c2011-02-07 10:33:21 +00001794 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
1795 unsigned fieldSize = CGM.getContext().getTypeSize(type);
1796
1797 if (GCAttr == Qualifiers::Strong)
1798 IvarsInfo.push_back(GC_IVAR(fieldOffset,
1799 fieldSize / WordSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001800 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
John McCall351762c2011-02-07 10:33:21 +00001801 SkipIvars.push_back(GC_IVAR(fieldOffset,
1802 fieldSize / ByteSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001803 }
1804
1805 if (IvarsInfo.empty())
John McCall351762c2011-02-07 10:33:21 +00001806 return nullPtr;
1807
1808 // Sort on byte position; captures might not be allocated in order,
1809 // and unions can do funny things.
1810 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
1811 llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001812
1813 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00001814 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001815 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
1816 printf("\n block variable layout for block: ");
1817 const unsigned char *s = (unsigned char*)BitMap.c_str();
Bill Wendling53136852012-02-07 09:06:01 +00001818 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001819 if (!(s[i] & 0xf0))
1820 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
1821 else
1822 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
1823 printf("\n");
1824 }
1825
1826 return C;
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00001827}
1828
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001829llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00001830 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00001831 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00001832 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00001833 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1834
Owen Andersonade90fd2009-07-29 18:54:39 +00001835 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00001836 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001837}
1838
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001839void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00001840 // FIXME: We shouldn't need this, the protocol decl should contain enough
1841 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00001842 DefinedProtocols.insert(PD->getIdentifier());
1843
1844 // If we have generated a forward reference to this protocol, emit
1845 // it now. Otherwise do nothing, the protocol objects are lazily
1846 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001847 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00001848 GetOrEmitProtocol(PD);
1849}
1850
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001851llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001852 if (DefinedProtocols.count(PD->getIdentifier()))
1853 return GetOrEmitProtocol(PD);
Douglas Gregora9d84932011-05-27 01:19:52 +00001854
Daniel Dunbarc475d422008-10-29 22:36:39 +00001855 return GetOrEmitProtocolRef(PD);
1856}
1857
Daniel Dunbarb036db82008-08-13 03:21:16 +00001858/*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001859// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1860struct _objc_protocol {
1861struct _objc_protocol_extension *isa;
1862char *protocol_name;
1863struct _objc_protocol_list *protocol_list;
1864struct _objc__method_prototype_list *instance_methods;
1865struct _objc__method_prototype_list *class_methods
1866};
Daniel Dunbarb036db82008-08-13 03:21:16 +00001867
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001868See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00001869*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00001870llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1871 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1872
1873 // Early exit if a defining object has already been generated.
1874 if (Entry && Entry->hasInitializer())
1875 return Entry;
1876
Douglas Gregora715bff2012-01-01 19:51:50 +00001877 // Use the protocol definition, if there is one.
1878 if (const ObjCProtocolDecl *Def = PD->getDefinition())
1879 PD = Def;
1880
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00001881 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00001882 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00001883 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1884
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001885 // Construct method lists.
1886 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1887 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001888 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001889 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00001890 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001891 ObjCMethodDecl *MD = *i;
1892 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00001893 if (!C)
1894 return GetOrEmitProtocolRef(PD);
1895
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001896 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1897 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001898 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001899 } else {
1900 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001901 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001902 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001903 }
1904
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001905 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00001906 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001907 ObjCMethodDecl *MD = *i;
1908 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00001909 if (!C)
1910 return GetOrEmitProtocolRef(PD);
1911
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001912 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1913 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001914 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001915 } else {
1916 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001917 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001918 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001919 }
1920
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001921 MethodTypesExt.insert(MethodTypesExt.end(),
1922 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
1923
Benjamin Kramer22d24c22011-10-15 12:20:02 +00001924 llvm::Constant *Values[] = {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001925 EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods,
1926 MethodTypesExt),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00001927 GetClassName(PD->getIdentifier()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001928 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardec75f82008-08-21 21:57:41 +00001929 PD->protocol_begin(),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00001930 PD->protocol_end()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001931 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001932 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00001933 InstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001934 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001935 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00001936 ClassMethods)
1937 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00001938 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001939 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001940
Daniel Dunbarb036db82008-08-13 03:21:16 +00001941 if (Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001942 // Already created, fix the linkage and update the initializer.
1943 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001944 Entry->setInitializer(Init);
1945 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001946 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00001947 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001948 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001949 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001950 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00001951 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00001952 // FIXME: Is this necessary? Why only for protocol?
1953 Entry->setAlignment(4);
1954 }
Chris Lattnerf56501c2009-07-17 23:57:13 +00001955 CGM.AddUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001956
1957 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00001958}
1959
Daniel Dunbarc475d422008-10-29 22:36:39 +00001960llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00001961 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1962
1963 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001964 // We use the initializer as a marker of whether this is a forward
1965 // reference or not. At module finalization we add the empty
1966 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001967 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00001968 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarc475d422008-10-29 22:36:39 +00001969 llvm::GlobalValue::ExternalLinkage,
1970 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001971 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00001972 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00001973 // FIXME: Is this necessary? Why only for protocol?
1974 Entry->setAlignment(4);
1975 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001976
Daniel Dunbarb036db82008-08-13 03:21:16 +00001977 return Entry;
1978}
1979
1980/*
1981 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001982 uint32_t size;
1983 struct objc_method_description_list *optional_instance_methods;
1984 struct objc_method_description_list *optional_class_methods;
1985 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00001986 const char ** extendedMethodTypes;
Daniel Dunbarb036db82008-08-13 03:21:16 +00001987 };
1988*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001989llvm::Constant *
1990CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001991 ArrayRef<llvm::Constant*> OptInstanceMethods,
1992 ArrayRef<llvm::Constant*> OptClassMethods,
1993 ArrayRef<llvm::Constant*> MethodTypesExt) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001994 uint64_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00001995 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Benjamin Kramer22d24c22011-10-15 12:20:02 +00001996 llvm::Constant *Values[] = {
1997 llvm::ConstantInt::get(ObjCTypes.IntTy, Size),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001998 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001999 + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002000 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002001 OptInstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002002 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002003 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002004 OptClassMethods),
2005 EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002006 ObjCTypes),
2007 EmitProtocolMethodTypes("\01L_OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
2008 MethodTypesExt, ObjCTypes)
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002009 };
Daniel Dunbarb036db82008-08-13 03:21:16 +00002010
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002011 // Return null if no extension bits are used.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002012 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002013 Values[3]->isNullValue() && Values[4]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002014 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002015
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002016 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002017 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002018
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002019 // No special section, but goes in llvm.used
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002020 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002021 Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002022 0, 0, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002023}
2024
2025/*
2026 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002027 struct objc_protocol_list *next;
2028 long count;
2029 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002030 };
2031*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00002032llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002033CGObjCMac::EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00002034 ObjCProtocolDecl::protocol_iterator begin,
2035 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendlinga515b582012-02-09 22:16:49 +00002036 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002037
Daniel Dunbardec75f82008-08-21 21:57:41 +00002038 for (; begin != end; ++begin)
2039 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002040
2041 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002042 if (ProtocolRefs.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002043 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002044
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002045 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00002046 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002047
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002048 llvm::Constant *Values[3];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002049 // This field is only used by the runtime.
Owen Anderson0b75f232009-07-31 20:28:54 +00002050 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002051 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002052 ProtocolRefs.size() - 1);
2053 Values[2] =
2054 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
2055 ProtocolRefs.size()),
Daniel Dunbarb036db82008-08-13 03:21:16 +00002056 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002057
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002058 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002059 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002060 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002061 4, false);
Owen Andersonade90fd2009-07-29 18:54:39 +00002062 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002063}
2064
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002065void CGObjCCommonMac::
2066PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
Bill Wendlinga515b582012-02-09 22:16:49 +00002067 llvm::SmallVectorImpl<llvm::Constant*> &Properties,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002068 const Decl *Container,
2069 const ObjCProtocolDecl *PROTO,
2070 const ObjCCommonTypesHelper &ObjCTypes) {
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002071 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
2072 E = PROTO->protocol_end(); P != E; ++P)
2073 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
2074 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
2075 E = PROTO->prop_end(); I != E; ++I) {
2076 const ObjCPropertyDecl *PD = *I;
2077 if (!PropertySet.insert(PD->getIdentifier()))
2078 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002079 llvm::Constant *Prop[] = {
2080 GetPropertyName(PD->getIdentifier()),
2081 GetPropertyTypeString(PD, Container)
2082 };
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002083 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
2084 }
2085}
2086
Daniel Dunbarb036db82008-08-13 03:21:16 +00002087/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002088 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00002089 const char * const name;
2090 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002091 };
2092
2093 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002094 uint32_t entsize; // sizeof (struct _objc_property)
2095 uint32_t prop_count;
2096 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002097 };
2098*/
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002099llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002100 const Decl *Container,
2101 const ObjCContainerDecl *OCD,
2102 const ObjCCommonTypesHelper &ObjCTypes) {
Bill Wendlinga515b582012-02-09 22:16:49 +00002103 llvm::SmallVector<llvm::Constant*, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002104 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002105 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
2106 E = OCD->prop_end(); I != E; ++I) {
Steve Naroffba3dc382009-01-11 12:47:58 +00002107 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002108 PropertySet.insert(PD->getIdentifier());
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002109 llvm::Constant *Prop[] = {
2110 GetPropertyName(PD->getIdentifier()),
2111 GetPropertyTypeString(PD, Container)
2112 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002113 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002114 Prop));
2115 }
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002116 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek0ef508d2010-09-01 01:21:15 +00002117 for (ObjCInterfaceDecl::all_protocol_iterator
2118 P = OID->all_referenced_protocol_begin(),
2119 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002120 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2121 ObjCTypes);
2122 }
2123 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
2124 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
2125 E = CD->protocol_end(); P != E; ++P)
2126 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2127 ObjCTypes);
2128 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002129
2130 // Return null for empty list.
2131 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002132 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002133
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002134 unsigned PropertySize =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002135 CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002136 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002137 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
2138 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002139 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002140 Properties.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002141 Values[2] = llvm::ConstantArray::get(AT, Properties);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002142 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002143
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002144 llvm::GlobalVariable *GV =
2145 CreateMetadataVar(Name, Init,
2146 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002147 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002148 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002149 true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002150 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002151}
2152
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002153llvm::Constant *
2154CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
2155 ArrayRef<llvm::Constant*> MethodTypes,
2156 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002157 // Return null for empty list.
2158 if (MethodTypes.empty())
2159 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
2160
2161 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
2162 MethodTypes.size());
2163 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
2164
2165 llvm::GlobalVariable *GV =
2166 CreateMetadataVar(Name, Init,
2167 (ObjCABI == 2) ? "__DATA, __objc_const" : 0,
2168 (ObjCABI == 2) ? 8 : 4,
2169 true);
2170 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
2171}
2172
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002173/*
Daniel Dunbarb036db82008-08-13 03:21:16 +00002174 struct objc_method_description_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002175 int count;
2176 struct objc_method_description list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002177 };
2178*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002179llvm::Constant *
2180CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002181 llvm::Constant *Desc[] = {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002182 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002183 ObjCTypes.SelectorPtrTy),
2184 GetMethodVarType(MD)
2185 };
Douglas Gregora9d84932011-05-27 01:19:52 +00002186 if (!Desc[1])
2187 return 0;
2188
Owen Anderson0e0189d2009-07-27 22:29:56 +00002189 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002190 Desc);
2191}
Daniel Dunbarb036db82008-08-13 03:21:16 +00002192
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002193llvm::Constant *
2194CGObjCMac::EmitMethodDescList(Twine Name, const char *Section,
2195 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002196 // Return null for empty list.
2197 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002198 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002199
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002200 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002201 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002202 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002203 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002204 Values[1] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002205 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002206
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002207 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002208 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002209 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002210}
2211
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002212/*
2213 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002214 char *category_name;
2215 char *class_name;
2216 struct _objc_method_list *instance_methods;
2217 struct _objc_method_list *class_methods;
2218 struct _objc_protocol_list *protocols;
2219 uint32_t size; // <rdar://4585769>
2220 struct _objc_property_list *instance_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002221 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002222*/
Daniel Dunbar92992502008-08-15 22:20:32 +00002223void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002224 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002225
Mike Stump18bb9282009-05-16 07:57:57 +00002226 // FIXME: This is poor design, the OCD should have a pointer to the category
2227 // decl. Additionally, note that Category can be null for the @implementation
2228 // w/o an @interface case. Sema should just create one for us as it does for
2229 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002230 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002231 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002232 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002233
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002234 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002235 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2236 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002237
Bill Wendlinga515b582012-02-09 22:16:49 +00002238 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002239 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002240 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002241 // Instance methods should always be defined.
2242 InstanceMethods.push_back(GetMethodConstant(*i));
2243 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002244 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002245 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002246 // Class methods should always be defined.
2247 ClassMethods.push_back(GetMethodConstant(*i));
2248 }
2249
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002250 llvm::Constant *Values[7];
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002251 Values[0] = GetClassName(OCD->getIdentifier());
2252 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00002253 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002254 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002255 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002256 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002257 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002258 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002259 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002260 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002261 ClassMethods);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002262 if (Category) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002263 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002264 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002265 Category->protocol_begin(),
2266 Category->protocol_end());
2267 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002268 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002269 }
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002270 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002271
2272 // If there is no category @interface then there can be no properties.
2273 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002274 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002275 OCD, Category, ObjCTypes);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002276 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002277 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002278 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002279
Owen Anderson0e0189d2009-07-27 22:29:56 +00002280 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002281 Values);
2282
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002283 llvm::GlobalVariable *GV =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002284 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002285 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002286 4, true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002287 DefinedCategories.push_back(GV);
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00002288 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002289 // method definition entries must be clear for next implementation.
2290 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002291}
2292
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002293// FIXME: Get from somewhere?
2294enum ClassFlags {
2295 eClassFlags_Factory = 0x00001,
2296 eClassFlags_Meta = 0x00002,
2297 // <rdr://5142207>
2298 eClassFlags_HasCXXStructors = 0x02000,
2299 eClassFlags_Hidden = 0x20000,
2300 eClassFlags_ABI2_Hidden = 0x00010,
2301 eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
2302};
2303
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002304/*
2305 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002306 Class isa;
2307 Class super_class;
2308 const char *name;
2309 long version;
2310 long info;
2311 long instance_size;
2312 struct _objc_ivar_list *ivars;
2313 struct _objc_method_list *methods;
2314 struct _objc_cache *cache;
2315 struct _objc_protocol_list *protocols;
2316 // Objective-C 1.0 extensions (<rdr://4585769>)
2317 const char *ivar_layout;
2318 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002319 };
2320
2321 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002322*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002323void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002324 DefinedSymbols.insert(ID->getIdentifier());
2325
Chris Lattner86d7d912008-11-24 03:54:41 +00002326 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002327 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002328 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002329 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002330 llvm::Constant *Protocols =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002331 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00002332 Interface->all_referenced_protocol_begin(),
2333 Interface->all_referenced_protocol_end());
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002334 unsigned Flags = eClassFlags_Factory;
John McCall31168b02011-06-15 23:02:42 +00002335 if (ID->hasCXXStructors())
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00002336 Flags |= eClassFlags_HasCXXStructors;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002337 unsigned Size =
Ken Dyckc8ae5502011-02-09 01:59:34 +00002338 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002339
2340 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00002341 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002342 Flags |= eClassFlags_Hidden;
2343
Bill Wendlinga515b582012-02-09 22:16:49 +00002344 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002345 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002346 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002347 // Instance methods should always be defined.
2348 InstanceMethods.push_back(GetMethodConstant(*i));
2349 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002350 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002351 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002352 // Class methods should always be defined.
2353 ClassMethods.push_back(GetMethodConstant(*i));
2354 }
2355
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002356 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002357 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002358 ObjCPropertyImplDecl *PID = *i;
2359
2360 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2361 ObjCPropertyDecl *PD = PID->getPropertyDecl();
2362
2363 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
2364 if (llvm::Constant *C = GetMethodConstant(MD))
2365 InstanceMethods.push_back(C);
2366 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
2367 if (llvm::Constant *C = GetMethodConstant(MD))
2368 InstanceMethods.push_back(C);
2369 }
2370 }
2371
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002372 llvm::Constant *Values[12];
Daniel Dunbarccf61832009-05-03 08:56:52 +00002373 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002374 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002375 // Record a reference to the super class.
2376 LazySymbols.insert(Super->getIdentifier());
2377
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002378 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002379 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002380 ObjCTypes.ClassPtrTy);
2381 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002382 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002383 }
2384 Values[ 2] = GetClassName(ID->getIdentifier());
2385 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002386 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2387 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2388 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002389 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002390 Values[ 7] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002391 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002392 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002393 InstanceMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002394 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002395 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002396 Values[ 9] = Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002397 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002398 Values[11] = EmitClassExtension(ID);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002399 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002400 Values);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002401 std::string Name("\01L_OBJC_CLASS_");
2402 Name += ClassName;
2403 const char *Section = "__OBJC,__class,regular,no_dead_strip";
2404 // Check for a forward reference.
2405 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2406 if (GV) {
2407 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2408 "Forward metaclass reference has incorrect type.");
2409 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2410 GV->setInitializer(Init);
2411 GV->setSection(Section);
2412 GV->setAlignment(4);
2413 CGM.AddUsedGlobal(GV);
2414 }
2415 else
2416 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002417 DefinedClasses.push_back(GV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002418 // method definition entries must be clear for next implementation.
2419 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002420}
2421
2422llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2423 llvm::Constant *Protocols,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002424 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002425 unsigned Flags = eClassFlags_Meta;
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002426 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002427
John McCall457a04e2010-10-22 21:05:15 +00002428 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002429 Flags |= eClassFlags_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002430
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002431 llvm::Constant *Values[12];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002432 // The isa for the metaclass is the root of the hierarchy.
2433 const ObjCInterfaceDecl *Root = ID->getClassInterface();
2434 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2435 Root = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002436 Values[ 0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002437 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002438 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002439 // The super class for the metaclass is emitted as the name of the
2440 // super class. The runtime fixes this up to point to the
2441 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002442 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002443 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002444 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002445 ObjCTypes.ClassPtrTy);
2446 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002447 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002448 }
2449 Values[ 2] = GetClassName(ID->getIdentifier());
2450 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002451 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2452 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2453 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002454 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002455 Values[ 7] =
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002456 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002457 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002458 Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002459 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002460 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002461 Values[ 9] = Protocols;
2462 // ivar_layout for metaclass is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002463 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002464 // The class extension is always unused for metaclasses.
Owen Anderson0b75f232009-07-31 20:28:54 +00002465 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002466 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002467 Values);
2468
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002469 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattner86d7d912008-11-24 03:54:41 +00002470 Name += ID->getNameAsCString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002471
2472 // Check for a forward reference.
2473 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2474 if (GV) {
2475 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2476 "Forward metaclass reference has incorrect type.");
2477 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2478 GV->setInitializer(Init);
2479 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00002480 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002481 llvm::GlobalValue::InternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002482 Init, Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002483 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002484 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbarae333842009-03-09 22:18:41 +00002485 GV->setAlignment(4);
Chris Lattnerf56501c2009-07-17 23:57:13 +00002486 CGM.AddUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002487
2488 return GV;
2489}
2490
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002491llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002492 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002493
Mike Stump18bb9282009-05-16 07:57:57 +00002494 // FIXME: Should we look these up somewhere other than the module. Its a bit
2495 // silly since we only generate these while processing an implementation, so
2496 // exactly one pointer would work if know when we entered/exitted an
2497 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002498
2499 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00002500 // Previously, metaclass with internal linkage may have been defined.
2501 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002502 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2503 true)) {
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002504 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2505 "Forward metaclass reference has incorrect type.");
2506 return GV;
2507 } else {
2508 // Generate as an external reference to keep a consistent
2509 // module. This will be patched up when we emit the metaclass.
Owen Andersonc10c8d32009-07-08 19:05:04 +00002510 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002511 llvm::GlobalValue::ExternalLinkage,
2512 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002513 Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002514 }
2515}
2516
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002517llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2518 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2519
2520 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2521 true)) {
2522 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2523 "Forward class metadata reference has incorrect type.");
2524 return GV;
2525 } else {
2526 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2527 llvm::GlobalValue::ExternalLinkage,
2528 0,
2529 Name);
2530 }
2531}
2532
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002533/*
2534 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002535 uint32_t size;
2536 const char *weak_ivar_layout;
2537 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002538 };
2539*/
2540llvm::Constant *
2541CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002542 uint64_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002543 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002544
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002545 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002546 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian6df69862009-04-22 23:00:43 +00002547 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002548 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002549 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002550
2551 // Return null if no extension bits are used.
2552 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002553 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002554
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002555 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002556 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002557 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002558 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002559 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002560}
2561
2562/*
2563 struct objc_ivar {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002564 char *ivar_name;
2565 char *ivar_type;
2566 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002567 };
2568
2569 struct objc_ivar_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002570 int ivar_count;
2571 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002572 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002573*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002574llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002575 bool ForClass) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002576 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002577
2578 // When emitting the root class GCC emits ivar entries for the
2579 // actual class structure. It is not clear if we need to follow this
2580 // behavior; for now lets try and get away with not doing it. If so,
2581 // the cleanest solution would be to make up an ObjCInterfaceDecl
2582 // for the class.
2583 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00002584 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002585
Jordy Rosea91768e2011-07-22 02:08:32 +00002586 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002587
Jordy Rosea91768e2011-07-22 02:08:32 +00002588 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00002589 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00002590 // Ignore unnamed bit-fields.
2591 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002592 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002593 llvm::Constant *Ivar[] = {
2594 GetMethodVarName(IVD->getIdentifier()),
2595 GetMethodVarType(IVD),
2596 llvm::ConstantInt::get(ObjCTypes.IntTy,
2597 ComputeIvarBaseOffset(CGM, OID, IVD))
2598 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002599 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002600 }
2601
2602 // Return null for empty list.
2603 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002604 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002605
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002606 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002607 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002608 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002609 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002610 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002611 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002612
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002613 llvm::GlobalVariable *GV;
2614 if (ForClass)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002615 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002616 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002617 4, true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002618 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002619 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002620 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002621 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002622 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002623}
2624
2625/*
2626 struct objc_method {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002627 SEL method_name;
2628 char *method_types;
2629 void *method;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002630 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002631
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002632 struct objc_method_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002633 struct objc_method_list *obsolete;
2634 int count;
2635 struct objc_method methods_list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002636 };
2637*/
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002638
2639/// GetMethodConstant - Return a struct objc_method constant for the
2640/// given method if it has been defined. The result is null if the
2641/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002642llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00002643 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002644 if (!Fn)
2645 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002646
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002647 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00002648 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002649 ObjCTypes.SelectorPtrTy),
2650 GetMethodVarType(MD),
2651 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
2652 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002653 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002654}
2655
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002656llvm::Constant *CGObjCMac::EmitMethodList(Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002657 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002658 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002659 // Return null for empty list.
2660 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002661 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002662
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002663 llvm::Constant *Values[3];
Owen Anderson0b75f232009-07-31 20:28:54 +00002664 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002665 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002666 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002667 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002668 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002669 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002670
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002671 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002672 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002673}
2674
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00002675llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002676 const ObjCContainerDecl *CD) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002677 SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00002678 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002679
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00002680 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00002681 llvm::FunctionType *MethodTy =
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00002682 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002683 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00002684 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002685 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00002686 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002687 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002688 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002689
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002690 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002691}
2692
Daniel Dunbar30c65362009-03-09 20:09:19 +00002693llvm::GlobalVariable *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002694CGObjCCommonMac::CreateMetadataVar(Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00002695 llvm::Constant *Init,
2696 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00002697 unsigned Align,
2698 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00002699 llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002700 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002701 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerf56501c2009-07-17 23:57:13 +00002702 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbar30c65362009-03-09 20:09:19 +00002703 if (Section)
2704 GV->setSection(Section);
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00002705 if (Align)
2706 GV->setAlignment(Align);
2707 if (AddToUsed)
Chris Lattnerf56501c2009-07-17 23:57:13 +00002708 CGM.AddUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00002709 return GV;
2710}
2711
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002712llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00002713 // Abuse this interface function as a place to finalize.
2714 FinishModule();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002715 return NULL;
2716}
2717
Chris Lattnerd4808922009-03-22 21:03:39 +00002718llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002719 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00002720}
2721
Chris Lattnerd4808922009-03-22 21:03:39 +00002722llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002723 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00002724}
2725
David Chisnall168b80f2010-12-26 22:13:16 +00002726llvm::Constant *CGObjCMac::GetGetStructFunction() {
2727 return ObjCTypes.getCopyStructFn();
2728}
2729llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00002730 return ObjCTypes.getCopyStructFn();
2731}
2732
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00002733llvm::Constant *CGObjCMac::GetCppAtomicObjectFunction() {
2734 return ObjCTypes.getCppAtomicObjectFunction();
2735}
2736
Chris Lattnerd4808922009-03-22 21:03:39 +00002737llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002738 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00002739}
2740
John McCallbd309292010-07-06 01:34:17 +00002741void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
2742 return EmitTryOrSynchronizedStmt(CGF, S);
2743}
2744
2745void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
2746 const ObjCAtSynchronizedStmt &S) {
2747 return EmitTryOrSynchronizedStmt(CGF, S);
2748}
2749
John McCall65bea082010-07-21 06:59:36 +00002750namespace {
John McCallcda666c2010-07-21 07:22:38 +00002751 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00002752 const Stmt &S;
John McCall2dd7d442010-08-04 05:59:32 +00002753 llvm::Value *SyncArgSlot;
John McCall65bea082010-07-21 06:59:36 +00002754 llvm::Value *CallTryExitVar;
2755 llvm::Value *ExceptionData;
2756 ObjCTypesHelper &ObjCTypes;
2757 PerformFragileFinally(const Stmt *S,
John McCall2dd7d442010-08-04 05:59:32 +00002758 llvm::Value *SyncArgSlot,
John McCall65bea082010-07-21 06:59:36 +00002759 llvm::Value *CallTryExitVar,
2760 llvm::Value *ExceptionData,
2761 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00002762 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00002763 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
2764
John McCall30317fd2011-07-12 20:27:29 +00002765 void Emit(CodeGenFunction &CGF, Flags flags) {
John McCall65bea082010-07-21 06:59:36 +00002766 // Check whether we need to call objc_exception_try_exit.
2767 // In optimized code, this branch will always be folded.
2768 llvm::BasicBlock *FinallyCallExit =
2769 CGF.createBasicBlock("finally.call_exit");
2770 llvm::BasicBlock *FinallyNoCallExit =
2771 CGF.createBasicBlock("finally.no_call_exit");
2772 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
2773 FinallyCallExit, FinallyNoCallExit);
2774
2775 CGF.EmitBlock(FinallyCallExit);
2776 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
2777 ->setDoesNotThrow();
2778
2779 CGF.EmitBlock(FinallyNoCallExit);
2780
2781 if (isa<ObjCAtTryStmt>(S)) {
2782 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00002783 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
2784 // Save the current cleanup destination in case there's
2785 // control flow inside the finally statement.
2786 llvm::Value *CurCleanupDest =
2787 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
2788
John McCall65bea082010-07-21 06:59:36 +00002789 CGF.EmitStmt(FinallyStmt->getFinallyBody());
2790
John McCallcebe0ca2010-08-11 00:16:14 +00002791 if (CGF.HaveInsertPoint()) {
2792 CGF.Builder.CreateStore(CurCleanupDest,
2793 CGF.getNormalCleanupDestSlot());
2794 } else {
2795 // Currently, the end of the cleanup must always exist.
2796 CGF.EnsureInsertPoint();
2797 }
2798 }
John McCall65bea082010-07-21 06:59:36 +00002799 } else {
2800 // Emit objc_sync_exit(expr); as finally's sole statement for
2801 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00002802 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall65bea082010-07-21 06:59:36 +00002803 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
2804 ->setDoesNotThrow();
2805 }
2806 }
2807 };
John McCall42227ed2010-07-31 23:20:56 +00002808
2809 class FragileHazards {
2810 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002811 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00002812 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
2813
2814 llvm::InlineAsm *ReadHazard;
2815 llvm::InlineAsm *WriteHazard;
2816
2817 llvm::FunctionType *GetAsmFnType();
2818
2819 void collectLocals();
2820 void emitReadHazard(CGBuilderTy &Builder);
2821
2822 public:
2823 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00002824
John McCall42227ed2010-07-31 23:20:56 +00002825 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00002826 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00002827 };
2828}
2829
2830/// Create the fragile-ABI read and write hazards based on the current
2831/// state of the function, which is presumed to be immediately prior
2832/// to a @try block. These hazards are used to maintain correct
2833/// semantics in the face of optimization and the fragile ABI's
2834/// cavalier use of setjmp/longjmp.
2835FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
2836 collectLocals();
2837
2838 if (Locals.empty()) return;
2839
2840 // Collect all the blocks in the function.
2841 for (llvm::Function::iterator
2842 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
2843 BlocksBeforeTry.insert(&*I);
2844
2845 llvm::FunctionType *AsmFnTy = GetAsmFnType();
2846
2847 // Create a read hazard for the allocas. This inhibits dead-store
2848 // optimizations and forces the values to memory. This hazard is
2849 // inserted before any 'throwing' calls in the protected scope to
2850 // reflect the possibility that the variables might be read from the
2851 // catch block if the call throws.
2852 {
2853 std::string Constraint;
2854 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2855 if (I) Constraint += ',';
2856 Constraint += "*m";
2857 }
2858
2859 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2860 }
2861
2862 // Create a write hazard for the allocas. This inhibits folding
2863 // loads across the hazard. This hazard is inserted at the
2864 // beginning of the catch path to reflect the possibility that the
2865 // variables might have been written within the protected scope.
2866 {
2867 std::string Constraint;
2868 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2869 if (I) Constraint += ',';
2870 Constraint += "=*m";
2871 }
2872
2873 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2874 }
2875}
2876
2877/// Emit a write hazard at the current location.
2878void FragileHazards::emitWriteHazard() {
2879 if (Locals.empty()) return;
2880
Jay Foad5bd375a2011-07-15 08:37:34 +00002881 CGF.Builder.CreateCall(WriteHazard, Locals)->setDoesNotThrow();
John McCall42227ed2010-07-31 23:20:56 +00002882}
2883
John McCall42227ed2010-07-31 23:20:56 +00002884void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
2885 assert(!Locals.empty());
Jay Foad5bd375a2011-07-15 08:37:34 +00002886 Builder.CreateCall(ReadHazard, Locals)->setDoesNotThrow();
John McCall42227ed2010-07-31 23:20:56 +00002887}
2888
2889/// Emit read hazards in all the protected blocks, i.e. all the blocks
2890/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00002891void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00002892 if (Locals.empty()) return;
2893
2894 CGBuilderTy Builder(CGF.getLLVMContext());
2895
2896 // Iterate through all blocks, skipping those prior to the try.
2897 for (llvm::Function::iterator
2898 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
2899 llvm::BasicBlock &BB = *FI;
2900 if (BlocksBeforeTry.count(&BB)) continue;
2901
2902 // Walk through all the calls in the block.
2903 for (llvm::BasicBlock::iterator
2904 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
2905 llvm::Instruction &I = *BI;
2906
2907 // Ignore instructions that aren't non-intrinsic calls.
2908 // These are the only calls that can possibly call longjmp.
2909 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
2910 if (isa<llvm::IntrinsicInst>(I))
2911 continue;
2912
2913 // Ignore call sites marked nounwind. This may be questionable,
2914 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
2915 llvm::CallSite CS(&I);
2916 if (CS.doesNotThrow()) continue;
2917
John McCall2dd7d442010-08-04 05:59:32 +00002918 // Insert a read hazard before the call. This will ensure that
2919 // any writes to the locals are performed before making the
2920 // call. If the call throws, then this is sufficient to
2921 // guarantee correctness as long as it doesn't also write to any
2922 // locals.
John McCall42227ed2010-07-31 23:20:56 +00002923 Builder.SetInsertPoint(&BB, BI);
2924 emitReadHazard(Builder);
2925 }
2926 }
2927}
2928
2929static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
2930 if (V) S.insert(V);
2931}
2932
2933void FragileHazards::collectLocals() {
2934 // Compute a set of allocas to ignore.
2935 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
2936 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
2937 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00002938
2939 // Collect all the allocas currently in the function. This is
2940 // probably way too aggressive.
2941 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
2942 for (llvm::BasicBlock::iterator
2943 I = Entry.begin(), E = Entry.end(); I != E; ++I)
2944 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
2945 Locals.push_back(&*I);
2946}
2947
2948llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002949 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00002950 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
2951 tys[i] = Locals[i]->getType();
2952 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00002953}
2954
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002955/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002956
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002957 Objective-C setjmp-longjmp (sjlj) Exception Handling
2958 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002959
John McCallbd309292010-07-06 01:34:17 +00002960 A catch buffer is a setjmp buffer plus:
2961 - a pointer to the exception that was caught
2962 - a pointer to the previous exception data buffer
2963 - two pointers of reserved storage
2964 Therefore catch buffers form a stack, with a pointer to the top
2965 of the stack kept in thread-local storage.
2966
2967 objc_exception_try_enter pushes a catch buffer onto the EH stack.
2968 objc_exception_try_exit pops the given catch buffer, which is
2969 required to be the top of the EH stack.
2970 objc_exception_throw pops the top of the EH stack, writes the
2971 thrown exception into the appropriate field, and longjmps
2972 to the setjmp buffer. It crashes the process (with a printf
2973 and an abort()) if there are no catch buffers on the stack.
2974 objc_exception_extract just reads the exception pointer out of the
2975 catch buffer.
2976
2977 There's no reason an implementation couldn't use a light-weight
2978 setjmp here --- something like __builtin_setjmp, but API-compatible
2979 with the heavyweight setjmp. This will be more important if we ever
2980 want to implement correct ObjC/C++ exception interactions for the
2981 fragile ABI.
2982
2983 Note that for this use of setjmp/longjmp to be correct, we may need
2984 to mark some local variables volatile: if a non-volatile local
2985 variable is modified between the setjmp and the longjmp, it has
2986 indeterminate value. For the purposes of LLVM IR, it may be
2987 sufficient to make loads and stores within the @try (to variables
2988 declared outside the @try) volatile. This is necessary for
2989 optimized correctness, but is not currently being done; this is
2990 being tracked as rdar://problem/8160285
2991
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002992 The basic framework for a @try-catch-finally is as follows:
2993 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002994 objc_exception_data d;
2995 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00002996 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002997
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002998 objc_exception_try_enter(&d);
2999 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003000 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003001 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003002 // exception path
3003 id _caught = objc_exception_extract(&d);
3004
3005 // enter new try scope for handlers
3006 if (!setjmp(d.jmp_buf)) {
3007 ... match exception and execute catch blocks ...
3008
3009 // fell off end, rethrow.
3010 _rethrow = _caught;
3011 ... jump-through-finally to finally_rethrow ...
3012 } else {
3013 // exception in catch block
3014 _rethrow = objc_exception_extract(&d);
3015 _call_try_exit = false;
3016 ... jump-through-finally to finally_rethrow ...
3017 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003018 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003019 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003020
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003021 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00003022 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003023 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00003024
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003025 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003026 ... dispatch to finally destination ...
3027
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003028 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003029 objc_exception_throw(_rethrow);
3030
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003031 finally_end:
3032 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003033
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003034 This framework differs slightly from the one gcc uses, in that gcc
3035 uses _rethrow to determine if objc_exception_try_exit should be called
3036 and if the object should be rethrown. This breaks in the face of
3037 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003038
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003039 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003040
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003041 - If there are no catch blocks, then we avoid emitting the second
3042 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003043
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003044 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
3045 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003046
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003047 - FIXME: If there is no @finally block we can do a few more
3048 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003049
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003050 Rethrows and Jumps-Through-Finally
3051 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003052
John McCallbd309292010-07-06 01:34:17 +00003053 '@throw;' is supported by pushing the currently-caught exception
3054 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003055
John McCallbd309292010-07-06 01:34:17 +00003056 Branches through the @finally block are handled with an ordinary
3057 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
3058 exceptions are not compatible with C++ exceptions, and this is
3059 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003060
John McCallbd309292010-07-06 01:34:17 +00003061 @synchronized(expr) { stmt; } is emitted as if it were:
3062 id synch_value = expr;
3063 objc_sync_enter(synch_value);
3064 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003065*/
3066
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00003067void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
3068 const Stmt &S) {
3069 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00003070
3071 // A destination for the fall-through edges of the catch handlers to
3072 // jump to.
3073 CodeGenFunction::JumpDest FinallyEnd =
3074 CGF.getJumpDestInCurrentScope("finally.end");
3075
3076 // A destination for the rethrow edge of the catch handlers to jump
3077 // to.
3078 CodeGenFunction::JumpDest FinallyRethrow =
3079 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003080
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003081 // For @synchronized, call objc_sync_enter(sync.expr). The
3082 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00003083 // @synchronized. We can't avoid a temp here because we need the
3084 // value to be preserved. If the backend ever does liveness
3085 // correctly after setjmp, this will be unnecessary.
3086 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003087 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00003088 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003089 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
3090 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallbd309292010-07-06 01:34:17 +00003091 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
3092 ->setDoesNotThrow();
John McCall2dd7d442010-08-04 05:59:32 +00003093
3094 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
3095 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003096 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003097
John McCall2dd7d442010-08-04 05:59:32 +00003098 // Allocate memory for the setjmp buffer. This needs to be kept
3099 // live throughout the try and catch blocks.
3100 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
3101 "exceptiondata.ptr");
3102
John McCall42227ed2010-07-31 23:20:56 +00003103 // Create the fragile hazards. Note that this will not capture any
3104 // of the allocas required for exception processing, but will
3105 // capture the current basic block (which extends all the way to the
3106 // setjmp call) as "before the @try".
3107 FragileHazards Hazards(CGF);
3108
John McCallbd309292010-07-06 01:34:17 +00003109 // Create a flag indicating whether the cleanup needs to call
3110 // objc_exception_try_exit. This is true except when
3111 // - no catches match and we're branching through the cleanup
3112 // just to rethrow the exception, or
3113 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00003114 // The setjmp-safety rule here is that we should always store to this
3115 // variable in a place that dominates the branch through the cleanup
3116 // without passing through any setjmps.
John McCallbd309292010-07-06 01:34:17 +00003117 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlssonda0e4562009-02-07 21:26:04 +00003118 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003119
John McCall9916e3f2010-10-04 23:42:51 +00003120 // A slot containing the exception to rethrow. Only needed when we
3121 // have both a @catch and a @finally.
3122 llvm::Value *PropagatingExnVar = 0;
3123
John McCallbd309292010-07-06 01:34:17 +00003124 // Push a normal cleanup to leave the try scope.
John McCallcda666c2010-07-21 07:22:38 +00003125 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00003126 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00003127 CallTryExitVar,
3128 ExceptionData,
3129 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00003130
3131 // Enter a try block:
3132 // - Call objc_exception_try_enter to push ExceptionData on top of
3133 // the EH stack.
3134 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3135 ->setDoesNotThrow();
3136
3137 // - Call setjmp on the exception data buffer.
3138 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
3139 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
3140 llvm::Value *SetJmpBuffer =
Jay Foad040dd822011-07-22 08:16:57 +00003141 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
John McCallbd309292010-07-06 01:34:17 +00003142 llvm::CallInst *SetJmpResult =
3143 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
3144 SetJmpResult->setDoesNotThrow();
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003145 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00003146
3147 // If setjmp returned 0, enter the protected block; otherwise,
3148 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00003149 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3150 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00003151 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00003152 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3153 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003154
John McCallbd309292010-07-06 01:34:17 +00003155 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003156 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00003157 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003158 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00003159 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00003160
3161 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003162
John McCallbd309292010-07-06 01:34:17 +00003163 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00003164 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003165
John McCall42227ed2010-07-31 23:20:56 +00003166 // Don't optimize loads of the in-scope locals across this point.
3167 Hazards.emitWriteHazard();
3168
John McCallbd309292010-07-06 01:34:17 +00003169 // For a @synchronized (or a @try with no catches), just branch
3170 // through the cleanup to the rethrow block.
3171 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
3172 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00003173 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003174 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00003175
3176 // Otherwise, we have to match against the caught exceptions.
3177 } else {
John McCall2dd7d442010-08-04 05:59:32 +00003178 // Retrieve the exception object. We may emit multiple blocks but
3179 // nothing can cross this so the value is already in SSA form.
3180 llvm::CallInst *Caught =
3181 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3182 ExceptionData, "caught");
3183 Caught->setDoesNotThrow();
3184
John McCallbd309292010-07-06 01:34:17 +00003185 // Push the exception to rethrow onto the EH value stack for the
3186 // benefit of any @throws in the handlers.
3187 CGF.ObjCEHValueStack.push_back(Caught);
3188
Douglas Gregor96c79492010-04-23 22:50:49 +00003189 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003190
John McCall2dd7d442010-08-04 05:59:32 +00003191 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallbd309292010-07-06 01:34:17 +00003192
John McCall2dd7d442010-08-04 05:59:32 +00003193 llvm::BasicBlock *CatchBlock = 0;
3194 llvm::BasicBlock *CatchHandler = 0;
3195 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00003196 // Save the currently-propagating exception before
3197 // objc_exception_try_enter clears the exception slot.
3198 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
3199 "propagating_exception");
3200 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
3201
John McCall2dd7d442010-08-04 05:59:32 +00003202 // Enter a new exception try block (in case a @catch block
3203 // throws an exception).
3204 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3205 ->setDoesNotThrow();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003206
John McCall2dd7d442010-08-04 05:59:32 +00003207 llvm::CallInst *SetJmpResult =
3208 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3209 "setjmp.result");
3210 SetJmpResult->setDoesNotThrow();
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003211 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003212
John McCall2dd7d442010-08-04 05:59:32 +00003213 llvm::Value *Threw =
3214 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3215
3216 CatchBlock = CGF.createBasicBlock("catch");
3217 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3218 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3219
3220 CGF.EmitBlock(CatchBlock);
3221 }
3222
3223 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003224
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003225 // Handle catch list. As a special case we check if everything is
3226 // matched and avoid generating code for falling off the end if
3227 // so.
3228 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00003229 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3230 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003231
Douglas Gregor46a572b2010-04-26 16:46:50 +00003232 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff7cae42b2009-07-10 23:34:53 +00003233 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar523208f2008-09-27 07:36:24 +00003234
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003235 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003236 if (!CatchParam) {
3237 AllMatched = true;
3238 } else {
John McCall9dd450b2009-09-21 23:43:11 +00003239 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003240
John McCallbd309292010-07-06 01:34:17 +00003241 // catch(id e) always matches under this ABI, since only
3242 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00003243 // FIXME: For the time being we also match id<X>; this should
3244 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00003245 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003246 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003247 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003248
John McCallbd309292010-07-06 01:34:17 +00003249 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003250 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00003251 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3252
Anders Carlsson9396a892008-09-11 09:15:33 +00003253 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00003254 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003255 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00003256
3257 // These types work out because ConvertType(id) == i8*.
Steve Naroff371b8fb2009-03-03 19:52:17 +00003258 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson9396a892008-09-11 09:15:33 +00003259 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003260
Anders Carlsson9396a892008-09-11 09:15:33 +00003261 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003262
3263 // The scope of the catch variable ends right here.
3264 CatchVarCleanups.ForceCleanup();
3265
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003266 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003267 break;
3268 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003269
Steve Naroff7cae42b2009-07-10 23:34:53 +00003270 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00003271 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00003272
3273 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00003274 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3275 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003276
3277 // Check if the @catch block matches the exception object.
John McCall96fa4842010-05-17 21:00:27 +00003278 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003279
John McCallbd309292010-07-06 01:34:17 +00003280 llvm::CallInst *Match =
Chris Lattnerc6406db2009-04-22 02:26:14 +00003281 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3282 Class, Caught, "match");
John McCallbd309292010-07-06 01:34:17 +00003283 Match->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003284
John McCallbd309292010-07-06 01:34:17 +00003285 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3286 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003287
3288 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00003289 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003290
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003291 // Emit the @catch block.
3292 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00003293
3294 // Collect any cleanups for the catch variable. The scope lasts until
3295 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00003296 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00003297
John McCall1c9c3fd2010-10-15 04:57:14 +00003298 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003299 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003300
John McCallbd309292010-07-06 01:34:17 +00003301 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003302 llvm::Value *Tmp =
3303 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00003304 CGF.ConvertType(CatchParam->getType()));
Steve Naroff371b8fb2009-03-03 19:52:17 +00003305 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003306
Anders Carlsson9396a892008-09-11 09:15:33 +00003307 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003308
3309 // We're done with the catch variable.
3310 CatchVarCleanups.ForceCleanup();
3311
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003312 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003313
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003314 CGF.EmitBlock(NextCatchBlock);
3315 }
3316
John McCallbd309292010-07-06 01:34:17 +00003317 CGF.ObjCEHValueStack.pop_back();
3318
John McCall2dd7d442010-08-04 05:59:32 +00003319 // If nothing wanted anything to do with the caught exception,
3320 // kill the extract call.
3321 if (Caught->use_empty())
3322 Caught->eraseFromParent();
3323
3324 if (!AllMatched)
3325 CGF.EmitBranchThroughCleanup(FinallyRethrow);
3326
3327 if (HasFinally) {
3328 // Emit the exception handler for the @catch blocks.
3329 CGF.EmitBlock(CatchHandler);
3330
3331 // In theory we might now need a write hazard, but actually it's
3332 // unnecessary because there's no local-accessing code between
3333 // the try's write hazard and here.
3334 //Hazards.emitWriteHazard();
3335
John McCall9916e3f2010-10-04 23:42:51 +00003336 // Extract the new exception and save it to the
3337 // propagating-exception slot.
3338 assert(PropagatingExnVar);
3339 llvm::CallInst *NewCaught =
3340 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3341 ExceptionData, "caught");
3342 NewCaught->setDoesNotThrow();
3343 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
3344
John McCall2dd7d442010-08-04 05:59:32 +00003345 // Don't pop the catch handler; the throw already did.
3346 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003347 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003348 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003349 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003350
John McCall42227ed2010-07-31 23:20:56 +00003351 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00003352 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003353
John McCallbd309292010-07-06 01:34:17 +00003354 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00003355 CGF.Builder.restoreIP(TryFallthroughIP);
3356 if (CGF.HaveInsertPoint())
3357 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00003358 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00003359 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003360
John McCallbd309292010-07-06 01:34:17 +00003361 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00003362 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00003363 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00003364 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00003365 // If we have a propagating-exception variable, check it.
3366 llvm::Value *PropagatingExn;
3367 if (PropagatingExnVar) {
3368 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00003369
John McCall9916e3f2010-10-04 23:42:51 +00003370 // Otherwise, just look in the buffer for the exception to throw.
3371 } else {
3372 llvm::CallInst *Caught =
3373 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3374 ExceptionData);
3375 Caught->setDoesNotThrow();
3376 PropagatingExn = Caught;
3377 }
3378
3379 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
John McCallbd309292010-07-06 01:34:17 +00003380 ->setDoesNotThrow();
3381 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00003382 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003383
John McCall42227ed2010-07-31 23:20:56 +00003384 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003385}
3386
3387void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003388 const ObjCAtThrowStmt &S) {
Anders Carlssone005aa12008-09-09 16:16:55 +00003389 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003390
Anders Carlssone005aa12008-09-09 16:16:55 +00003391 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00003392 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003393 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00003394 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00003395 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003396 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003397 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00003398 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00003399 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003400
John McCallbd309292010-07-06 01:34:17 +00003401 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3402 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003403 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003404
3405 // Clear the insertion point to indicate we are in unreachable code.
3406 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003407}
3408
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003409/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003410/// object: objc_read_weak (id *src)
3411///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003412llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003413 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003414 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003415 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3416 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3417 ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00003418 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003419 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00003420 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003421 return read_weak;
3422}
3423
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003424/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
3425/// objc_assign_weak (id src, id *dst)
3426///
3427void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003428 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003429 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003430 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003431 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003432 assert(Size <= 8 && "does not support size > 8");
3433 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003434 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003435 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3436 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003437 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3438 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00003439 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003440 src, dst, "weakassign");
3441 return;
3442}
3443
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003444/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
3445/// objc_assign_global (id src, id *dst)
3446///
3447void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00003448 llvm::Value *src, llvm::Value *dst,
3449 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003450 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003451 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003452 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003453 assert(Size <= 8 && "does not support size > 8");
3454 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003455 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003456 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3457 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003458 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3459 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00003460 if (!threadlocal)
3461 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
3462 src, dst, "globalassign");
3463 else
3464 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
3465 src, dst, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003466 return;
3467}
3468
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003469/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003470/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003471///
3472void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003473 llvm::Value *src, llvm::Value *dst,
3474 llvm::Value *ivarOffset) {
3475 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00003476 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003477 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003478 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003479 assert(Size <= 8 && "does not support size > 8");
3480 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003481 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003482 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3483 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003484 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3485 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003486 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3487 src, dst, ivarOffset);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003488 return;
3489}
3490
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003491/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
3492/// objc_assign_strongCast (id src, id *dst)
3493///
3494void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003495 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003496 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003497 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003498 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003499 assert(Size <= 8 && "does not support size > 8");
3500 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003501 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003502 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3503 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003504 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3505 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00003506 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003507 src, dst, "weakassign");
3508 return;
3509}
3510
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003511void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003512 llvm::Value *DestPtr,
3513 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003514 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003515 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3516 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003517 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003518 DestPtr, SrcPtr, size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003519 return;
3520}
3521
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003522/// EmitObjCValueForIvar - Code Gen for ivar reference.
3523///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003524LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3525 QualType ObjectTy,
3526 llvm::Value *BaseValue,
3527 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003528 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00003529 const ObjCInterfaceDecl *ID =
3530 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003531 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3532 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003533}
3534
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003535llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00003536 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003537 const ObjCIvarDecl *Ivar) {
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003538 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003539 return llvm::ConstantInt::get(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003540 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3541 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003542}
3543
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003544/* *** Private Interface *** */
3545
3546/// EmitImageInfo - Emit the image info marker used to encode some module
3547/// level information.
3548///
3549/// See: <rdr://4810609&4810587&4810587>
3550/// struct IMAGE_INFO {
3551/// unsigned version;
3552/// unsigned flags;
3553/// };
3554enum ImageInfoFlags {
Daniel Dunbar5e639272010-04-25 20:39:01 +00003555 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003556 eImageInfo_GarbageCollected = (1 << 1),
3557 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003558 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
3559
Daniel Dunbar5e639272010-04-25 20:39:01 +00003560 // A flag indicating that the module has no instances of a @synthesize of a
3561 // superclass variable. <rdar://problem/6803242>
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003562 eImageInfo_CorrectedSynthesize = (1 << 4)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003563};
3564
Daniel Dunbar5e639272010-04-25 20:39:01 +00003565void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003566 unsigned version = 0; // Version is unused?
3567 unsigned flags = 0;
3568
3569 // FIXME: Fix and continue?
Douglas Gregor79a91412011-09-13 17:21:33 +00003570 if (CGM.getLangOptions().getGC() != LangOptions::NonGC)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003571 flags |= eImageInfo_GarbageCollected;
Douglas Gregor79a91412011-09-13 17:21:33 +00003572 if (CGM.getLangOptions().getGC() == LangOptions::GCOnly)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003573 flags |= eImageInfo_GCOnly;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003574
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003575 // We never allow @synthesize of a superclass property.
3576 flags |= eImageInfo_CorrectedSynthesize;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003577
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003578 // Emitted as int[2];
Chris Lattner3def9ae2012-02-06 22:16:34 +00003579 uint32_t Values[2] = { version, flags };
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003580
3581 const char *Section;
3582 if (ObjCABI == 1)
3583 Section = "__OBJC, __image_info,regular";
3584 else
3585 Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003586 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003587 CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
Chris Lattner3def9ae2012-02-06 22:16:34 +00003588 llvm::ConstantDataArray::get(VMContext, Values),
3589 Section, 0, true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003590 GV->setConstant(true);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003591}
3592
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003593
3594// struct objc_module {
3595// unsigned long version;
3596// unsigned long size;
3597// const char *name;
3598// Symtab symtab;
3599// };
3600
3601// FIXME: Get from somewhere
3602static const int ModuleVersion = 7;
3603
3604void CGObjCMac::EmitModuleInfo() {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003605 uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003606
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003607 llvm::Constant *Values[] = {
3608 llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion),
3609 llvm::ConstantInt::get(ObjCTypes.LongTy, Size),
3610 // This used to be the filename, now it is unused. <rdr://4327263>
3611 GetClassName(&CGM.getContext().Idents.get("")),
3612 EmitModuleSymbols()
3613 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003614 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson0e0189d2009-07-27 22:29:56 +00003615 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003616 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00003617 4, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003618}
3619
3620llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003621 unsigned NumClasses = DefinedClasses.size();
3622 unsigned NumCategories = DefinedCategories.size();
3623
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003624 // Return null if no symbols were defined.
3625 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00003626 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003627
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003628 llvm::Constant *Values[5];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003629 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Anderson0b75f232009-07-31 20:28:54 +00003630 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003631 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3632 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003633
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003634 // The runtime expects exactly the list of defined classes followed
3635 // by the list of defined categories, in a single array.
Chris Lattner3def9ae2012-02-06 22:16:34 +00003636 SmallVector<llvm::Constant*, 8> Symbols(NumClasses + NumCategories);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003637 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00003638 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003639 ObjCTypes.Int8PtrTy);
3640 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003641 Symbols[NumClasses + i] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003642 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003643 ObjCTypes.Int8PtrTy);
3644
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003645 Values[4] =
Owen Anderson9793f0e2009-07-29 22:16:19 +00003646 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00003647 Symbols.size()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003648 Symbols);
3649
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003650 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003651
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003652 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003653 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3654 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003655 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003656 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003657}
3658
John McCall31168b02011-06-15 23:02:42 +00003659llvm::Value *CGObjCMac::EmitClassRefFromId(CGBuilderTy &Builder,
3660 IdentifierInfo *II) {
3661 LazySymbols.insert(II);
3662
3663 llvm::GlobalVariable *&Entry = ClassReferences[II];
3664
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003665 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003666 llvm::Constant *Casted =
John McCall31168b02011-06-15 23:02:42 +00003667 llvm::ConstantExpr::getBitCast(GetClassName(II),
3668 ObjCTypes.ClassPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003669 Entry =
John McCall31168b02011-06-15 23:02:42 +00003670 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3671 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
3672 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003673 }
John McCall31168b02011-06-15 23:02:42 +00003674
Benjamin Kramer76399eb2011-09-27 21:06:10 +00003675 return Builder.CreateLoad(Entry);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003676}
3677
John McCall31168b02011-06-15 23:02:42 +00003678llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
3679 const ObjCInterfaceDecl *ID) {
3680 return EmitClassRefFromId(Builder, ID->getIdentifier());
3681}
3682
3683llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder) {
3684 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
3685 return EmitClassRefFromId(Builder, II);
3686}
3687
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00003688llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
3689 bool lvalue) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003690 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003691
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003692 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003693 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00003694 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003695 ObjCTypes.SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003696 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003697 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3698 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003699 4, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003700 }
3701
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00003702 if (lvalue)
3703 return Entry;
Benjamin Kramer76399eb2011-09-27 21:06:10 +00003704 return Builder.CreateLoad(Entry);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003705}
3706
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00003707llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003708 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003709
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003710 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003711 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00003712 llvm::ConstantDataArray::getString(VMContext,
3713 Ident->getNameStart()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003714 ((ObjCABI == 2) ?
3715 "__TEXT,__objc_classname,cstring_literals" :
3716 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003717 1, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003718
Owen Anderson170229f2009-07-14 23:10:40 +00003719 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003720}
3721
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00003722llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
3723 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
3724 I = MethodDefinitions.find(MD);
3725 if (I != MethodDefinitions.end())
3726 return I->second;
3727
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00003728 return NULL;
3729}
3730
Fariborz Jahanian01dff422009-03-05 19:17:31 +00003731/// GetIvarLayoutName - Returns a unique constant for the given
3732/// ivar layout bitmap.
3733llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003734 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003735 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00003736}
3737
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003738void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003739 unsigned int BytePos,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003740 bool ForStrongLayout,
3741 bool &HasUnion) {
3742 const RecordDecl *RD = RT->getDecl();
3743 // FIXME - Use iterator.
Jordy Rosea91768e2011-07-22 02:08:32 +00003744 SmallVector<const FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
Chris Lattner2192fe52011-07-18 04:24:23 +00003745 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003746 const llvm::StructLayout *RecLayout =
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003747 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003748
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003749 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3750 ForStrongLayout, HasUnion);
3751}
3752
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +00003753void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003754 const llvm::StructLayout *Layout,
3755 const RecordDecl *RD,
Jordy Rosea91768e2011-07-22 02:08:32 +00003756 const SmallVectorImpl<const FieldDecl*> &RecFields,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003757 unsigned int BytePos, bool ForStrongLayout,
3758 bool &HasUnion) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003759 bool IsUnion = (RD && RD->isUnion());
3760 uint64_t MaxUnionIvarSize = 0;
3761 uint64_t MaxSkippedUnionIvarSize = 0;
Jordy Rosea91768e2011-07-22 02:08:32 +00003762 const FieldDecl *MaxField = 0;
3763 const FieldDecl *MaxSkippedField = 0;
3764 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003765 uint64_t MaxFieldOffset = 0;
3766 uint64_t MaxSkippedFieldOffset = 0;
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003767 uint64_t LastBitfieldOrUnnamedOffset = 0;
John McCall31168b02011-06-15 23:02:42 +00003768 uint64_t FirstFieldDelta = 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003769
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003770 if (RecFields.empty())
3771 return;
Douglas Gregore8bbc122011-09-02 00:18:52 +00003772 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
3773 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
John McCall31168b02011-06-15 23:02:42 +00003774 if (!RD && CGM.getLangOptions().ObjCAutoRefCount) {
Jordy Rosea91768e2011-07-22 02:08:32 +00003775 const FieldDecl *FirstField = RecFields[0];
John McCall31168b02011-06-15 23:02:42 +00003776 FirstFieldDelta =
3777 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
3778 }
3779
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003780 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Jordy Rosea91768e2011-07-22 02:08:32 +00003781 const FieldDecl *Field = RecFields[i];
Daniel Dunbar62b10702009-05-03 23:35:23 +00003782 uint64_t FieldOffset;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00003783 if (RD) {
Daniel Dunbard51c1a62010-04-14 17:02:21 +00003784 // Note that 'i' here is actually the field index inside RD of Field,
3785 // although this dependency is hidden.
3786 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
John McCall31168b02011-06-15 23:02:42 +00003787 FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00003788 } else
John McCall31168b02011-06-15 23:02:42 +00003789 FieldOffset =
3790 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003791
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003792 // Skip over unnamed or bitfields
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003793 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003794 LastFieldBitfieldOrUnnamed = Field;
3795 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003796 continue;
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003797 }
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003798
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003799 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003800 QualType FQT = Field->getType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003801 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003802 if (FQT->isUnionType())
3803 HasUnion = true;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003804
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003805 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003806 BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003807 ForStrongLayout, HasUnion);
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003808 continue;
3809 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003810
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003811 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003812 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003813 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003814 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003815 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003816 FQT = CArray->getElementType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003817 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3818 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003819 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003820 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003821 FQT = CArray->getElementType();
3822 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003823
3824 assert(!FQT->isUnionType() &&
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003825 "layout for array of unions not supported");
Fariborz Jahanian9a7d57d2011-01-03 19:23:18 +00003826 if (FQT->isRecordType() && ElCount) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003827 int OldIndex = IvarsInfo.size() - 1;
3828 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003829
Ted Kremenekc23c7e62009-07-29 21:53:49 +00003830 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003831 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003832 ForStrongLayout, HasUnion);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003833
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003834 // Replicate layout information for each array element. Note that
3835 // one element is already done.
3836 uint64_t ElIx = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003837 for (int FirstIndex = IvarsInfo.size() - 1,
3838 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003839 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003840 for (int i = OldIndex+1; i <= FirstIndex; ++i)
3841 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
3842 IvarsInfo[i].ivar_size));
3843 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
3844 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
3845 SkipIvars[i].ivar_size));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003846 }
3847 continue;
3848 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003849 }
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003850 // At this point, we are done with Record/Union and array there of.
3851 // For other arrays we are down to its element type.
John McCall8ccfcb52009-09-24 19:53:00 +00003852 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003853
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003854 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall8ccfcb52009-09-24 19:53:00 +00003855 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3856 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00003857 if (IsUnion) {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003858 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00003859 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003860 MaxUnionIvarSize = UnionIvarSize;
3861 MaxField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003862 MaxFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003863 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00003864 } else {
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003865 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003866 FieldSize / WordSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003867 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003868 } else if ((ForStrongLayout &&
John McCall8ccfcb52009-09-24 19:53:00 +00003869 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3870 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00003871 if (IsUnion) {
Mike Stump18bb9282009-05-16 07:57:57 +00003872 // FIXME: Why the asymmetry? We divide by word size in bits on other
3873 // side.
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003874 uint64_t UnionIvarSize = FieldSize;
Daniel Dunbar22007d32009-05-03 13:32:01 +00003875 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003876 MaxSkippedUnionIvarSize = UnionIvarSize;
3877 MaxSkippedField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003878 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003879 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00003880 } else {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003881 // FIXME: Why the asymmetry, we divide by byte size in bits here?
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003882 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003883 FieldSize / ByteSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003884 }
3885 }
3886 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003887
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003888 if (LastFieldBitfieldOrUnnamed) {
3889 if (LastFieldBitfieldOrUnnamed->isBitField()) {
3890 // Last field was a bitfield. Must update skip info.
Richard Smithcaf33902011-10-10 18:28:20 +00003891 uint64_t BitFieldSize
3892 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003893 GC_IVAR skivar;
3894 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
3895 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3896 + ((BitFieldSize % ByteSizeInBits) != 0);
3897 SkipIvars.push_back(skivar);
3898 } else {
3899 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
3900 // Last field was unnamed. Must update skip info.
3901 unsigned FieldSize
3902 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
3903 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
3904 FieldSize / ByteSizeInBits));
3905 }
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003906 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003907
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003908 if (MaxField)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003909 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003910 MaxUnionIvarSize));
3911 if (MaxSkippedField)
Daniel Dunbar5b743912009-05-03 23:31:46 +00003912 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003913 MaxSkippedUnionIvarSize));
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00003914}
3915
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00003916/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
3917/// the computations and returning the layout bitmap (for ivar or blocks) in
3918/// the given argument BitMap string container. Routine reads
3919/// two containers, IvarsInfo and SkipIvars which are assumed to be
3920/// filled already by the caller.
Chris Lattner9c818332012-02-05 02:30:40 +00003921llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003922 unsigned int WordsToScan, WordsToSkip;
Chris Lattnerece04092012-02-07 00:39:47 +00003923 llvm::Type *PtrTy = CGM.Int8PtrTy;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003924
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003925 // Build the string of skip/scan nibbles
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003926 SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003927 unsigned int WordSize =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003928 CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003929 if (IvarsInfo[0].ivar_bytepos == 0) {
3930 WordsToSkip = 0;
3931 WordsToScan = IvarsInfo[0].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003932 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003933 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3934 WordsToScan = IvarsInfo[0].ivar_size;
3935 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003936 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003937 unsigned int TailPrevGCObjC =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003938 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003939 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003940 // consecutive 'scanned' object pointers.
3941 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003942 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003943 // Skip over 'gc'able object pointer which lay over each other.
3944 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
3945 continue;
3946 // Must skip over 1 or more words. We save current skip/scan values
3947 // and start a new pair.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003948 SKIP_SCAN SkScan;
3949 SkScan.skip = WordsToSkip;
3950 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003951 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003952
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003953 // Skip the hole.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003954 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3955 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003956 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003957 WordsToSkip = 0;
3958 WordsToScan = IvarsInfo[i].ivar_size;
3959 }
3960 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003961 if (WordsToScan > 0) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003962 SKIP_SCAN SkScan;
3963 SkScan.skip = WordsToSkip;
3964 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003965 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003966 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003967
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003968 if (!SkipIvars.empty()) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003969 unsigned int LastIndex = SkipIvars.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003970 int LastByteSkipped =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003971 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003972 LastIndex = IvarsInfo.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003973 int LastByteScanned =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003974 IvarsInfo[LastIndex].ivar_bytepos +
3975 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003976 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramerd20ef752009-12-25 15:43:36 +00003977 if (LastByteSkipped > LastByteScanned) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003978 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003979 SKIP_SCAN SkScan;
3980 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3981 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003982 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003983 }
3984 }
3985 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3986 // as 0xMN.
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003987 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003988 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003989 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3990 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3991 // 0xM0 followed by 0x0N detected.
3992 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
3993 for (int j = i+1; j < SkipScan; j++)
3994 SkipScanIvars[j] = SkipScanIvars[j+1];
3995 --SkipScan;
3996 }
3997 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003998
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003999 // Generate the string.
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004000 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004001 unsigned char byte;
4002 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
4003 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
4004 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
4005 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004006
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004007 // first skip big.
4008 for (unsigned int ix = 0; ix < skip_big; ix++)
4009 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004010
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004011 // next (skip small, scan)
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004012 if (skip_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004013 byte = skip_small << 4;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004014 if (scan_big > 0) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004015 byte |= 0xf;
4016 --scan_big;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004017 } else if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004018 byte |= scan_small;
4019 scan_small = 0;
4020 }
4021 BitMap += byte;
4022 }
4023 // next scan big
4024 for (unsigned int ix = 0; ix < scan_big; ix++)
4025 BitMap += (unsigned char)(0x0f);
4026 // last scan small
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004027 if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004028 byte = scan_small;
4029 BitMap += byte;
4030 }
4031 }
4032 // null terminate string.
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004033 unsigned char zero = 0;
4034 BitMap += zero;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004035
4036 llvm::GlobalVariable * Entry =
4037 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004038 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004039 ((ObjCABI == 2) ?
4040 "__TEXT,__objc_classname,cstring_literals" :
4041 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004042 1, true);
4043 return getConstantGEP(VMContext, Entry, 0, 0);
4044}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004045
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004046/// BuildIvarLayout - Builds ivar layout bitmap for the class
4047/// implementation for the __strong or __weak case.
4048/// The layout map displays which words in ivar list must be skipped
4049/// and which must be scanned by GC (see below). String is built of bytes.
4050/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
4051/// of words to skip and right nibble is count of words to scan. So, each
4052/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
4053/// represented by a 0x00 byte which also ends the string.
4054/// 1. when ForStrongLayout is true, following ivars are scanned:
4055/// - id, Class
4056/// - object *
4057/// - __strong anything
4058///
4059/// 2. When ForStrongLayout is false, following ivars are scanned:
4060/// - __weak anything
4061///
4062llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
4063 const ObjCImplementationDecl *OMD,
4064 bool ForStrongLayout) {
4065 bool hasUnion = false;
4066
Chris Lattnerece04092012-02-07 00:39:47 +00004067 llvm::Type *PtrTy = CGM.Int8PtrTy;
Douglas Gregor79a91412011-09-13 17:21:33 +00004068 if (CGM.getLangOptions().getGC() == LangOptions::NonGC &&
John McCall31168b02011-06-15 23:02:42 +00004069 !CGM.getLangOptions().ObjCAutoRefCount)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004070 return llvm::Constant::getNullValue(PtrTy);
4071
Jordy Rosea91768e2011-07-22 02:08:32 +00004072 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
4073 SmallVector<const FieldDecl*, 32> RecFields;
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004074 if (CGM.getLangOptions().ObjCAutoRefCount) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004075 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004076 IVD; IVD = IVD->getNextIvar())
4077 RecFields.push_back(cast<FieldDecl>(IVD));
4078 }
4079 else {
Jordy Rosea91768e2011-07-22 02:08:32 +00004080 SmallVector<const ObjCIvarDecl*, 32> Ivars;
John McCall31168b02011-06-15 23:02:42 +00004081 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004082
Jordy Rosea91768e2011-07-22 02:08:32 +00004083 // FIXME: This is not ideal; we shouldn't have to do this copy.
4084 RecFields.append(Ivars.begin(), Ivars.end());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004085 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004086
4087 if (RecFields.empty())
4088 return llvm::Constant::getNullValue(PtrTy);
4089
4090 SkipIvars.clear();
4091 IvarsInfo.clear();
4092
4093 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
4094 if (IvarsInfo.empty())
4095 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004096 // Sort on byte position in case we encounterred a union nested in
4097 // the ivar list.
4098 if (hasUnion && !IvarsInfo.empty())
4099 std::sort(IvarsInfo.begin(), IvarsInfo.end());
4100 if (hasUnion && !SkipIvars.empty())
4101 std::sort(SkipIvars.begin(), SkipIvars.end());
4102
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004103 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004104 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004105
4106 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004107 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004108 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar56df9772010-08-17 22:39:59 +00004109 OMD->getClassInterface()->getName().data());
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004110 const unsigned char *s = (unsigned char*)BitMap.c_str();
Bill Wendling53136852012-02-07 09:06:01 +00004111 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004112 if (!(s[i] & 0xf0))
4113 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
4114 else
4115 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
4116 printf("\n");
4117 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004118 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004119}
4120
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004121llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004122 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
4123
Chris Lattner3def9ae2012-02-06 22:16:34 +00004124 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004125 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004126 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004127 llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004128 ((ObjCABI == 2) ?
4129 "__TEXT,__objc_methname,cstring_literals" :
4130 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004131 1, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004132
Owen Anderson170229f2009-07-14 23:10:40 +00004133 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004134}
4135
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004136// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004137llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004138 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
4139}
4140
Daniel Dunbarf5c18462009-04-20 06:54:31 +00004141llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004142 std::string TypeStr;
4143 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
4144
4145 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarb036db82008-08-13 03:21:16 +00004146
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004147 if (!Entry)
4148 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004149 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004150 ((ObjCABI == 2) ?
4151 "__TEXT,__objc_methtype,cstring_literals" :
4152 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004153 1, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004154
Owen Anderson170229f2009-07-14 23:10:40 +00004155 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004156}
4157
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004158llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
4159 bool Extended) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004160 std::string TypeStr;
Bill Wendlinge22bef72012-02-09 22:45:21 +00004161 if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended))
Douglas Gregora9d84932011-05-27 01:19:52 +00004162 return 0;
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004163
4164 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4165
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004166 if (!Entry)
4167 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004168 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004169 ((ObjCABI == 2) ?
4170 "__TEXT,__objc_methtype,cstring_literals" :
4171 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004172 1, true);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004173
Owen Anderson170229f2009-07-14 23:10:40 +00004174 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004175}
4176
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004177// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004178llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004179 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004180
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004181 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004182 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Chris Lattner9c818332012-02-05 02:30:40 +00004183 llvm::ConstantDataArray::getString(VMContext,
4184 Ident->getNameStart()),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004185 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004186 1, true);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004187
Owen Anderson170229f2009-07-14 23:10:40 +00004188 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004189}
4190
4191// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00004192// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004193llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004194CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4195 const Decl *Container) {
Daniel Dunbar4932b362008-08-28 04:38:10 +00004196 std::string TypeStr;
4197 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004198 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4199}
4200
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004201void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004202 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004203 SmallVectorImpl<char> &Name) {
Daniel Dunbard2386812009-10-19 01:21:19 +00004204 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00004205 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00004206 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4207 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004208 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00004209 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer2f569922012-02-07 11:57:45 +00004210 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00004211 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004212}
4213
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004214void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004215 EmitModuleInfo();
4216
Daniel Dunbarc475d422008-10-29 22:36:39 +00004217 // Emit the dummy bodies for any protocols which were referenced but
4218 // never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004219 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerf56501c2009-07-17 23:57:13 +00004220 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4221 if (I->second->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00004222 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004223
Benjamin Kramer22d24c22011-10-15 12:20:02 +00004224 llvm::Constant *Values[5];
Owen Anderson0b75f232009-07-31 20:28:54 +00004225 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004226 Values[1] = GetClassName(I->first);
Owen Anderson0b75f232009-07-31 20:28:54 +00004227 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004228 Values[3] = Values[4] =
Owen Anderson0b75f232009-07-31 20:28:54 +00004229 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004230 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004231 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarc475d422008-10-29 22:36:39 +00004232 Values));
Chris Lattnerf56501c2009-07-17 23:57:13 +00004233 CGM.AddUsedGlobal(I->second);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004234 }
4235
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004236 // Add assembler directives to add lazy undefined symbol references
4237 // for classes which are referenced but not defined. This is
4238 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00004239 //
4240 // FIXME: It would be nice if we had an LLVM construct for this.
4241 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00004242 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00004243 Asm += CGM.getModule().getModuleInlineAsm();
4244 if (!Asm.empty() && Asm.back() != '\n')
4245 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004246
Daniel Dunbard027a922009-09-07 00:20:42 +00004247 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbard027a922009-09-07 00:20:42 +00004248 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4249 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar07d07852009-10-18 21:17:35 +00004250 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4251 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnera299f2c2010-04-17 18:26:20 +00004252 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004253 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnera299f2c2010-04-17 18:26:20 +00004254 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004255 }
4256
Bill Wendling53136852012-02-07 09:06:01 +00004257 for (size_t i = 0, e = DefinedCategoryNames.size(); i < e; ++i) {
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004258 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4259 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4260 }
Chris Lattnera299f2c2010-04-17 18:26:20 +00004261
Daniel Dunbard027a922009-09-07 00:20:42 +00004262 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004263 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004264}
4265
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004266CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004267 : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00004268 ObjCTypes(cgm) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004269 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004270 ObjCABI = 2;
4271}
4272
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004273/* *** */
4274
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004275ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00004276 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(0)
4277{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004278 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4279 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004280
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004281 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004282 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004283 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004284 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Chris Lattnerece04092012-02-07 00:39:47 +00004285 Int8PtrTy = CGM.Int8PtrTy;
4286 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004287
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004288 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004289 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004290 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004291
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004292 // I'm not sure I like this. The implicit coordination is a bit
4293 // gross. We should solve this in a reasonable fashion because this
4294 // is a pretty common task (match some runtime data structure with
4295 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004296
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004297 // FIXME: This is leaked.
4298 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004299
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004300 // struct _objc_super {
4301 // id self;
4302 // Class cls;
4303 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00004304 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00004305 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00004306 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004307 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004308 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith938f40b2011-06-11 17:19:42 +00004309 Ctx.getObjCIdType(), 0, 0, false, false));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004310 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith938f40b2011-06-11 17:19:42 +00004311 Ctx.getObjCClassType(), 0, 0, false, false));
Douglas Gregord5058122010-02-11 01:19:42 +00004312 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004313
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004314 SuperCTy = Ctx.getTagDeclType(RD);
4315 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004316
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004317 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004318 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4319
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004320 // struct _prop_t {
4321 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004322 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004323 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00004324 PropertyTy = llvm::StructType::create("struct._prop_t",
4325 Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004326
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004327 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004328 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004329 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004330 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004331 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004332 PropertyListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004333 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
4334 llvm::ArrayType::get(PropertyTy, 0), NULL);
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004335 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004336 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004337
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004338 // struct _objc_method {
4339 // SEL _cmd;
4340 // char *method_type;
4341 // char *_imp;
4342 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00004343 MethodTy = llvm::StructType::create("struct._objc_method",
4344 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
4345 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004346
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004347 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00004348 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00004349 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00004350
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004351}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004352
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004353ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004354 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004355 // struct _objc_method_description {
4356 // SEL name;
4357 // char *types;
4358 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004359 MethodDescriptionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004360 llvm::StructType::create("struct._objc_method_description",
4361 SelectorPtrTy, Int8PtrTy, NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004362
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004363 // struct _objc_method_description_list {
4364 // int count;
4365 // struct _objc_method_description[1];
4366 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004367 MethodDescriptionListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004368 llvm::StructType::create("struct._objc_method_description_list",
4369 IntTy,
4370 llvm::ArrayType::get(MethodDescriptionTy, 0),NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004371
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004372 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004373 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004374 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004375
Daniel Dunbarb036db82008-08-13 03:21:16 +00004376 // Protocol description structures
4377
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004378 // struct _objc_protocol_extension {
4379 // uint32_t size; // sizeof(struct _objc_protocol_extension)
4380 // struct _objc_method_description_list *optional_instance_methods;
4381 // struct _objc_method_description_list *optional_class_methods;
4382 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004383 // const char ** extendedMethodTypes;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004384 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004385 ProtocolExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004386 llvm::StructType::create("struct._objc_protocol_extension",
4387 IntTy, MethodDescriptionListPtrTy,
4388 MethodDescriptionListPtrTy, PropertyListPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004389 Int8PtrPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004390
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004391 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004392 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004393
Daniel Dunbarc475d422008-10-29 22:36:39 +00004394 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00004395
Chris Lattnera5f58b02011-07-09 17:41:47 +00004396 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004397 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00004398
Chris Lattnera5f58b02011-07-09 17:41:47 +00004399 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004400 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattnera5f58b02011-07-09 17:41:47 +00004401 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004402 LongTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00004403 llvm::ArrayType::get(ProtocolTy, 0),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004404 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004405
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004406 // struct _objc_protocol {
4407 // struct _objc_protocol_extension *isa;
4408 // char *protocol_name;
4409 // struct _objc_protocol **_objc_protocol_list;
4410 // struct _objc_method_description_list *instance_methods;
4411 // struct _objc_method_description_list *class_methods;
4412 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004413 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
4414 llvm::PointerType::getUnqual(ProtocolListTy),
4415 MethodDescriptionListPtrTy,
4416 MethodDescriptionListPtrTy,
4417 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004418
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004419 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004420 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004421
Owen Anderson9793f0e2009-07-29 22:16:19 +00004422 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004423
4424 // Class description structures
4425
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004426 // struct _objc_ivar {
4427 // char *ivar_name;
4428 // char *ivar_type;
4429 // int ivar_offset;
4430 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00004431 IvarTy = llvm::StructType::create("struct._objc_ivar",
4432 Int8PtrTy, Int8PtrTy, IntTy, NULL);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004433
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004434 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00004435 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004436 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00004437 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004438
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004439 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00004440 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004441 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00004442 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004443
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004444 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004445 ClassExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004446 llvm::StructType::create("struct._objc_class_extension",
4447 IntTy, Int8PtrTy, PropertyListPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004448 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004449
Chris Lattner5ec04a52011-08-12 17:43:31 +00004450 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004451
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004452 // struct _objc_class {
4453 // Class isa;
4454 // Class super_class;
4455 // char *name;
4456 // long version;
4457 // long info;
4458 // long instance_size;
4459 // struct _objc_ivar_list *ivars;
4460 // struct _objc_method_list *methods;
4461 // struct _objc_cache *cache;
4462 // struct _objc_protocol_list *protocols;
4463 // char *ivar_layout;
4464 // struct _objc_class_ext *ext;
4465 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00004466 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
4467 llvm::PointerType::getUnqual(ClassTy),
4468 Int8PtrTy,
4469 LongTy,
4470 LongTy,
4471 LongTy,
4472 IvarListPtrTy,
4473 MethodListPtrTy,
4474 CachePtrTy,
4475 ProtocolListPtrTy,
4476 Int8PtrTy,
4477 ClassExtensionPtrTy,
4478 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004479
Owen Anderson9793f0e2009-07-29 22:16:19 +00004480 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004481
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004482 // struct _objc_category {
4483 // char *category_name;
4484 // char *class_name;
4485 // struct _objc_method_list *instance_method;
4486 // struct _objc_method_list *class_method;
4487 // uint32_t size; // sizeof(struct _objc_category)
4488 // struct _objc_property_list *instance_properties;// category's @property
4489 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004490 CategoryTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004491 llvm::StructType::create("struct._objc_category",
4492 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
4493 MethodListPtrTy, ProtocolListPtrTy,
4494 IntTy, PropertyListPtrTy, NULL);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004495
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004496 // Global metadata structures
4497
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004498 // struct _objc_symtab {
4499 // long sel_ref_cnt;
4500 // SEL *refs;
4501 // short cls_def_cnt;
4502 // short cat_def_cnt;
4503 // char *defs[cls_def_cnt + cat_def_cnt];
4504 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004505 SymtabTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004506 llvm::StructType::create("struct._objc_symtab",
4507 LongTy, SelectorPtrTy, ShortTy, ShortTy,
4508 llvm::ArrayType::get(Int8PtrTy, 0), NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004509 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004510
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00004511 // struct _objc_module {
4512 // long version;
4513 // long size; // sizeof(struct _objc_module)
4514 // char *name;
4515 // struct _objc_symtab* symtab;
4516 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004517 ModuleTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004518 llvm::StructType::create("struct._objc_module",
4519 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, NULL);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00004520
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004521
Mike Stump18bb9282009-05-16 07:57:57 +00004522 // FIXME: This is the size of the setjmp buffer and should be target
4523 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00004524 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004525
Anders Carlsson9ff22482008-09-09 10:10:21 +00004526 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00004527 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004528
4529 ExceptionDataTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004530 llvm::StructType::create("struct._objc_exception_data",
Chris Lattnerece04092012-02-07 00:39:47 +00004531 llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
4532 StackPtrTy, NULL);
Anders Carlsson9ff22482008-09-09 10:10:21 +00004533
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00004534}
4535
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004536ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004537 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004538 // struct _method_list_t {
4539 // uint32_t entsize; // sizeof(struct _objc_method)
4540 // uint32_t method_count;
4541 // struct _objc_method method_list[method_count];
4542 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004543 MethodListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004544 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
4545 llvm::ArrayType::get(MethodTy, 0), NULL);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004546 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004547 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004548
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004549 // struct _protocol_t {
4550 // id isa; // NULL
4551 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004552 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004553 // const struct method_list_t * const instance_methods;
4554 // const struct method_list_t * const class_methods;
4555 // const struct method_list_t *optionalInstanceMethods;
4556 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004557 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004558 // const uint32_t size; // sizeof(struct _protocol_t)
4559 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004560 // const char ** extendedMethodTypes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004561 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004562
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004563 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00004564 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004565 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004566
Chris Lattnera5f58b02011-07-09 17:41:47 +00004567 ProtocolnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004568 llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
4569 llvm::PointerType::getUnqual(ProtocolListnfABITy),
4570 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
4571 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004572 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
4573 NULL);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004574
4575 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004576 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004577
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004578 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004579 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004580 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004581 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004582 ProtocolListnfABITy->setBody(LongTy,
4583 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
4584 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004585
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004586 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004587 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004588
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004589 // struct _ivar_t {
4590 // unsigned long int *offset; // pointer to ivar offset location
4591 // char *name;
4592 // char *type;
4593 // uint32_t alignment;
4594 // uint32_t size;
4595 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004596 IvarnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004597 llvm::StructType::create("struct._ivar_t",
4598 llvm::PointerType::getUnqual(LongTy),
4599 Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004600
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004601 // struct _ivar_list_t {
4602 // uint32 entsize; // sizeof(struct _ivar_t)
4603 // uint32 count;
4604 // struct _iver_t list[count];
4605 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00004606 IvarListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004607 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
4608 llvm::ArrayType::get(IvarnfABITy, 0), NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004609
Owen Anderson9793f0e2009-07-29 22:16:19 +00004610 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004611
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004612 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004613 // uint32_t const flags;
4614 // uint32_t const instanceStart;
4615 // uint32_t const instanceSize;
4616 // uint32_t const reserved; // only when building for 64bit targets
4617 // const uint8_t * const ivarLayout;
4618 // const char *const name;
4619 // const struct _method_list_t * const baseMethods;
4620 // const struct _objc_protocol_list *const baseProtocols;
4621 // const struct _ivar_list_t *const ivars;
4622 // const uint8_t * const weakIvarLayout;
4623 // const struct _prop_list_t * const properties;
4624 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004625
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004626 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattner5ec04a52011-08-12 17:43:31 +00004627 ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
4628 IntTy, IntTy, IntTy, Int8PtrTy,
4629 Int8PtrTy, MethodListnfABIPtrTy,
4630 ProtocolListnfABIPtrTy,
4631 IvarListnfABIPtrTy,
4632 Int8PtrTy, PropertyListPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004633
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004634 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00004635 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00004636 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
4637 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004638
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004639 // struct _class_t {
4640 // struct _class_t *isa;
4641 // struct _class_t * const superclass;
4642 // void *cache;
4643 // IMP *vtable;
4644 // struct class_ro_t *ro;
4645 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004646
Chris Lattner5ec04a52011-08-12 17:43:31 +00004647 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00004648 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
4649 llvm::PointerType::getUnqual(ClassnfABITy),
4650 CachePtrTy,
4651 llvm::PointerType::getUnqual(ImpnfABITy),
4652 llvm::PointerType::getUnqual(ClassRonfABITy),
4653 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004654
Fariborz Jahanian71394042009-01-23 23:53:38 +00004655 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004656 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004657
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004658 // struct _category_t {
4659 // const char * const name;
4660 // struct _class_t *const cls;
4661 // const struct _method_list_t * const instance_methods;
4662 // const struct _method_list_t * const class_methods;
4663 // const struct _protocol_list_t * const protocols;
4664 // const struct _prop_list_t * const properties;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00004665 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00004666 CategorynfABITy = llvm::StructType::create("struct._category_t",
4667 Int8PtrTy, ClassnfABIPtrTy,
4668 MethodListnfABIPtrTy,
4669 MethodListnfABIPtrTy,
4670 ProtocolListnfABIPtrTy,
4671 PropertyListPtrTy,
4672 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004673
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004674 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004675 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4676 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004677
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004678 // MessageRefTy - LLVM for:
4679 // struct _message_ref_t {
4680 // IMP messenger;
4681 // SEL name;
4682 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004683
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004684 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00004685 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00004686 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00004687 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004688 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004689 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith938f40b2011-06-11 17:19:42 +00004690 Ctx.VoidPtrTy, 0, 0, false, false));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004691 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith938f40b2011-06-11 17:19:42 +00004692 Ctx.getObjCSelType(), 0, 0, false, false));
Douglas Gregord5058122010-02-11 01:19:42 +00004693 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004694
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004695 MessageRefCTy = Ctx.getTagDeclType(RD);
4696 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4697 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004698
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004699 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004700 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004701
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004702 // SuperMessageRefTy - LLVM for:
4703 // struct _super_message_ref_t {
4704 // SUPER_IMP messenger;
4705 // SEL name;
4706 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00004707 SuperMessageRefTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004708 llvm::StructType::create("struct._super_message_ref_t",
4709 ImpnfABITy, SelectorPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004710
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004711 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004712 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00004713
Daniel Dunbarb1559a42009-03-01 04:46:24 +00004714
4715 // struct objc_typeinfo {
4716 // const void** vtable; // objc_ehtype_vtable + 2
4717 // const char* name; // c++ typeinfo string
4718 // Class cls;
4719 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00004720 EHTypeTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00004721 llvm::StructType::create("struct._objc_typeinfo",
4722 llvm::PointerType::getUnqual(Int8PtrTy),
4723 Int8PtrTy, ClassnfABIPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004724 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00004725}
4726
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004727llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004728 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004729
Fariborz Jahanian71394042009-01-23 23:53:38 +00004730 return NULL;
4731}
4732
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00004733void CGObjCNonFragileABIMac::
4734AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
4735 const char *SymbolName,
4736 const char *SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00004737 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004738
Daniel Dunbar19573e72009-05-15 21:48:48 +00004739 if (!NumClasses)
4740 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004741
Chris Lattner3def9ae2012-02-06 22:16:34 +00004742 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00004743 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00004744 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00004745 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00004746 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004747 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00004748 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00004749 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004750
Daniel Dunbar19573e72009-05-15 21:48:48 +00004751 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00004752 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004753 llvm::GlobalValue::InternalLinkage,
4754 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00004755 SymbolName);
Daniel Dunbar710cb202010-04-25 20:39:32 +00004756 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00004757 GV->setSection(SectionName);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004758 CGM.AddUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00004759}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004760
Fariborz Jahanian71394042009-01-23 23:53:38 +00004761void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4762 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004763
Daniel Dunbar19573e72009-05-15 21:48:48 +00004764 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00004765 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004766 AddModuleClassList(DefinedClasses,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004767 "\01L_OBJC_LABEL_CLASS_$",
4768 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahanian67260552009-11-17 21:37:35 +00004769
Bill Wendling53136852012-02-07 09:06:01 +00004770 for (unsigned i = 0, e = DefinedClasses.size(); i < e; i++) {
Fariborz Jahanian67260552009-11-17 21:37:35 +00004771 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
4772 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4773 continue;
4774 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahanian67260552009-11-17 21:37:35 +00004775 }
4776
Bill Wendling53136852012-02-07 09:06:01 +00004777 for (unsigned i = 0, e = DefinedMetaClasses.size(); i < e; i++) {
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004778 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
4779 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4780 continue;
4781 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4782 }
Fariborz Jahanian67260552009-11-17 21:37:35 +00004783
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004784 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004785 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4786 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004787
Fariborz Jahanian279abd32009-01-30 20:55:31 +00004788 // Build list of all implemented category addresses in array
4789 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004790 AddModuleClassList(DefinedCategories,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004791 "\01L_OBJC_LABEL_CATEGORY_$",
4792 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004793 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004794 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4795 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004796
Daniel Dunbar5e639272010-04-25 20:39:01 +00004797 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00004798}
4799
John McCall9e8bb002011-05-14 03:10:52 +00004800/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
4801/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004802/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004803/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00004804bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
4805 // At various points we've experimented with using vtable-based
4806 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004807 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004808 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00004809 return false;
John McCall9e8bb002011-05-14 03:10:52 +00004810 case CodeGenOptions::NonLegacy:
4811 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004812 case CodeGenOptions::Mixed:
4813 break;
4814 }
4815
4816 // If so, see whether this selector is in the white-list of things which must
4817 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00004818 if (VTableDispatchMethods.empty()) {
4819 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
4820 VTableDispatchMethods.insert(GetNullarySelector("class"));
4821 VTableDispatchMethods.insert(GetNullarySelector("self"));
4822 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
4823 VTableDispatchMethods.insert(GetNullarySelector("length"));
4824 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004825
John McCall9e8bb002011-05-14 03:10:52 +00004826 // These are vtable-based if GC is disabled.
4827 // Optimistically use vtable dispatch for hybrid compiles.
Douglas Gregor79a91412011-09-13 17:21:33 +00004828 if (CGM.getLangOptions().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00004829 VTableDispatchMethods.insert(GetNullarySelector("retain"));
4830 VTableDispatchMethods.insert(GetNullarySelector("release"));
4831 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
4832 }
4833
4834 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
4835 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
4836 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
4837 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
4838 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
4839 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
4840 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
4841
4842 // These are vtable-based if GC is enabled.
4843 // Optimistically use vtable dispatch for hybrid compiles.
Douglas Gregor79a91412011-09-13 17:21:33 +00004844 if (CGM.getLangOptions().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00004845 VTableDispatchMethods.insert(GetNullarySelector("hash"));
4846 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
4847
4848 // "countByEnumeratingWithState:objects:count"
4849 IdentifierInfo *KeyIdents[] = {
4850 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
4851 &CGM.getContext().Idents.get("objects"),
4852 &CGM.getContext().Idents.get("count")
4853 };
4854 VTableDispatchMethods.insert(
4855 CGM.getContext().Selectors.getSelector(3, KeyIdents));
4856 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004857 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004858
John McCall9e8bb002011-05-14 03:10:52 +00004859 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004860}
4861
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004862// Metadata flags
4863enum MetaDataDlags {
4864 CLS = 0x0,
4865 CLS_META = 0x1,
4866 CLS_ROOT = 0x2,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004867 OBJC2_CLS_HIDDEN = 0x10,
John McCall31168b02011-06-15 23:02:42 +00004868 CLS_EXCEPTION = 0x20,
4869
4870 /// (Obsolete) ARC-specific: this class has a .release_ivars method
4871 CLS_HAS_IVAR_RELEASER = 0x40,
4872 /// class was compiled with -fobjc-arr
4873 CLS_COMPILED_BY_ARC = 0x80 // (1<<7)
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004874};
4875/// BuildClassRoTInitializer - generate meta-data for:
4876/// struct _class_ro_t {
4877/// uint32_t const flags;
4878/// uint32_t const instanceStart;
4879/// uint32_t const instanceSize;
4880/// uint32_t const reserved; // only when building for 64bit targets
4881/// const uint8_t * const ivarLayout;
4882/// const char *const name;
4883/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004884/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004885/// const struct _ivar_list_t *const ivars;
4886/// const uint8_t * const weakIvarLayout;
4887/// const struct _prop_list_t * const properties;
4888/// }
4889///
4890llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004891 unsigned flags,
4892 unsigned InstanceStart,
4893 unsigned InstanceSize,
4894 const ObjCImplementationDecl *ID) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004895 std::string ClassName = ID->getNameAsString();
Benjamin Kramer22d24c22011-10-15 12:20:02 +00004896 llvm::Constant *Values[10]; // 11 for 64bit targets!
John McCall31168b02011-06-15 23:02:42 +00004897
4898 if (CGM.getLangOptions().ObjCAutoRefCount)
4899 flags |= CLS_COMPILED_BY_ARC;
4900
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004901 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4902 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
4903 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004904 // FIXME. For 64bit targets add 0 here.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004905 Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4906 : BuildIvarLayout(ID, true);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004907 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004908 // const struct _method_list_t * const baseMethods;
4909 std::vector<llvm::Constant*> Methods;
4910 std::string MethodListName("\01l_OBJC_$_");
4911 if (flags & CLS_META) {
4912 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004913 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004914 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004915 // Class methods should always be defined.
4916 Methods.push_back(GetMethodConstant(*i));
4917 }
4918 } else {
4919 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004920 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004921 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004922 // Instance methods should always be defined.
4923 Methods.push_back(GetMethodConstant(*i));
4924 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004925 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004926 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004927 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004928
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004929 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4930 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004931
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004932 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
4933 if (llvm::Constant *C = GetMethodConstant(MD))
4934 Methods.push_back(C);
4935 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
4936 if (llvm::Constant *C = GetMethodConstant(MD))
4937 Methods.push_back(C);
4938 }
4939 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004940 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004941 Values[ 5] = EmitMethodList(MethodListName,
4942 "__DATA, __objc_const", Methods);
4943
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004944 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4945 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004946 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00004947 + OID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00004948 OID->all_referenced_protocol_begin(),
4949 OID->all_referenced_protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004950
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00004951 if (flags & CLS_META)
Owen Anderson0b75f232009-07-31 20:28:54 +00004952 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00004953 else
4954 Values[ 7] = EmitIvarList(ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004955 Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4956 : BuildIvarLayout(ID, false);
Fariborz Jahanian066347e2009-01-28 22:18:42 +00004957 if (flags & CLS_META)
Owen Anderson0b75f232009-07-31 20:28:54 +00004958 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian066347e2009-01-28 22:18:42 +00004959 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00004960 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4961 ID, ID->getClassInterface(), ObjCTypes);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004962 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004963 Values);
4964 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004965 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
4966 llvm::GlobalValue::InternalLinkage,
4967 Init,
4968 (flags & CLS_META) ?
4969 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
4970 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00004971 CLASS_RO_GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00004972 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00004973 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004974 return CLASS_RO_GV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00004975
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004976}
4977
4978/// BuildClassMetaData - This routine defines that to-level meta-data
4979/// for the given ClassName for:
4980/// struct _class_t {
4981/// struct _class_t *isa;
4982/// struct _class_t * const superclass;
4983/// void *cache;
4984/// IMP *vtable;
4985/// struct class_ro_t *ro;
4986/// }
4987///
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004988llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004989 std::string &ClassName,
4990 llvm::Constant *IsAGV,
4991 llvm::Constant *SuperClassGV,
4992 llvm::Constant *ClassRoGV,
4993 bool HiddenVisibility) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00004994 llvm::Constant *Values[] = {
4995 IsAGV,
4996 SuperClassGV,
4997 ObjCEmptyCacheVar, // &ObjCEmptyCacheVar
4998 ObjCEmptyVtableVar, // &ObjCEmptyVtableVar
4999 ClassRoGV // &CLASS_RO_GV
5000 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005001 if (!Values[1])
5002 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005003 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005004 Values);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005005 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
5006 GV->setInitializer(Init);
Fariborz Jahanian04087232009-01-31 01:07:39 +00005007 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005008 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005009 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian82208252009-01-31 00:59:10 +00005010 if (HiddenVisibility)
5011 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005012 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005013}
5014
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005015bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00005016CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005017 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005018}
5019
Daniel Dunbar961202372009-05-03 12:57:56 +00005020void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00005021 uint32_t &InstanceStart,
5022 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005023 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00005024 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005025
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005026 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00005027 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005028
5029 // If there are no fields, the start is the same as the end.
5030 if (!RL.getFieldCount())
5031 InstanceStart = InstanceSize;
5032 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00005033 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00005034}
5035
Fariborz Jahanian71394042009-01-23 23:53:38 +00005036void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
5037 std::string ClassName = ID->getNameAsString();
5038 if (!ObjCEmptyCacheVar) {
5039 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005040 CGM.getModule(),
5041 ObjCTypes.CacheTy,
5042 false,
5043 llvm::GlobalValue::ExternalLinkage,
5044 0,
5045 "_objc_empty_cache");
5046
Fariborz Jahanian71394042009-01-23 23:53:38 +00005047 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005048 CGM.getModule(),
5049 ObjCTypes.ImpnfABITy,
5050 false,
5051 llvm::GlobalValue::ExternalLinkage,
5052 0,
5053 "_objc_empty_vtable");
Fariborz Jahanian71394042009-01-23 23:53:38 +00005054 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005055 assert(ID->getClassInterface() &&
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005056 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00005057 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005058 uint32_t InstanceStart =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005059 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005060 uint32_t InstanceSize = InstanceStart;
5061 uint32_t flags = CLS_META;
Daniel Dunbar15894b72009-04-07 05:48:37 +00005062 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
5063 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005064
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005065 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005066
5067 bool classIsHidden =
John McCall457a04e2010-10-22 21:05:15 +00005068 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005069 if (classIsHidden)
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005070 flags |= OBJC2_CLS_HIDDEN;
John McCall31168b02011-06-15 23:02:42 +00005071 if (ID->hasCXXStructors())
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00005072 flags |= eClassFlags_ABI2_HasCXXStructors;
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005073 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005074 // class is root
5075 flags |= CLS_ROOT;
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005076 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005077 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005078 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005079 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005080 const ObjCInterfaceDecl *Root = ID->getClassInterface();
5081 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
5082 Root = Super;
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005083 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005084 if (Root->isWeakImported())
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005085 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005086 // work on super class metadata symbol.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005087 std::string SuperClassName =
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005088 ObjCMetaClassName +
5089 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005090 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005091 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00005092 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005093 }
5094 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
5095 InstanceStart,
5096 InstanceSize,ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005097 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005098 llvm::GlobalVariable *MetaTClass =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005099 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
5100 classIsHidden);
Fariborz Jahanian67260552009-11-17 21:37:35 +00005101 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00005102
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005103 // Metadata for the class
5104 flags = CLS;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005105 if (classIsHidden)
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005106 flags |= OBJC2_CLS_HIDDEN;
John McCall31168b02011-06-15 23:02:42 +00005107 if (ID->hasCXXStructors())
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00005108 flags |= eClassFlags_ABI2_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005109
Douglas Gregor78bd61f2009-06-18 16:11:24 +00005110 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005111 flags |= CLS_EXCEPTION;
5112
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005113 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005114 flags |= CLS_ROOT;
5115 SuperClassGV = 0;
Chris Lattnerb433b272009-04-19 06:02:28 +00005116 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005117 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005118 std::string RootClassName =
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005119 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005120 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005121 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00005122 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005123 }
Daniel Dunbar961202372009-05-03 12:57:56 +00005124 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005125 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005126 InstanceStart,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005127 InstanceSize,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005128 ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005129
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005130 TClassName = ObjCClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005131 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005132 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5133 classIsHidden);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005134 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005135
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005136 // Determine if this class is also "non-lazy".
5137 if (ImplementationIsNonLazy(ID))
5138 DefinedNonLazyClasses.push_back(ClassMD);
5139
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005140 // Force the definition of the EHType if necessary.
5141 if (flags & CLS_EXCEPTION)
5142 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005143 // Make sure method definition entries are all clear for next implementation.
5144 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005145}
5146
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005147/// GenerateProtocolRef - This routine is called to generate code for
5148/// a protocol reference expression; as in:
5149/// @code
5150/// @protocol(Proto1);
5151/// @endcode
5152/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5153/// which will hold address of the protocol meta-data.
5154///
5155llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005156 const ObjCProtocolDecl *PD) {
5157
Fariborz Jahanian464423d2009-04-10 18:47:34 +00005158 // This routine is called for @protocol only. So, we must build definition
5159 // of protocol's meta-data (not a reference to it!)
5160 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005161 llvm::Constant *Init =
5162 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00005163 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005164
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005165 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar56df9772010-08-17 22:39:59 +00005166 ProtocolName += PD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005167
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005168 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5169 if (PTGV)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005170 return Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005171 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005172 CGM.getModule(),
5173 Init->getType(), false,
5174 llvm::GlobalValue::WeakAnyLinkage,
5175 Init,
5176 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005177 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5178 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005179 CGM.AddUsedGlobal(PTGV);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005180 return Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005181}
5182
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005183/// GenerateCategory - Build metadata for a category implementation.
5184/// struct _category_t {
5185/// const char * const name;
5186/// struct _class_t *const cls;
5187/// const struct _method_list_t * const instance_methods;
5188/// const struct _method_list_t * const class_methods;
5189/// const struct _protocol_list_t * const protocols;
5190/// const struct _prop_list_t * const properties;
5191/// }
5192///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005193void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005194 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005195 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005196 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5197 "_$_" + OCD->getNameAsString());
5198 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar15894b72009-04-07 05:48:37 +00005199 Interface->getNameAsString());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005200
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005201 llvm::Constant *Values[6];
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005202 Values[0] = GetClassName(OCD->getIdentifier());
5203 // meta-class entry symbol
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005204 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005205 if (Interface->isWeakImported())
Fariborz Jahanian3ad8dcf2009-11-17 22:02:21 +00005206 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5207
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005208 Values[1] = ClassGV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005209 std::vector<llvm::Constant*> Methods;
5210 std::string MethodListName(Prefix);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005211 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005212 "_$_" + OCD->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005213
5214 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005215 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005216 // Instance methods should always be defined.
5217 Methods.push_back(GetMethodConstant(*i));
5218 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005219
5220 Values[2] = EmitMethodList(MethodListName,
5221 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005222 Methods);
5223
5224 MethodListName = Prefix;
5225 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5226 OCD->getNameAsString();
5227 Methods.clear();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005228 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005229 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005230 // Class methods should always be defined.
5231 Methods.push_back(GetMethodConstant(*i));
5232 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005233
5234 Values[3] = EmitMethodList(MethodListName,
5235 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005236 Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005237 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00005238 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005239 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005240 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005241 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5242 << OCD->getName();
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005243 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005244 + Interface->getName() + "_$_"
5245 + Category->getName(),
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005246 Category->protocol_begin(),
5247 Category->protocol_end());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005248 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5249 OCD, Category, ObjCTypes);
Mike Stump658fe022009-07-30 22:28:39 +00005250 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00005251 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5252 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005253 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005254
5255 llvm::Constant *Init =
5256 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005257 Values);
5258 llvm::GlobalVariable *GCATV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005259 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005260 false,
5261 llvm::GlobalValue::InternalLinkage,
5262 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005263 ExtCatName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005264 GCATV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005265 CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005266 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005267 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005268 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005269
5270 // Determine if this category is also "non-lazy".
5271 if (ImplementationIsNonLazy(OCD))
5272 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005273 // method definition entries must be clear for next implementation.
5274 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005275}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005276
5277/// GetMethodConstant - Return a struct objc_method constant for the
5278/// given method if it has been defined. The result is null if the
5279/// method has not been defined. The return value has type MethodPtrTy.
5280llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005281 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005282 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005283 if (!Fn)
5284 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005285
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005286 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00005287 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005288 ObjCTypes.SelectorPtrTy),
5289 GetMethodVarType(MD),
5290 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
5291 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00005292 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005293}
5294
5295/// EmitMethodList - Build meta-data for method declarations
5296/// struct _method_list_t {
5297/// uint32_t entsize; // sizeof(struct _objc_method)
5298/// uint32_t method_count;
5299/// struct _objc_method method_list[method_count];
5300/// }
5301///
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00005302llvm::Constant *
5303CGObjCNonFragileABIMac::EmitMethodList(Twine Name,
5304 const char *Section,
5305 ArrayRef<llvm::Constant*> Methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005306 // Return null for empty list.
5307 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005308 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005309
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005310 llvm::Constant *Values[3];
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005311 // sizeof(struct _objc_method)
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005312 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005313 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005314 // method_count
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005315 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005316 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005317 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005318 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005319 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005320
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005321 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005322 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005323 llvm::GlobalValue::InternalLinkage, Init, Name);
5324 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005325 GV->setSection(Section);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005326 CGM.AddUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005327 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005328}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005329
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005330/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5331/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005332llvm::GlobalVariable *
5333CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5334 const ObjCIvarDecl *Ivar) {
5335 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar3f86b9c2009-05-05 00:36:57 +00005336 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregorbcced4e2009-04-09 21:40:53 +00005337 '.' + Ivar->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005338 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005339 CGM.getModule().getGlobalVariable(Name);
5340 if (!IvarOffsetGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005341 IvarOffsetGV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005342 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005343 false,
5344 llvm::GlobalValue::ExternalLinkage,
5345 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005346 Name);
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005347 return IvarOffsetGV;
5348}
5349
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005350llvm::Constant *
5351CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5352 const ObjCIvarDecl *Ivar,
5353 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005354 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005355 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005356 Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005357 IvarOffsetGV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005358 CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005359
Mike Stump18bb9282009-05-16 07:57:57 +00005360 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
5361 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005362 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5363 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall457a04e2010-10-22 21:05:15 +00005364 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00005365 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00005366 else
Fariborz Jahanianbc3c77b2009-04-06 18:30:00 +00005367 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendlingf7d45982011-05-04 21:37:25 +00005368 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005369 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005370}
5371
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005372/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005373/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005374/// IvarListnfABIPtrTy.
5375/// struct _ivar_t {
5376/// unsigned long int *offset; // pointer to ivar offset location
5377/// char *name;
5378/// char *type;
5379/// uint32_t alignment;
5380/// uint32_t size;
5381/// }
5382/// struct _ivar_list_t {
5383/// uint32 entsize; // sizeof(struct _ivar_t)
5384/// uint32 count;
5385/// struct _iver_t list[count];
5386/// }
5387///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005388
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005389llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005390 const ObjCImplementationDecl *ID) {
5391
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005392 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005393
Jordy Rosea91768e2011-07-22 02:08:32 +00005394 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005395 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005396
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005397 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005398
Jordy Rosea91768e2011-07-22 02:08:32 +00005399 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00005400 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00005401 // Ignore unnamed bit-fields.
5402 if (!IVD->getDeclName())
5403 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005404 llvm::Constant *Ivar[5];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005405 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar961202372009-05-03 12:57:56 +00005406 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005407 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5408 Ivar[2] = GetMethodVarType(IVD);
Chris Lattner2192fe52011-07-18 04:24:23 +00005409 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005410 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005411 unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005412 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005413 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005414 Align = llvm::Log2_32(Align);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005415 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00005416 // NOTE. Size of a bitfield does not match gcc's, because of the
5417 // way bitfields are treated special in each. But I am told that
5418 // 'size' for bitfield ivars is ignored by the runtime so it does
5419 // not matter. If it matters, there is enough info to get the
5420 // bitfield right!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005421 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005422 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005423 }
5424 // Return null for empty list.
5425 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005426 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005427
5428 llvm::Constant *Values[3];
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005429 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005430 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5431 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005432 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005433 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005434 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005435 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005436 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5437 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005438 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005439 llvm::GlobalValue::InternalLinkage,
5440 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005441 Prefix + OID->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005442 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005443 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005444 GV->setSection("__DATA, __objc_const");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005445
Chris Lattnerf56501c2009-07-17 23:57:13 +00005446 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00005447 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005448}
5449
5450llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005451 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005452 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005453
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005454 if (!Entry) {
5455 // We use the initializer as a marker of whether this is a forward
5456 // reference or not. At module finalization we add the empty
5457 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005458 Entry =
5459 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5460 llvm::GlobalValue::ExternalLinkage,
5461 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005462 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005463 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005464 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005465
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005466 return Entry;
5467}
5468
5469/// GetOrEmitProtocol - Generate the protocol meta-data:
5470/// @code
5471/// struct _protocol_t {
5472/// id isa; // NULL
5473/// const char * const protocol_name;
5474/// const struct _protocol_list_t * protocol_list; // super protocols
5475/// const struct method_list_t * const instance_methods;
5476/// const struct method_list_t * const class_methods;
5477/// const struct method_list_t *optionalInstanceMethods;
5478/// const struct method_list_t *optionalClassMethods;
5479/// const struct _prop_list_t * properties;
5480/// const uint32_t size; // sizeof(struct _protocol_t)
5481/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005482/// const char ** extendedMethodTypes;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005483/// }
5484/// @endcode
5485///
5486
5487llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005488 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005489 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005490
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005491 // Early exit if a defining object has already been generated.
5492 if (Entry && Entry->hasInitializer())
5493 return Entry;
5494
Douglas Gregora715bff2012-01-01 19:51:50 +00005495 // Use the protocol definition, if there is one.
5496 if (const ObjCProtocolDecl *Def = PD->getDefinition())
5497 PD = Def;
5498
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005499 // Construct method lists.
5500 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5501 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005502 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005503 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005504 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005505 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005506 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00005507 if (!C)
5508 return GetOrEmitProtocolRef(PD);
5509
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005510 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5511 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005512 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005513 } else {
5514 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005515 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005516 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005517 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005518
5519 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005520 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005521 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005522 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00005523 if (!C)
5524 return GetOrEmitProtocolRef(PD);
5525
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005526 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5527 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005528 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005529 } else {
5530 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005531 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005532 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005533 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005534
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005535 MethodTypesExt.insert(MethodTypesExt.end(),
5536 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
5537
5538 llvm::Constant *Values[11];
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005539 // isa is NULL
Owen Anderson0b75f232009-07-31 20:28:54 +00005540 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005541 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005542 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5543 PD->protocol_begin(),
5544 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005545
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005546 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005547 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005548 "__DATA, __objc_const",
5549 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005550 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005551 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005552 "__DATA, __objc_const",
5553 ClassMethods);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005554 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005555 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005556 "__DATA, __objc_const",
5557 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005558 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005559 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005560 "__DATA, __objc_const",
5561 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005562 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005563 0, PD, ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005564 uint32_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005565 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005566 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0b75f232009-07-31 20:28:54 +00005567 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005568 Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
5569 + PD->getName(),
5570 MethodTypesExt, ObjCTypes);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005571 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005572 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005573
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005574 if (Entry) {
5575 // Already created, fix the linkage and update the initializer.
Mike Stumpa6ca3342009-03-07 16:33:28 +00005576 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005577 Entry->setInitializer(Init);
5578 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005579 Entry =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005580 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
5581 false, llvm::GlobalValue::WeakAnyLinkage, Init,
5582 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005583 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005584 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005585 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005586 }
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005587 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005588 CGM.AddUsedGlobal(Entry);
5589
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005590 // Use this protocol meta-data to build protocol list table in section
5591 // __DATA, __objc_protolist
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005592 llvm::GlobalVariable *PTGV =
5593 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
5594 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
5595 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005596 PTGV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005597 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbarb25452a2009-04-15 02:56:18 +00005598 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005599 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005600 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005601 return Entry;
5602}
5603
5604/// EmitProtocolList - Generate protocol list meta-data:
5605/// @code
5606/// struct _protocol_list_t {
5607/// long protocol_count; // Note, this is 32/64 bit
5608/// struct _protocol_t[protocol_count];
5609/// }
5610/// @endcode
5611///
5612llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005613CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005614 ObjCProtocolDecl::protocol_iterator begin,
5615 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendlinga515b582012-02-09 22:16:49 +00005616 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005617
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005618 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005619 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00005620 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005621
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005622 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005623 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005624 Name.toVector(TmpName);
5625 llvm::GlobalVariable *GV =
5626 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005627 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005628 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005629
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005630 for (; begin != end; ++begin)
5631 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
5632
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005633 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00005634 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005635 ObjCTypes.ProtocolnfABIPtrTy));
5636
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005637 llvm::Constant *Values[2];
Owen Anderson170229f2009-07-14 23:10:40 +00005638 Values[0] =
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005639 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005640 Values[1] =
Bill Wendlinga515b582012-02-09 22:16:49 +00005641 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
5642 ProtocolRefs.size()),
5643 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005644
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005645 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Owen Andersonc10c8d32009-07-08 19:05:04 +00005646 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005647 llvm::GlobalValue::InternalLinkage,
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005648 Init, Name);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005649 GV->setSection("__DATA, __objc_const");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005650 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005651 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Chris Lattnerf56501c2009-07-17 23:57:13 +00005652 CGM.AddUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005653 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005654 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005655}
5656
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005657/// GetMethodDescriptionConstant - This routine build following meta-data:
5658/// struct _objc_method {
5659/// SEL _cmd;
5660/// char *method_type;
5661/// char *_imp;
5662/// }
5663
5664llvm::Constant *
5665CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005666 llvm::Constant *Desc[3];
Owen Anderson170229f2009-07-14 23:10:40 +00005667 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005668 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5669 ObjCTypes.SelectorPtrTy);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005670 Desc[1] = GetMethodVarType(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00005671 if (!Desc[1])
5672 return 0;
5673
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005674 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00005675 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005676 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005677}
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005678
5679/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
5680/// This code gen. amounts to generating code for:
5681/// @code
5682/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
5683/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005684///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00005685LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00005686 CodeGen::CodeGenFunction &CGF,
5687 QualType ObjectTy,
5688 llvm::Value *BaseValue,
5689 const ObjCIvarDecl *Ivar,
5690 unsigned CVRQualifiers) {
5691 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00005692 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5693 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005694}
5695
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005696llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005697 CodeGen::CodeGenFunction &CGF,
5698 const ObjCInterfaceDecl *Interface,
5699 const ObjCIvarDecl *Ivar) {
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005700 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005701}
5702
John McCall234eac82011-05-13 23:16:18 +00005703static void appendSelectorForMessageRefTable(std::string &buffer,
5704 Selector selector) {
5705 if (selector.isUnarySelector()) {
5706 buffer += selector.getNameForSlot(0);
5707 return;
5708 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005709
John McCall234eac82011-05-13 23:16:18 +00005710 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
5711 buffer += selector.getNameForSlot(i);
5712 buffer += '_';
5713 }
5714}
5715
John McCall9e8bb002011-05-14 03:10:52 +00005716/// Emit a "v-table" message send. We emit a weak hidden-visibility
5717/// struct, initially containing the selector pointer and a pointer to
5718/// a "fixup" variant of the appropriate objc_msgSend. To call, we
5719/// load and call the function pointer, passing the address of the
5720/// struct as the second parameter. The runtime determines whether
5721/// the selector is currently emitted using vtable dispatch; if so, it
5722/// substitutes a stub function which simply tail-calls through the
5723/// appropriate vtable slot, and if not, it substitues a stub function
5724/// which tail-calls objc_msgSend. Both stubs adjust the selector
5725/// argument to correctly point to the selector.
5726RValue
5727CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
5728 ReturnValueSlot returnSlot,
5729 QualType resultType,
5730 Selector selector,
5731 llvm::Value *arg0,
5732 QualType arg0Type,
5733 bool isSuper,
5734 const CallArgList &formalArgs,
5735 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00005736 // Compute the actual arguments.
5737 CallArgList args;
5738
John McCall9e8bb002011-05-14 03:10:52 +00005739 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00005740 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00005741 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
5742 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00005743
John McCall9e8bb002011-05-14 03:10:52 +00005744 // Second argument: a pointer to the message ref structure. Leave
5745 // the actual argument value blank for now.
John McCall234eac82011-05-13 23:16:18 +00005746 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
5747
5748 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
5749
5750 const CGFunctionInfo &fnInfo =
5751 CGM.getTypes().getFunctionInfo(resultType, args,
5752 FunctionType::ExtInfo());
5753
John McCall5880fb82011-05-14 21:12:11 +00005754 NullReturnState nullReturn;
5755
John McCall9e8bb002011-05-14 03:10:52 +00005756 // Find the function to call and the mangled name for the message
5757 // ref structure. Using a different mangled name wouldn't actually
5758 // be a problem; it would just be a waste.
5759 //
5760 // The runtime currently never uses vtable dispatch for anything
5761 // except normal, non-super message-sends.
5762 // FIXME: don't use this for that.
John McCall234eac82011-05-13 23:16:18 +00005763 llvm::Constant *fn = 0;
5764 std::string messageRefName("\01l_");
5765 if (CGM.ReturnTypeUsesSRet(fnInfo)) {
John McCall234eac82011-05-13 23:16:18 +00005766 if (isSuper) {
5767 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
5768 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005769 } else {
John McCall5880fb82011-05-14 21:12:11 +00005770 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00005771 fn = ObjCTypes.getMessageSendStretFixupFn();
5772 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005773 }
John McCall234eac82011-05-13 23:16:18 +00005774 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
5775 fn = ObjCTypes.getMessageSendFpretFixupFn();
5776 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00005777 } else {
John McCall234eac82011-05-13 23:16:18 +00005778 if (isSuper) {
5779 fn = ObjCTypes.getMessageSendSuper2FixupFn();
5780 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005781 } else {
John McCall234eac82011-05-13 23:16:18 +00005782 fn = ObjCTypes.getMessageSendFixupFn();
5783 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005784 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005785 }
John McCall234eac82011-05-13 23:16:18 +00005786 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
5787 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005788
John McCall234eac82011-05-13 23:16:18 +00005789 // Append the selector name, except use underscores anywhere we
5790 // would have used colons.
5791 appendSelectorForMessageRefTable(messageRefName, selector);
5792
5793 llvm::GlobalVariable *messageRef
5794 = CGM.getModule().getGlobalVariable(messageRefName);
5795 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00005796 // Build the message ref structure.
John McCall234eac82011-05-13 23:16:18 +00005797 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
Chris Lattnere64d7ba2011-06-20 04:01:35 +00005798 llvm::Constant *init = llvm::ConstantStruct::getAnon(values);
John McCall234eac82011-05-13 23:16:18 +00005799 messageRef = new llvm::GlobalVariable(CGM.getModule(),
5800 init->getType(),
5801 /*constant*/ false,
5802 llvm::GlobalValue::WeakAnyLinkage,
5803 init,
5804 messageRefName);
5805 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
5806 messageRef->setAlignment(16);
5807 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
5808 }
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00005809
5810 bool requiresnullCheck = false;
5811 if (CGM.getLangOptions().ObjCAutoRefCount && method)
5812 for (ObjCMethodDecl::param_const_iterator i = method->param_begin(),
5813 e = method->param_end(); i != e; ++i) {
5814 const ParmVarDecl *ParamDecl = (*i);
5815 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
5816 if (!nullReturn.NullBB)
5817 nullReturn.init(CGF, arg0);
5818 requiresnullCheck = true;
5819 break;
5820 }
5821 }
5822
John McCall234eac82011-05-13 23:16:18 +00005823 llvm::Value *mref =
5824 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
5825
John McCall9e8bb002011-05-14 03:10:52 +00005826 // Update the message ref argument.
John McCall234eac82011-05-13 23:16:18 +00005827 args[1].RV = RValue::get(mref);
5828
5829 // Load the function to call from the message ref table.
5830 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
5831 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
5832
5833 bool variadic = method ? method->isVariadic() : false;
Chris Lattner2192fe52011-07-18 04:24:23 +00005834 llvm::FunctionType *fnType =
John McCall234eac82011-05-13 23:16:18 +00005835 CGF.getTypes().GetFunctionType(fnInfo, variadic);
5836 callee = CGF.Builder.CreateBitCast(callee,
5837 llvm::PointerType::getUnqual(fnType));
5838
John McCall5880fb82011-05-14 21:12:11 +00005839 RValue result = CGF.EmitCall(fnInfo, callee, returnSlot, args);
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00005840 return nullReturn.complete(CGF, result, resultType, formalArgs,
5841 requiresnullCheck ? method : 0);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00005842}
5843
5844/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005845CodeGen::RValue
5846CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00005847 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005848 QualType ResultType,
5849 Selector Sel,
5850 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005851 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00005852 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005853 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00005854 return isVTableDispatchedSelector(Sel)
5855 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005856 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00005857 false, CallArgs, Method)
5858 : EmitMessageSend(CGF, Return, ResultType,
5859 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005860 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00005861 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00005862}
5863
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005864llvm::GlobalVariable *
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005865CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005866 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5867
Daniel Dunbara6468342009-03-02 05:18:14 +00005868 if (!GV) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005869 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005870 false, llvm::GlobalValue::ExternalLinkage,
5871 0, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005872 }
5873
5874 return GV;
5875}
5876
John McCall31168b02011-06-15 23:02:42 +00005877llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CGBuilderTy &Builder,
5878 IdentifierInfo *II) {
5879 llvm::GlobalVariable *&Entry = ClassReferences[II];
5880
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005881 if (!Entry) {
John McCall31168b02011-06-15 23:02:42 +00005882 std::string ClassName(getClassSymbolPrefix() + II->getName().str());
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005883 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005884 Entry =
John McCall31168b02011-06-15 23:02:42 +00005885 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
5886 false, llvm::GlobalValue::InternalLinkage,
5887 ClassGV,
5888 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005889 Entry->setAlignment(
John McCall31168b02011-06-15 23:02:42 +00005890 CGM.getTargetData().getABITypeAlignment(
5891 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005892 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005893 CGM.AddUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005894 }
John McCall31168b02011-06-15 23:02:42 +00005895
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005896 return Builder.CreateLoad(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005897}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005898
John McCall31168b02011-06-15 23:02:42 +00005899llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5900 const ObjCInterfaceDecl *ID) {
5901 return EmitClassRefFromId(Builder, ID->getIdentifier());
5902}
5903
5904llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
5905 CGBuilderTy &Builder) {
5906 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
5907 return EmitClassRefFromId(Builder, II);
5908}
5909
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005910llvm::Value *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005911CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005912 const ObjCInterfaceDecl *ID) {
5913 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005914
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005915 if (!Entry) {
5916 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5917 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005918 Entry =
5919 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005920 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005921 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005922 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005923 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005924 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005925 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005926 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005927 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005928 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005929
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005930 return Builder.CreateLoad(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005931}
5932
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005933/// EmitMetaClassRef - Return a Value * of the address of _class_t
5934/// meta-data
5935///
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005936llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5937 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005938 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5939 if (Entry)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005940 return Builder.CreateLoad(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005941
Daniel Dunbar15894b72009-04-07 05:48:37 +00005942 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005943 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005944 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005945 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005946 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005947 MetaClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005948 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005949 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005950 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005951 ObjCTypes.ClassnfABIPtrTy));
5952
Daniel Dunbare60aa052009-04-15 19:03:14 +00005953 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005954 CGM.AddUsedGlobal(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005955
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005956 return Builder.CreateLoad(Entry);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005957}
5958
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005959/// GetClass - Return a reference to the class for the given interface
5960/// decl.
5961llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
5962 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005963 if (ID->isWeakImported()) {
Fariborz Jahanian95ace552009-11-17 22:42:00 +00005964 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5965 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5966 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5967 }
5968
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005969 return EmitClassRef(Builder, ID);
5970}
5971
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005972/// Generates a message send where the super is the receiver. This is
5973/// a message send to self with special delivery semantics indicating
5974/// which class's method should be called.
5975CodeGen::RValue
5976CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00005977 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005978 QualType ResultType,
5979 Selector Sel,
5980 const ObjCInterfaceDecl *Class,
5981 bool isCategoryImpl,
5982 llvm::Value *Receiver,
5983 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005984 const CodeGen::CallArgList &CallArgs,
5985 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005986 // ...
5987 // Create and init a super structure; this is a (receiver, class)
5988 // pair we will pass to objc_msgSendSuper.
5989 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00005990 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005991
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005992 llvm::Value *ReceiverAsObject =
5993 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
5994 CGF.Builder.CreateStore(ReceiverAsObject,
5995 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005996
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005997 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005998 llvm::Value *Target;
5999 if (IsClassMessage) {
6000 if (isCategoryImpl) {
6001 // Message sent to "super' in a class method defined in
6002 // a category implementation.
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006003 Target = EmitClassRef(CGF.Builder, Class);
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00006004 Target = CGF.Builder.CreateStructGEP(Target, 0);
6005 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00006006 } else
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00006007 Target = EmitMetaClassRef(CGF.Builder, Class);
Mike Stump658fe022009-07-30 22:28:39 +00006008 } else
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006009 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006010
Mike Stump18bb9282009-05-16 07:57:57 +00006011 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
6012 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00006013 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006014 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
6015 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
6016 CGF.Builder.CreateStore(Target,
6017 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006018
John McCall9e8bb002011-05-14 03:10:52 +00006019 return (isVTableDispatchedSelector(Sel))
6020 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006021 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006022 true, CallArgs, Method)
6023 : EmitMessageSend(CGF, Return, ResultType,
6024 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006025 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006026 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006027}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006028
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006029llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006030 Selector Sel, bool lval) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006031 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006032
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006033 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006034 llvm::Constant *Casted =
6035 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
6036 ObjCTypes.SelectorPtrTy);
6037 Entry =
6038 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
6039 llvm::GlobalValue::InternalLinkage,
6040 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006041 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006042 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006043 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006044
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006045 if (lval)
6046 return Entry;
Pete Cooper9d605512011-11-10 21:45:06 +00006047 llvm::LoadInst* LI = Builder.CreateLoad(Entry);
6048
6049 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6050 llvm::MDNode::get(VMContext,
6051 ArrayRef<llvm::Value*>()));
6052 return LI;
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006053}
Fariborz Jahanian06292952009-02-16 22:52:32 +00006054/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006055/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00006056///
6057void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006058 llvm::Value *src,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006059 llvm::Value *dst,
6060 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006061 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006062 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00006063 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006064 assert(Size <= 8 && "does not support size > 8");
6065 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6066 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006067 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6068 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006069 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6070 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006071 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
6072 src, dst, ivarOffset);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006073 return;
6074}
6075
6076/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
6077/// objc_assign_strongCast (id src, id *dst)
6078///
6079void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006080 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006081 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006082 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006083 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00006084 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006085 assert(Size <= 8 && "does not support size > 8");
6086 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006087 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006088 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6089 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006090 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6091 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00006092 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006093 src, dst, "weakassign");
6094 return;
6095}
6096
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006097void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006098 CodeGen::CodeGenFunction &CGF,
6099 llvm::Value *DestPtr,
6100 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00006101 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006102 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
6103 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006104 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00006105 DestPtr, SrcPtr, Size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006106 return;
6107}
6108
Fariborz Jahanian06292952009-02-16 22:52:32 +00006109/// EmitObjCWeakRead - Code gen for loading value of a __weak
6110/// object: objc_read_weak (id *src)
6111///
6112llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006113 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006114 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006115 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006116 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
6117 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00006118 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006119 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00006120 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006121 return read_weak;
6122}
6123
6124/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
6125/// objc_assign_weak (id src, id *dst)
6126///
6127void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006128 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006129 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006130 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00006131 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006132 assert(Size <= 8 && "does not support size > 8");
6133 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6134 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006135 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6136 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006137 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6138 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00006139 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006140 src, dst, "weakassign");
6141 return;
6142}
6143
6144/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
6145/// objc_assign_global (id src, id *dst)
6146///
6147void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00006148 llvm::Value *src, llvm::Value *dst,
6149 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006150 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006151 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00006152 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006153 assert(Size <= 8 && "does not support size > 8");
6154 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6155 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006156 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6157 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006158 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6159 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00006160 if (!threadlocal)
6161 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
6162 src, dst, "globalassign");
6163 else
6164 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
6165 src, dst, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00006166 return;
6167}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006168
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006169void
John McCallbd309292010-07-06 01:34:17 +00006170CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6171 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006172 EmitAtSynchronizedStmt(CGF, S,
6173 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6174 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00006175}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006176
John McCall2ca705e2010-07-24 00:37:23 +00006177llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00006178CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00006179 // There's a particular fixed type info for 'id'.
6180 if (T->isObjCIdType() ||
6181 T->isObjCQualifiedIdType()) {
6182 llvm::Constant *IDEHType =
6183 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6184 if (!IDEHType)
6185 IDEHType =
6186 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6187 false,
6188 llvm::GlobalValue::ExternalLinkage,
6189 0, "OBJC_EHTYPE_id");
6190 return IDEHType;
6191 }
6192
6193 // All other types should be Objective-C interface pointer types.
6194 const ObjCObjectPointerType *PT =
6195 T->getAs<ObjCObjectPointerType>();
6196 assert(PT && "Invalid @catch type.");
6197 const ObjCInterfaceType *IT = PT->getInterfaceType();
6198 assert(IT && "Invalid @catch type.");
6199 return GetInterfaceEHType(IT->getDecl(), false);
6200}
6201
John McCallbd309292010-07-06 01:34:17 +00006202void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6203 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006204 EmitTryCatchStmt(CGF, S,
6205 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6206 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6207 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006208}
6209
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006210/// EmitThrowStmt - Generate code for a throw statement.
6211void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6212 const ObjCAtThrowStmt &S) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006213 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00006214 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006215 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Jay Foad5bd375a2011-07-15 08:37:34 +00006216 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall17afe452010-10-16 08:21:07 +00006217 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006218 } else {
Jay Foad5bd375a2011-07-15 08:37:34 +00006219 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall17afe452010-10-16 08:21:07 +00006220 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006221 }
6222
John McCall17afe452010-10-16 08:21:07 +00006223 CGF.Builder.CreateUnreachable();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006224 CGF.Builder.ClearInsertionPoint();
6225}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006226
John McCall2ca705e2010-07-24 00:37:23 +00006227llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006228CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006229 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006230 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006231
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006232 // If we don't need a definition, return the entry if found or check
6233 // if we use an external reference.
6234 if (!ForDefinition) {
6235 if (Entry)
6236 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00006237
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006238 // If this type (or a super class) has the __objc_exception__
6239 // attribute, emit an external reference.
Douglas Gregor78bd61f2009-06-18 16:11:24 +00006240 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006241 return Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006242 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006243 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006244 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006245 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006246 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006247 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006248
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006249 // Otherwise we need to either make a new entry or fill in the
6250 // initializer.
6251 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar15894b72009-04-07 05:48:37 +00006252 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006253 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006254 llvm::GlobalVariable *VTableGV =
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006255 CGM.getModule().getGlobalVariable(VTableName);
6256 if (!VTableGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006257 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6258 false,
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006259 llvm::GlobalValue::ExternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006260 0, VTableName);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006261
Chris Lattnerece04092012-02-07 00:39:47 +00006262 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006263
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006264 llvm::Constant *Values[] = {
6265 llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
6266 GetClassName(ID->getIdentifier()),
6267 GetClassGlobal(ClassName)
6268 };
Owen Anderson170229f2009-07-14 23:10:40 +00006269 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00006270 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006271
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006272 if (Entry) {
6273 Entry->setInitializer(Init);
6274 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00006275 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006276 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006277 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006278 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006279 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006280 }
6281
John McCall457a04e2010-10-22 21:05:15 +00006282 if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar15894b72009-04-07 05:48:37 +00006283 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar710cb202010-04-25 20:39:32 +00006284 Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
6285 ObjCTypes.EHTypeTy));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006286
6287 if (ForDefinition) {
6288 Entry->setSection("__DATA,__objc_const");
6289 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6290 } else {
6291 Entry->setSection("__DATA,__datacoal_nt,coalesced");
6292 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006293
6294 return Entry;
6295}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006296
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00006297/* *** */
6298
Daniel Dunbarb036db82008-08-13 03:21:16 +00006299CodeGen::CGObjCRuntime *
6300CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
David Chisnall067f0ed2011-03-22 21:21:24 +00006301 if (CGM.getLangOptions().ObjCNonFragileABI)
6302 return new CGObjCNonFragileABIMac(CGM);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00006303 return new CGObjCMac(CGM);
6304}