CGObjCMac.cpp revision 199482
1193326Sed//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed// This provides Objective-C code generation targetting the Apple runtime.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#include "CGObjCRuntime.h"
15193326Sed
16193326Sed#include "CodeGenModule.h"
17193326Sed#include "CodeGenFunction.h"
18193326Sed#include "clang/AST/ASTContext.h"
19193326Sed#include "clang/AST/Decl.h"
20193326Sed#include "clang/AST/DeclObjC.h"
21193326Sed#include "clang/AST/RecordLayout.h"
22193326Sed#include "clang/AST/StmtObjC.h"
23193326Sed#include "clang/Basic/LangOptions.h"
24193326Sed
25193326Sed#include "llvm/Intrinsics.h"
26198092Srdivacky#include "llvm/LLVMContext.h"
27193326Sed#include "llvm/Module.h"
28193326Sed#include "llvm/ADT/DenseSet.h"
29198092Srdivacky#include "llvm/ADT/SetVector.h"
30198092Srdivacky#include "llvm/ADT/SmallString.h"
31198092Srdivacky#include "llvm/Support/raw_ostream.h"
32193326Sed#include "llvm/Target/TargetData.h"
33198092Srdivacky#include <cstdio>
34193326Sed
35193326Sedusing namespace clang;
36193326Sedusing namespace CodeGen;
37193326Sed
38193326Sed// Common CGObjCRuntime functions, these don't belong here, but they
39193326Sed// don't belong in CGObjCRuntime either so we will live with it for
40193326Sed// now.
41193326Sed
42198092Srdivacky/// FindIvarInterface - Find the interface containing the ivar.
43193326Sed///
44193326Sed/// FIXME: We shouldn't need to do this, the containing context should
45193326Sed/// be fixed.
46193326Sedstatic const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
47193326Sed                                                  const ObjCInterfaceDecl *OID,
48193326Sed                                                  const ObjCIvarDecl *OIVD,
49193326Sed                                                  unsigned &Index) {
50193326Sed  // FIXME: The index here is closely tied to how
51193326Sed  // ASTContext::getObjCLayout is implemented. This should be fixed to
52193326Sed  // get the information from the layout directly.
53193326Sed  Index = 0;
54193326Sed  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
55193576Sed  Context.ShallowCollectObjCIvars(OID, Ivars);
56193326Sed  for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
57193326Sed    if (OIVD == Ivars[k])
58193326Sed      return OID;
59193326Sed    ++Index;
60193326Sed  }
61198092Srdivacky
62193326Sed  // Otherwise check in the super class.
63193326Sed  if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
64193326Sed    return FindIvarInterface(Context, Super, OIVD, Index);
65198092Srdivacky
66193326Sed  return 0;
67193326Sed}
68193326Sed
69193326Sedstatic uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
70193326Sed                                     const ObjCInterfaceDecl *OID,
71193326Sed                                     const ObjCImplementationDecl *ID,
72193326Sed                                     const ObjCIvarDecl *Ivar) {
73193326Sed  unsigned Index;
74198092Srdivacky  const ObjCInterfaceDecl *Container =
75193326Sed    FindIvarInterface(CGM.getContext(), OID, Ivar, Index);
76193326Sed  assert(Container && "Unable to find ivar container");
77193326Sed
78193326Sed  // If we know have an implementation (and the ivar is in it) then
79193326Sed  // look up in the implementation layout.
80198092Srdivacky  const ASTRecordLayout *RL;
81193326Sed  if (ID && ID->getClassInterface() == Container)
82193326Sed    RL = &CGM.getContext().getASTObjCImplementationLayout(ID);
83193326Sed  else
84193326Sed    RL = &CGM.getContext().getASTObjCInterfaceLayout(Container);
85193326Sed  return RL->getFieldOffset(Index);
86193326Sed}
87193326Sed
88193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
89193326Sed                                              const ObjCInterfaceDecl *OID,
90193326Sed                                              const ObjCIvarDecl *Ivar) {
91193326Sed  return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 8;
92193326Sed}
93193326Sed
94193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
95193326Sed                                              const ObjCImplementationDecl *OID,
96193326Sed                                              const ObjCIvarDecl *Ivar) {
97193326Sed  return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 8;
98193326Sed}
99193326Sed
100193326SedLValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
101193326Sed                                               const ObjCInterfaceDecl *OID,
102193326Sed                                               llvm::Value *BaseValue,
103193326Sed                                               const ObjCIvarDecl *Ivar,
104193326Sed                                               unsigned CVRQualifiers,
105193326Sed                                               llvm::Value *Offset) {
106193326Sed  // Compute (type*) ( (char *) BaseValue + Offset)
107198092Srdivacky  const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
108193326Sed  QualType IvarTy = Ivar->getType();
109193326Sed  const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
110193326Sed  llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr);
111193326Sed  V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
112193326Sed  V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
113198092Srdivacky
114198092Srdivacky  Qualifiers Quals = CGF.MakeQualifiers(IvarTy);
115198092Srdivacky  Quals.addCVRQualifiers(CVRQualifiers);
116198092Srdivacky
117193326Sed  if (Ivar->isBitField()) {
118193326Sed    // We need to compute the bit offset for the bit-field, the offset
119193326Sed    // is to the byte. Note, there is a subtle invariant here: we can
120193326Sed    // only call this routine on non-sythesized ivars but we may be
121193326Sed    // called for synthesized ivars. However, a synthesized ivar can
122193326Sed    // never be a bit-field so this is safe.
123193326Sed    uint64_t BitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar) % 8;
124193326Sed
125193326Sed    uint64_t BitFieldSize =
126193326Sed      Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue();
127193326Sed    return LValue::MakeBitfield(V, BitOffset, BitFieldSize,
128193326Sed                                IvarTy->isSignedIntegerType(),
129198092Srdivacky                                Quals.getCVRQualifiers());
130193326Sed  }
131193326Sed
132198092Srdivacky
133198092Srdivacky  LValue LV = LValue::MakeAddr(V, Quals);
134193326Sed  return LV;
135193326Sed}
136193326Sed
137193326Sed///
138193326Sed
139193326Sednamespace {
140193326Sed
141198092Srdivackytypedef std::vector<llvm::Constant*> ConstantVector;
142193326Sed
143198092Srdivacky// FIXME: We should find a nicer way to make the labels for metadata, string
144198092Srdivacky// concatenation is lame.
145193326Sed
146193326Sedclass ObjCCommonTypesHelper {
147198092Srdivackyprotected:
148198092Srdivacky  llvm::LLVMContext &VMContext;
149198092Srdivacky
150193326Sedprivate:
151193326Sed  llvm::Constant *getMessageSendFn() const {
152193326Sed    // id objc_msgSend (id, SEL, ...)
153193326Sed    std::vector<const llvm::Type*> Params;
154193326Sed    Params.push_back(ObjectPtrTy);
155193326Sed    Params.push_back(SelectorPtrTy);
156193326Sed    return
157198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
158198092Srdivacky                                                        Params, true),
159198092Srdivacky                                "objc_msgSend");
160193326Sed  }
161198092Srdivacky
162193326Sed  llvm::Constant *getMessageSendStretFn() const {
163193326Sed    // id objc_msgSend_stret (id, SEL, ...)
164193326Sed    std::vector<const llvm::Type*> Params;
165193326Sed    Params.push_back(ObjectPtrTy);
166193326Sed    Params.push_back(SelectorPtrTy);
167193326Sed    return
168198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
169198092Srdivacky                                                        Params, true),
170198092Srdivacky                                "objc_msgSend_stret");
171198092Srdivacky
172193326Sed  }
173198092Srdivacky
174193326Sed  llvm::Constant *getMessageSendFpretFn() const {
175193326Sed    // FIXME: This should be long double on x86_64?
176193326Sed    // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
177193326Sed    std::vector<const llvm::Type*> Params;
178193326Sed    Params.push_back(ObjectPtrTy);
179193326Sed    Params.push_back(SelectorPtrTy);
180193326Sed    return
181198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(
182198092Srdivacky                                             llvm::Type::getDoubleTy(VMContext),
183198092Srdivacky                                                        Params,
184198092Srdivacky                                                        true),
185198092Srdivacky                                "objc_msgSend_fpret");
186198092Srdivacky
187193326Sed  }
188198092Srdivacky
189193326Sed  llvm::Constant *getMessageSendSuperFn() const {
190193326Sed    // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
191193326Sed    const char *SuperName = "objc_msgSendSuper";
192193326Sed    std::vector<const llvm::Type*> Params;
193193326Sed    Params.push_back(SuperPtrTy);
194193326Sed    Params.push_back(SelectorPtrTy);
195193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
196193326Sed                                                             Params, true),
197193326Sed                                     SuperName);
198193326Sed  }
199198092Srdivacky
200193326Sed  llvm::Constant *getMessageSendSuperFn2() const {
201193326Sed    // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
202193326Sed    const char *SuperName = "objc_msgSendSuper2";
203193326Sed    std::vector<const llvm::Type*> Params;
204193326Sed    Params.push_back(SuperPtrTy);
205193326Sed    Params.push_back(SelectorPtrTy);
206193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
207193326Sed                                                             Params, true),
208193326Sed                                     SuperName);
209193326Sed  }
210198092Srdivacky
211193326Sed  llvm::Constant *getMessageSendSuperStretFn() const {
212193326Sed    // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
213193326Sed    //                              SEL op, ...)
214193326Sed    std::vector<const llvm::Type*> Params;
215193326Sed    Params.push_back(Int8PtrTy);
216193326Sed    Params.push_back(SuperPtrTy);
217193326Sed    Params.push_back(SelectorPtrTy);
218198092Srdivacky    return CGM.CreateRuntimeFunction(
219198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
220198092Srdivacky                              Params, true),
221198092Srdivacky      "objc_msgSendSuper_stret");
222193326Sed  }
223198092Srdivacky
224193326Sed  llvm::Constant *getMessageSendSuperStretFn2() const {
225193326Sed    // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
226193326Sed    //                               SEL op, ...)
227193326Sed    std::vector<const llvm::Type*> Params;
228193326Sed    Params.push_back(Int8PtrTy);
229193326Sed    Params.push_back(SuperPtrTy);
230193326Sed    Params.push_back(SelectorPtrTy);
231198092Srdivacky    return CGM.CreateRuntimeFunction(
232198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
233198092Srdivacky                              Params, true),
234198092Srdivacky      "objc_msgSendSuper2_stret");
235193326Sed  }
236198092Srdivacky
237193326Sed  llvm::Constant *getMessageSendSuperFpretFn() const {
238193326Sed    // There is no objc_msgSendSuper_fpret? How can that work?
239193326Sed    return getMessageSendSuperFn();
240193326Sed  }
241198092Srdivacky
242193326Sed  llvm::Constant *getMessageSendSuperFpretFn2() const {
243193326Sed    // There is no objc_msgSendSuper_fpret? How can that work?
244193326Sed    return getMessageSendSuperFn2();
245193326Sed  }
246198092Srdivacky
247193326Sedprotected:
248193326Sed  CodeGen::CodeGenModule &CGM;
249198092Srdivacky
250193326Sedpublic:
251193326Sed  const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
252193326Sed  const llvm::Type *Int8PtrTy;
253198092Srdivacky
254193326Sed  /// ObjectPtrTy - LLVM type for object handles (typeof(id))
255193326Sed  const llvm::Type *ObjectPtrTy;
256198092Srdivacky
257193326Sed  /// PtrObjectPtrTy - LLVM type for id *
258193326Sed  const llvm::Type *PtrObjectPtrTy;
259198092Srdivacky
260193326Sed  /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
261193326Sed  const llvm::Type *SelectorPtrTy;
262193326Sed  /// ProtocolPtrTy - LLVM type for external protocol handles
263193326Sed  /// (typeof(Protocol))
264193326Sed  const llvm::Type *ExternalProtocolPtrTy;
265198092Srdivacky
266193326Sed  // SuperCTy - clang type for struct objc_super.
267193326Sed  QualType SuperCTy;
268193326Sed  // SuperPtrCTy - clang type for struct objc_super *.
269193326Sed  QualType SuperPtrCTy;
270198092Srdivacky
271193326Sed  /// SuperTy - LLVM type for struct objc_super.
272193326Sed  const llvm::StructType *SuperTy;
273193326Sed  /// SuperPtrTy - LLVM type for struct objc_super *.
274193326Sed  const llvm::Type *SuperPtrTy;
275198092Srdivacky
276193326Sed  /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
277193326Sed  /// in GCC parlance).
278193326Sed  const llvm::StructType *PropertyTy;
279198092Srdivacky
280193326Sed  /// PropertyListTy - LLVM type for struct objc_property_list
281193326Sed  /// (_prop_list_t in GCC parlance).
282193326Sed  const llvm::StructType *PropertyListTy;
283193326Sed  /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
284193326Sed  const llvm::Type *PropertyListPtrTy;
285198092Srdivacky
286193326Sed  // MethodTy - LLVM type for struct objc_method.
287193326Sed  const llvm::StructType *MethodTy;
288198092Srdivacky
289193326Sed  /// CacheTy - LLVM type for struct objc_cache.
290193326Sed  const llvm::Type *CacheTy;
291193326Sed  /// CachePtrTy - LLVM type for struct objc_cache *.
292193326Sed  const llvm::Type *CachePtrTy;
293198092Srdivacky
294193326Sed  llvm::Constant *getGetPropertyFn() {
295193326Sed    CodeGen::CodeGenTypes &Types = CGM.getTypes();
296193326Sed    ASTContext &Ctx = CGM.getContext();
297193326Sed    // id objc_getProperty (id, SEL, ptrdiff_t, bool)
298193326Sed    llvm::SmallVector<QualType,16> Params;
299193326Sed    QualType IdType = Ctx.getObjCIdType();
300193326Sed    QualType SelType = Ctx.getObjCSelType();
301193326Sed    Params.push_back(IdType);
302193326Sed    Params.push_back(SelType);
303193326Sed    Params.push_back(Ctx.LongTy);
304193326Sed    Params.push_back(Ctx.BoolTy);
305193326Sed    const llvm::FunctionType *FTy =
306193326Sed      Types.GetFunctionType(Types.getFunctionInfo(IdType, Params), false);
307193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
308193326Sed  }
309198092Srdivacky
310193326Sed  llvm::Constant *getSetPropertyFn() {
311193326Sed    CodeGen::CodeGenTypes &Types = CGM.getTypes();
312193326Sed    ASTContext &Ctx = CGM.getContext();
313193326Sed    // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
314193326Sed    llvm::SmallVector<QualType,16> Params;
315193326Sed    QualType IdType = Ctx.getObjCIdType();
316193326Sed    QualType SelType = Ctx.getObjCSelType();
317193326Sed    Params.push_back(IdType);
318193326Sed    Params.push_back(SelType);
319193326Sed    Params.push_back(Ctx.LongTy);
320193326Sed    Params.push_back(IdType);
321193326Sed    Params.push_back(Ctx.BoolTy);
322193326Sed    Params.push_back(Ctx.BoolTy);
323193326Sed    const llvm::FunctionType *FTy =
324193326Sed      Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
325193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
326193326Sed  }
327198092Srdivacky
328193326Sed  llvm::Constant *getEnumerationMutationFn() {
329198092Srdivacky    CodeGen::CodeGenTypes &Types = CGM.getTypes();
330198092Srdivacky    ASTContext &Ctx = CGM.getContext();
331193326Sed    // void objc_enumerationMutation (id)
332198092Srdivacky    llvm::SmallVector<QualType,16> Params;
333198092Srdivacky    Params.push_back(Ctx.getObjCIdType());
334198092Srdivacky    const llvm::FunctionType *FTy =
335198092Srdivacky      Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
336193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
337193326Sed  }
338198092Srdivacky
339193326Sed  /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
340193326Sed  llvm::Constant *getGcReadWeakFn() {
341193326Sed    // id objc_read_weak (id *)
342193326Sed    std::vector<const llvm::Type*> Args;
343193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
344198092Srdivacky    llvm::FunctionType *FTy =
345198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
346193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
347198092Srdivacky  }
348198092Srdivacky
349193326Sed  /// GcAssignWeakFn -- LLVM objc_assign_weak function.
350193326Sed  llvm::Constant *getGcAssignWeakFn() {
351193326Sed    // id objc_assign_weak (id, id *)
352193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
353193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
354193326Sed    llvm::FunctionType *FTy =
355193326Sed      llvm::FunctionType::get(ObjectPtrTy, Args, false);
356193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
357193326Sed  }
358198092Srdivacky
359193326Sed  /// GcAssignGlobalFn -- LLVM objc_assign_global function.
360193326Sed  llvm::Constant *getGcAssignGlobalFn() {
361193326Sed    // id objc_assign_global(id, id *)
362193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
363193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
364198092Srdivacky    llvm::FunctionType *FTy =
365198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
366193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
367193326Sed  }
368198092Srdivacky
369193326Sed  /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
370193326Sed  llvm::Constant *getGcAssignIvarFn() {
371198092Srdivacky    // id objc_assign_ivar(id, id *, ptrdiff_t)
372193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
373193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
374198092Srdivacky    Args.push_back(LongTy);
375198092Srdivacky    llvm::FunctionType *FTy =
376198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
377193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
378193326Sed  }
379198092Srdivacky
380198092Srdivacky  /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
381198092Srdivacky  llvm::Constant *GcMemmoveCollectableFn() {
382198092Srdivacky    // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
383198092Srdivacky    std::vector<const llvm::Type*> Args(1, Int8PtrTy);
384198092Srdivacky    Args.push_back(Int8PtrTy);
385198092Srdivacky    Args.push_back(LongTy);
386198092Srdivacky    llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
387198092Srdivacky    return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
388198092Srdivacky  }
389198092Srdivacky
390193326Sed  /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
391193326Sed  llvm::Constant *getGcAssignStrongCastFn() {
392193326Sed    // id objc_assign_global(id, id *)
393193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
394193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
395198092Srdivacky    llvm::FunctionType *FTy =
396198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
397193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
398193326Sed  }
399193326Sed
400193326Sed  /// ExceptionThrowFn - LLVM objc_exception_throw function.
401193326Sed  llvm::Constant *getExceptionThrowFn() {
402193326Sed    // void objc_exception_throw(id)
403193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
404193326Sed    llvm::FunctionType *FTy =
405198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
406193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
407193326Sed  }
408198092Srdivacky
409193326Sed  /// SyncEnterFn - LLVM object_sync_enter function.
410193326Sed  llvm::Constant *getSyncEnterFn() {
411193326Sed    // void objc_sync_enter (id)
412193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
413193326Sed    llvm::FunctionType *FTy =
414198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
415193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
416193326Sed  }
417198092Srdivacky
418193326Sed  /// SyncExitFn - LLVM object_sync_exit function.
419193326Sed  llvm::Constant *getSyncExitFn() {
420193326Sed    // void objc_sync_exit (id)
421193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
422193326Sed    llvm::FunctionType *FTy =
423198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
424193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
425193326Sed  }
426198092Srdivacky
427193326Sed  llvm::Constant *getSendFn(bool IsSuper) const {
428193326Sed    return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
429193326Sed  }
430198092Srdivacky
431193326Sed  llvm::Constant *getSendFn2(bool IsSuper) const {
432193326Sed    return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
433193326Sed  }
434198092Srdivacky
435193326Sed  llvm::Constant *getSendStretFn(bool IsSuper) const {
436193326Sed    return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
437193326Sed  }
438198092Srdivacky
439193326Sed  llvm::Constant *getSendStretFn2(bool IsSuper) const {
440193326Sed    return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
441193326Sed  }
442198092Srdivacky
443193326Sed  llvm::Constant *getSendFpretFn(bool IsSuper) const {
444193326Sed    return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
445193326Sed  }
446198092Srdivacky
447193326Sed  llvm::Constant *getSendFpretFn2(bool IsSuper) const {
448193326Sed    return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
449193326Sed  }
450198092Srdivacky
451193326Sed  ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
452193326Sed  ~ObjCCommonTypesHelper(){}
453193326Sed};
454193326Sed
455193326Sed/// ObjCTypesHelper - Helper class that encapsulates lazy
456193326Sed/// construction of varies types used during ObjC generation.
457193326Sedclass ObjCTypesHelper : public ObjCCommonTypesHelper {
458193326Sedpublic:
459193326Sed  /// SymtabTy - LLVM type for struct objc_symtab.
460193326Sed  const llvm::StructType *SymtabTy;
461193326Sed  /// SymtabPtrTy - LLVM type for struct objc_symtab *.
462193326Sed  const llvm::Type *SymtabPtrTy;
463193326Sed  /// ModuleTy - LLVM type for struct objc_module.
464193326Sed  const llvm::StructType *ModuleTy;
465193326Sed
466193326Sed  /// ProtocolTy - LLVM type for struct objc_protocol.
467193326Sed  const llvm::StructType *ProtocolTy;
468193326Sed  /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
469193326Sed  const llvm::Type *ProtocolPtrTy;
470193326Sed  /// ProtocolExtensionTy - LLVM type for struct
471193326Sed  /// objc_protocol_extension.
472193326Sed  const llvm::StructType *ProtocolExtensionTy;
473193326Sed  /// ProtocolExtensionTy - LLVM type for struct
474193326Sed  /// objc_protocol_extension *.
475193326Sed  const llvm::Type *ProtocolExtensionPtrTy;
476193326Sed  /// MethodDescriptionTy - LLVM type for struct
477193326Sed  /// objc_method_description.
478193326Sed  const llvm::StructType *MethodDescriptionTy;
479193326Sed  /// MethodDescriptionListTy - LLVM type for struct
480193326Sed  /// objc_method_description_list.
481193326Sed  const llvm::StructType *MethodDescriptionListTy;
482193326Sed  /// MethodDescriptionListPtrTy - LLVM type for struct
483193326Sed  /// objc_method_description_list *.
484193326Sed  const llvm::Type *MethodDescriptionListPtrTy;
485193326Sed  /// ProtocolListTy - LLVM type for struct objc_property_list.
486193326Sed  const llvm::Type *ProtocolListTy;
487193326Sed  /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
488193326Sed  const llvm::Type *ProtocolListPtrTy;
489193326Sed  /// CategoryTy - LLVM type for struct objc_category.
490193326Sed  const llvm::StructType *CategoryTy;
491193326Sed  /// ClassTy - LLVM type for struct objc_class.
492193326Sed  const llvm::StructType *ClassTy;
493193326Sed  /// ClassPtrTy - LLVM type for struct objc_class *.
494193326Sed  const llvm::Type *ClassPtrTy;
495193326Sed  /// ClassExtensionTy - LLVM type for struct objc_class_ext.
496193326Sed  const llvm::StructType *ClassExtensionTy;
497193326Sed  /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
498193326Sed  const llvm::Type *ClassExtensionPtrTy;
499193326Sed  // IvarTy - LLVM type for struct objc_ivar.
500193326Sed  const llvm::StructType *IvarTy;
501193326Sed  /// IvarListTy - LLVM type for struct objc_ivar_list.
502193326Sed  const llvm::Type *IvarListTy;
503193326Sed  /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
504193326Sed  const llvm::Type *IvarListPtrTy;
505193326Sed  /// MethodListTy - LLVM type for struct objc_method_list.
506193326Sed  const llvm::Type *MethodListTy;
507193326Sed  /// MethodListPtrTy - LLVM type for struct objc_method_list *.
508193326Sed  const llvm::Type *MethodListPtrTy;
509198092Srdivacky
510193326Sed  /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
511193326Sed  const llvm::Type *ExceptionDataTy;
512198092Srdivacky
513193326Sed  /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
514193326Sed  llvm::Constant *getExceptionTryEnterFn() {
515193326Sed    std::vector<const llvm::Type*> Params;
516193326Sed    Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
517198092Srdivacky    return CGM.CreateRuntimeFunction(
518198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
519198092Srdivacky                              Params, false),
520198092Srdivacky      "objc_exception_try_enter");
521193326Sed  }
522193326Sed
523193326Sed  /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
524193326Sed  llvm::Constant *getExceptionTryExitFn() {
525193326Sed    std::vector<const llvm::Type*> Params;
526193326Sed    Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
527198092Srdivacky    return CGM.CreateRuntimeFunction(
528198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
529198092Srdivacky                              Params, false),
530198092Srdivacky      "objc_exception_try_exit");
531193326Sed  }
532193326Sed
533193326Sed  /// ExceptionExtractFn - LLVM objc_exception_extract function.
534193326Sed  llvm::Constant *getExceptionExtractFn() {
535193326Sed    std::vector<const llvm::Type*> Params;
536193326Sed    Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
537193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
538193326Sed                                                             Params, false),
539193326Sed                                     "objc_exception_extract");
540198092Srdivacky
541193326Sed  }
542198092Srdivacky
543193326Sed  /// ExceptionMatchFn - LLVM objc_exception_match function.
544193326Sed  llvm::Constant *getExceptionMatchFn() {
545193326Sed    std::vector<const llvm::Type*> Params;
546193326Sed    Params.push_back(ClassPtrTy);
547193326Sed    Params.push_back(ObjectPtrTy);
548198092Srdivacky    return CGM.CreateRuntimeFunction(
549198092Srdivacky      llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
550198092Srdivacky                              Params, false),
551198092Srdivacky      "objc_exception_match");
552198092Srdivacky
553193326Sed  }
554198092Srdivacky
555193326Sed  /// SetJmpFn - LLVM _setjmp function.
556193326Sed  llvm::Constant *getSetJmpFn() {
557193326Sed    std::vector<const llvm::Type*> Params;
558198092Srdivacky    Params.push_back(llvm::Type::getInt32PtrTy(VMContext));
559193326Sed    return
560198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
561193326Sed                                                        Params, false),
562193326Sed                                "_setjmp");
563198092Srdivacky
564193326Sed  }
565198092Srdivacky
566193326Sedpublic:
567193326Sed  ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
568193326Sed  ~ObjCTypesHelper() {}
569193326Sed};
570193326Sed
571193326Sed/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
572193326Sed/// modern abi
573193326Sedclass ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
574193326Sedpublic:
575198092Srdivacky
576193326Sed  // MethodListnfABITy - LLVM for struct _method_list_t
577193326Sed  const llvm::StructType *MethodListnfABITy;
578198092Srdivacky
579193326Sed  // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
580193326Sed  const llvm::Type *MethodListnfABIPtrTy;
581198092Srdivacky
582193326Sed  // ProtocolnfABITy = LLVM for struct _protocol_t
583193326Sed  const llvm::StructType *ProtocolnfABITy;
584198092Srdivacky
585193326Sed  // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
586193326Sed  const llvm::Type *ProtocolnfABIPtrTy;
587193326Sed
588193326Sed  // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
589193326Sed  const llvm::StructType *ProtocolListnfABITy;
590198092Srdivacky
591193326Sed  // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
592193326Sed  const llvm::Type *ProtocolListnfABIPtrTy;
593198092Srdivacky
594193326Sed  // ClassnfABITy - LLVM for struct _class_t
595193326Sed  const llvm::StructType *ClassnfABITy;
596198092Srdivacky
597193326Sed  // ClassnfABIPtrTy - LLVM for struct _class_t*
598193326Sed  const llvm::Type *ClassnfABIPtrTy;
599198092Srdivacky
600193326Sed  // IvarnfABITy - LLVM for struct _ivar_t
601193326Sed  const llvm::StructType *IvarnfABITy;
602198092Srdivacky
603193326Sed  // IvarListnfABITy - LLVM for struct _ivar_list_t
604193326Sed  const llvm::StructType *IvarListnfABITy;
605198092Srdivacky
606193326Sed  // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
607193326Sed  const llvm::Type *IvarListnfABIPtrTy;
608198092Srdivacky
609193326Sed  // ClassRonfABITy - LLVM for struct _class_ro_t
610193326Sed  const llvm::StructType *ClassRonfABITy;
611198092Srdivacky
612193326Sed  // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
613193326Sed  const llvm::Type *ImpnfABITy;
614198092Srdivacky
615193326Sed  // CategorynfABITy - LLVM for struct _category_t
616193326Sed  const llvm::StructType *CategorynfABITy;
617198092Srdivacky
618193326Sed  // New types for nonfragile abi messaging.
619198092Srdivacky
620193326Sed  // MessageRefTy - LLVM for:
621193326Sed  // struct _message_ref_t {
622193326Sed  //   IMP messenger;
623193326Sed  //   SEL name;
624193326Sed  // };
625193326Sed  const llvm::StructType *MessageRefTy;
626193326Sed  // MessageRefCTy - clang type for struct _message_ref_t
627193326Sed  QualType MessageRefCTy;
628198092Srdivacky
629193326Sed  // MessageRefPtrTy - LLVM for struct _message_ref_t*
630193326Sed  const llvm::Type *MessageRefPtrTy;
631193326Sed  // MessageRefCPtrTy - clang type for struct _message_ref_t*
632193326Sed  QualType MessageRefCPtrTy;
633198092Srdivacky
634193326Sed  // MessengerTy - Type of the messenger (shown as IMP above)
635193326Sed  const llvm::FunctionType *MessengerTy;
636198092Srdivacky
637193326Sed  // SuperMessageRefTy - LLVM for:
638193326Sed  // struct _super_message_ref_t {
639193326Sed  //   SUPER_IMP messenger;
640193326Sed  //   SEL name;
641193326Sed  // };
642193326Sed  const llvm::StructType *SuperMessageRefTy;
643198092Srdivacky
644193326Sed  // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
645193326Sed  const llvm::Type *SuperMessageRefPtrTy;
646193326Sed
647193326Sed  llvm::Constant *getMessageSendFixupFn() {
648193326Sed    // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
649193326Sed    std::vector<const llvm::Type*> Params;
650193326Sed    Params.push_back(ObjectPtrTy);
651193326Sed    Params.push_back(MessageRefPtrTy);
652193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
653193326Sed                                                             Params, true),
654193326Sed                                     "objc_msgSend_fixup");
655193326Sed  }
656198092Srdivacky
657193326Sed  llvm::Constant *getMessageSendFpretFixupFn() {
658193326Sed    // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
659193326Sed    std::vector<const llvm::Type*> Params;
660193326Sed    Params.push_back(ObjectPtrTy);
661193326Sed    Params.push_back(MessageRefPtrTy);
662193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
663193326Sed                                                             Params, true),
664193326Sed                                     "objc_msgSend_fpret_fixup");
665193326Sed  }
666198092Srdivacky
667193326Sed  llvm::Constant *getMessageSendStretFixupFn() {
668193326Sed    // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
669193326Sed    std::vector<const llvm::Type*> Params;
670193326Sed    Params.push_back(ObjectPtrTy);
671193326Sed    Params.push_back(MessageRefPtrTy);
672193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
673193326Sed                                                             Params, true),
674193326Sed                                     "objc_msgSend_stret_fixup");
675193326Sed  }
676198092Srdivacky
677193326Sed  llvm::Constant *getMessageSendIdFixupFn() {
678193326Sed    // id objc_msgSendId_fixup(id, struct message_ref_t*, ...)
679193326Sed    std::vector<const llvm::Type*> Params;
680193326Sed    Params.push_back(ObjectPtrTy);
681193326Sed    Params.push_back(MessageRefPtrTy);
682193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
683193326Sed                                                             Params, true),
684193326Sed                                     "objc_msgSendId_fixup");
685193326Sed  }
686198092Srdivacky
687193326Sed  llvm::Constant *getMessageSendIdStretFixupFn() {
688193326Sed    // id objc_msgSendId_stret_fixup(id, struct message_ref_t*, ...)
689193326Sed    std::vector<const llvm::Type*> Params;
690193326Sed    Params.push_back(ObjectPtrTy);
691193326Sed    Params.push_back(MessageRefPtrTy);
692193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
693193326Sed                                                             Params, true),
694193326Sed                                     "objc_msgSendId_stret_fixup");
695193326Sed  }
696193326Sed  llvm::Constant *getMessageSendSuper2FixupFn() {
697198092Srdivacky    // id objc_msgSendSuper2_fixup (struct objc_super *,
698193326Sed    //                              struct _super_message_ref_t*, ...)
699193326Sed    std::vector<const llvm::Type*> Params;
700193326Sed    Params.push_back(SuperPtrTy);
701193326Sed    Params.push_back(SuperMessageRefPtrTy);
702193326Sed    return  CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
703193326Sed                                                              Params, true),
704193326Sed                                      "objc_msgSendSuper2_fixup");
705193326Sed  }
706198092Srdivacky
707193326Sed  llvm::Constant *getMessageSendSuper2StretFixupFn() {
708198092Srdivacky    // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
709193326Sed    //                                   struct _super_message_ref_t*, ...)
710193326Sed    std::vector<const llvm::Type*> Params;
711193326Sed    Params.push_back(SuperPtrTy);
712193326Sed    Params.push_back(SuperMessageRefPtrTy);
713193326Sed    return  CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
714193326Sed                                                              Params, true),
715193326Sed                                      "objc_msgSendSuper2_stret_fixup");
716193326Sed  }
717198092Srdivacky
718198092Srdivacky
719198092Srdivacky
720193326Sed  /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C
721193326Sed  /// exception personality function.
722193326Sed  llvm::Value *getEHPersonalityPtr() {
723198092Srdivacky    llvm::Constant *Personality =
724198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
725193326Sed                                                        true),
726198092Srdivacky                                "__objc_personality_v0");
727193326Sed    return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy);
728193326Sed  }
729193326Sed
730193326Sed  llvm::Constant *getUnwindResumeOrRethrowFn() {
731193326Sed    std::vector<const llvm::Type*> Params;
732193326Sed    Params.push_back(Int8PtrTy);
733198092Srdivacky    return CGM.CreateRuntimeFunction(
734198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
735198092Srdivacky                              Params, false),
736198092Srdivacky      "_Unwind_Resume_or_Rethrow");
737193326Sed  }
738198092Srdivacky
739193326Sed  llvm::Constant *getObjCEndCatchFn() {
740198092Srdivacky    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
741195341Sed                                                             false),
742193326Sed                                     "objc_end_catch");
743198092Srdivacky
744193326Sed  }
745198092Srdivacky
746193326Sed  llvm::Constant *getObjCBeginCatchFn() {
747193326Sed    std::vector<const llvm::Type*> Params;
748193326Sed    Params.push_back(Int8PtrTy);
749193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
750193326Sed                                                             Params, false),
751193326Sed                                     "objc_begin_catch");
752193326Sed  }
753193326Sed
754193326Sed  const llvm::StructType *EHTypeTy;
755193326Sed  const llvm::Type *EHTypePtrTy;
756193326Sed
757193326Sed  ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
758193326Sed  ~ObjCNonFragileABITypesHelper(){}
759193326Sed};
760198092Srdivacky
761193326Sedclass CGObjCCommonMac : public CodeGen::CGObjCRuntime {
762193326Sedpublic:
763193326Sed  // FIXME - accessibility
764193326Sed  class GC_IVAR {
765193326Sed  public:
766193326Sed    unsigned ivar_bytepos;
767193326Sed    unsigned ivar_size;
768193326Sed    GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
769198092Srdivacky      : ivar_bytepos(bytepos), ivar_size(size) {}
770193326Sed
771193326Sed    // Allow sorting based on byte pos.
772193326Sed    bool operator<(const GC_IVAR &b) const {
773193326Sed      return ivar_bytepos < b.ivar_bytepos;
774193326Sed    }
775193326Sed  };
776198092Srdivacky
777193326Sed  class SKIP_SCAN {
778193326Sed  public:
779193326Sed    unsigned skip;
780193326Sed    unsigned scan;
781198092Srdivacky    SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
782193326Sed      : skip(_skip), scan(_scan) {}
783193326Sed  };
784198092Srdivacky
785193326Sedprotected:
786193326Sed  CodeGen::CodeGenModule &CGM;
787198092Srdivacky  llvm::LLVMContext &VMContext;
788193326Sed  // FIXME! May not be needing this after all.
789193326Sed  unsigned ObjCABI;
790198092Srdivacky
791193326Sed  // gc ivar layout bitmap calculation helper caches.
792193326Sed  llvm::SmallVector<GC_IVAR, 16> SkipIvars;
793193326Sed  llvm::SmallVector<GC_IVAR, 16> IvarsInfo;
794198092Srdivacky
795193326Sed  /// LazySymbols - Symbols to generate a lazy reference for. See
796193326Sed  /// DefinedSymbols and FinishModule().
797198092Srdivacky  llvm::SetVector<IdentifierInfo*> LazySymbols;
798198092Srdivacky
799193326Sed  /// DefinedSymbols - External symbols which are defined by this
800193326Sed  /// module. The symbols in this list and LazySymbols are used to add
801193326Sed  /// special linker symbols which ensure that Objective-C modules are
802193326Sed  /// linked properly.
803198092Srdivacky  llvm::SetVector<IdentifierInfo*> DefinedSymbols;
804198092Srdivacky
805193326Sed  /// ClassNames - uniqued class names.
806193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
807198092Srdivacky
808193326Sed  /// MethodVarNames - uniqued method variable names.
809193326Sed  llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
810198092Srdivacky
811193326Sed  /// MethodVarTypes - uniqued method type signatures. We have to use
812193326Sed  /// a StringMap here because have no other unique reference.
813193326Sed  llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
814198092Srdivacky
815193326Sed  /// MethodDefinitions - map of methods which have been defined in
816193326Sed  /// this translation unit.
817193326Sed  llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
818198092Srdivacky
819193326Sed  /// PropertyNames - uniqued method variable names.
820193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
821198092Srdivacky
822193326Sed  /// ClassReferences - uniqued class references.
823193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
824198092Srdivacky
825193326Sed  /// SelectorReferences - uniqued selector references.
826193326Sed  llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
827198092Srdivacky
828193326Sed  /// Protocols - Protocols for which an objc_protocol structure has
829193326Sed  /// been emitted. Forward declarations are handled by creating an
830193326Sed  /// empty structure whose initializer is filled in when/if defined.
831193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
832198092Srdivacky
833193326Sed  /// DefinedProtocols - Protocols which have actually been
834193326Sed  /// defined. We should not need this, see FIXME in GenerateProtocol.
835193326Sed  llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
836198092Srdivacky
837193326Sed  /// DefinedClasses - List of defined classes.
838193326Sed  std::vector<llvm::GlobalValue*> DefinedClasses;
839193326Sed
840193326Sed  /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
841193326Sed  std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
842198092Srdivacky
843193326Sed  /// DefinedCategories - List of defined categories.
844193326Sed  std::vector<llvm::GlobalValue*> DefinedCategories;
845198092Srdivacky
846193326Sed  /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
847193326Sed  std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
848193326Sed
849193326Sed  /// GetNameForMethod - Return a name for the given method.
850193326Sed  /// \param[out] NameOut - The return value.
851193326Sed  void GetNameForMethod(const ObjCMethodDecl *OMD,
852193326Sed                        const ObjCContainerDecl *CD,
853198398Srdivacky                        llvm::SmallVectorImpl<char> &NameOut);
854198092Srdivacky
855193326Sed  /// GetMethodVarName - Return a unique constant for the given
856193326Sed  /// selector's name. The return value has type char *.
857193326Sed  llvm::Constant *GetMethodVarName(Selector Sel);
858193326Sed  llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
859193326Sed  llvm::Constant *GetMethodVarName(const std::string &Name);
860198092Srdivacky
861193326Sed  /// GetMethodVarType - Return a unique constant for the given
862193326Sed  /// selector's name. The return value has type char *.
863198092Srdivacky
864193326Sed  // FIXME: This is a horrible name.
865193326Sed  llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
866193326Sed  llvm::Constant *GetMethodVarType(const FieldDecl *D);
867198092Srdivacky
868193326Sed  /// GetPropertyName - Return a unique constant for the given
869193326Sed  /// name. The return value has type char *.
870193326Sed  llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
871198092Srdivacky
872193326Sed  // FIXME: This can be dropped once string functions are unified.
873193326Sed  llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
874193326Sed                                        const Decl *Container);
875198092Srdivacky
876193326Sed  /// GetClassName - Return a unique constant for the given selector's
877193326Sed  /// name. The return value has type char *.
878193326Sed  llvm::Constant *GetClassName(IdentifierInfo *Ident);
879198092Srdivacky
880193326Sed  /// BuildIvarLayout - Builds ivar layout bitmap for the class
881193326Sed  /// implementation for the __strong or __weak case.
882193326Sed  ///
883193326Sed  llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
884193326Sed                                  bool ForStrongLayout);
885198092Srdivacky
886193326Sed  void BuildAggrIvarRecordLayout(const RecordType *RT,
887198092Srdivacky                                 unsigned int BytePos, bool ForStrongLayout,
888198092Srdivacky                                 bool &HasUnion);
889193326Sed  void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
890193326Sed                           const llvm::StructLayout *Layout,
891193326Sed                           const RecordDecl *RD,
892193326Sed                           const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
893193326Sed                           unsigned int BytePos, bool ForStrongLayout,
894193326Sed                           bool &HasUnion);
895193326Sed
896193326Sed  /// GetIvarLayoutName - Returns a unique constant for the given
897193326Sed  /// ivar layout bitmap.
898193326Sed  llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
899193326Sed                                    const ObjCCommonTypesHelper &ObjCTypes);
900198092Srdivacky
901193326Sed  /// EmitPropertyList - Emit the given property list. The return
902193326Sed  /// value has type PropertyListPtrTy.
903198398Srdivacky  llvm::Constant *EmitPropertyList(llvm::Twine Name,
904198092Srdivacky                                   const Decl *Container,
905193326Sed                                   const ObjCContainerDecl *OCD,
906193326Sed                                   const ObjCCommonTypesHelper &ObjCTypes);
907198092Srdivacky
908193326Sed  /// GetProtocolRef - Return a reference to the internal protocol
909193326Sed  /// description, creating an empty one if it has not been
910193326Sed  /// defined. The return value has type ProtocolPtrTy.
911193326Sed  llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
912193326Sed
913193326Sed  /// CreateMetadataVar - Create a global variable with internal
914193326Sed  /// linkage for use by the Objective-C runtime.
915193326Sed  ///
916193326Sed  /// This is a convenience wrapper which not only creates the
917193326Sed  /// variable, but also sets the section and alignment and adds the
918198092Srdivacky  /// global to the "llvm.used" list.
919193326Sed  ///
920193326Sed  /// \param Name - The variable name.
921193326Sed  /// \param Init - The variable initializer; this is also used to
922193326Sed  /// define the type of the variable.
923193326Sed  /// \param Section - The section the variable should go into, or 0.
924193326Sed  /// \param Align - The alignment for the variable, or 0.
925193326Sed  /// \param AddToUsed - Whether the variable should be added to
926193326Sed  /// "llvm.used".
927198398Srdivacky  llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
928193326Sed                                          llvm::Constant *Init,
929193326Sed                                          const char *Section,
930193326Sed                                          unsigned Align,
931193326Sed                                          bool AddToUsed);
932193326Sed
933193326Sed  CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
934193326Sed                                        QualType ResultType,
935193326Sed                                        llvm::Value *Sel,
936193326Sed                                        llvm::Value *Arg0,
937193326Sed                                        QualType Arg0Ty,
938193326Sed                                        bool IsSuper,
939193326Sed                                        const CallArgList &CallArgs,
940198092Srdivacky                                        const ObjCMethodDecl *OMD,
941193326Sed                                        const ObjCCommonTypesHelper &ObjCTypes);
942193326Sed
943198092Srdivackypublic:
944198092Srdivacky  CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
945198092Srdivacky    CGM(cgm), VMContext(cgm.getLLVMContext()) { }
946195099Sed
947193326Sed  virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *SL);
948198092Srdivacky
949193326Sed  virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
950193326Sed                                         const ObjCContainerDecl *CD=0);
951198092Srdivacky
952193326Sed  virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
953198092Srdivacky
954193326Sed  /// GetOrEmitProtocol - Get the protocol object for the given
955193326Sed  /// declaration, emitting it if necessary. The return value has type
956193326Sed  /// ProtocolPtrTy.
957193326Sed  virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
958198092Srdivacky
959193326Sed  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
960193326Sed  /// object for the given declaration, emitting it if needed. These
961193326Sed  /// forward references will be filled in with empty bodies if no
962193326Sed  /// definition is seen. The return value has type ProtocolPtrTy.
963193326Sed  virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
964193326Sed};
965198092Srdivacky
966193326Sedclass CGObjCMac : public CGObjCCommonMac {
967193326Sedprivate:
968193326Sed  ObjCTypesHelper ObjCTypes;
969193326Sed  /// EmitImageInfo - Emit the image info marker used to encode some module
970193326Sed  /// level information.
971193326Sed  void EmitImageInfo();
972193326Sed
973193326Sed  /// EmitModuleInfo - Another marker encoding module level
974198092Srdivacky  /// information.
975193326Sed  void EmitModuleInfo();
976193326Sed
977193326Sed  /// EmitModuleSymols - Emit module symbols, the list of defined
978193326Sed  /// classes and categories. The result has type SymtabPtrTy.
979193326Sed  llvm::Constant *EmitModuleSymbols();
980193326Sed
981193326Sed  /// FinishModule - Write out global data structures at the end of
982193326Sed  /// processing a translation unit.
983193326Sed  void FinishModule();
984193326Sed
985193326Sed  /// EmitClassExtension - Generate the class extension structure used
986193326Sed  /// to store the weak ivar layout and properties. The return value
987193326Sed  /// has type ClassExtensionPtrTy.
988193326Sed  llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
989193326Sed
990193326Sed  /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
991193326Sed  /// for the given class.
992198092Srdivacky  llvm::Value *EmitClassRef(CGBuilderTy &Builder,
993193326Sed                            const ObjCInterfaceDecl *ID);
994199482Srdivacky
995199482Srdivacky  /// EmitSuperClassRef - Emits reference to class's main metadata class.
996199482Srdivacky  llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
997193326Sed
998193326Sed  CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
999193326Sed                                  QualType ResultType,
1000193326Sed                                  Selector Sel,
1001193326Sed                                  llvm::Value *Arg0,
1002193326Sed                                  QualType Arg0Ty,
1003193326Sed                                  bool IsSuper,
1004193326Sed                                  const CallArgList &CallArgs);
1005193326Sed
1006193326Sed  /// EmitIvarList - Emit the ivar list for the given
1007193326Sed  /// implementation. If ForClass is true the list of class ivars
1008193326Sed  /// (i.e. metaclass ivars) is emitted, otherwise the list of
1009193326Sed  /// interface ivars will be emitted. The return value has type
1010193326Sed  /// IvarListPtrTy.
1011193326Sed  llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
1012193326Sed                               bool ForClass);
1013198092Srdivacky
1014193326Sed  /// EmitMetaClass - Emit a forward reference to the class structure
1015193326Sed  /// for the metaclass of the given interface. The return value has
1016193326Sed  /// type ClassPtrTy.
1017193326Sed  llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1018193326Sed
1019193326Sed  /// EmitMetaClass - Emit a class structure for the metaclass of the
1020193326Sed  /// given implementation. The return value has type ClassPtrTy.
1021193326Sed  llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1022193326Sed                                llvm::Constant *Protocols,
1023193326Sed                                const ConstantVector &Methods);
1024198092Srdivacky
1025193326Sed  llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
1026198092Srdivacky
1027193326Sed  llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
1028193326Sed
1029193326Sed  /// EmitMethodList - Emit the method list for the given
1030193326Sed  /// implementation. The return value has type MethodListPtrTy.
1031198398Srdivacky  llvm::Constant *EmitMethodList(llvm::Twine Name,
1032193326Sed                                 const char *Section,
1033193326Sed                                 const ConstantVector &Methods);
1034193326Sed
1035193326Sed  /// EmitMethodDescList - Emit a method description list for a list of
1036198092Srdivacky  /// method declarations.
1037193326Sed  ///  - TypeName: The name for the type containing the methods.
1038193326Sed  ///  - IsProtocol: True iff these methods are for a protocol.
1039193326Sed  ///  - ClassMethds: True iff these are class methods.
1040193326Sed  ///  - Required: When true, only "required" methods are
1041193326Sed  ///    listed. Similarly, when false only "optional" methods are
1042193326Sed  ///    listed. For classes this should always be true.
1043193326Sed  ///  - begin, end: The method list to output.
1044193326Sed  ///
1045193326Sed  /// The return value has type MethodDescriptionListPtrTy.
1046198398Srdivacky  llvm::Constant *EmitMethodDescList(llvm::Twine Name,
1047193326Sed                                     const char *Section,
1048193326Sed                                     const ConstantVector &Methods);
1049193326Sed
1050193326Sed  /// GetOrEmitProtocol - Get the protocol object for the given
1051193326Sed  /// declaration, emitting it if necessary. The return value has type
1052193326Sed  /// ProtocolPtrTy.
1053193326Sed  virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
1054193326Sed
1055193326Sed  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1056193326Sed  /// object for the given declaration, emitting it if needed. These
1057193326Sed  /// forward references will be filled in with empty bodies if no
1058193326Sed  /// definition is seen. The return value has type ProtocolPtrTy.
1059193326Sed  virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
1060193326Sed
1061193326Sed  /// EmitProtocolExtension - Generate the protocol extension
1062193326Sed  /// structure used to store optional instance and class methods, and
1063193326Sed  /// protocol properties. The return value has type
1064193326Sed  /// ProtocolExtensionPtrTy.
1065193326Sed  llvm::Constant *
1066193326Sed  EmitProtocolExtension(const ObjCProtocolDecl *PD,
1067193326Sed                        const ConstantVector &OptInstanceMethods,
1068193326Sed                        const ConstantVector &OptClassMethods);
1069193326Sed
1070193326Sed  /// EmitProtocolList - Generate the list of referenced
1071193326Sed  /// protocols. The return value has type ProtocolListPtrTy.
1072198398Srdivacky  llvm::Constant *EmitProtocolList(llvm::Twine Name,
1073193326Sed                                   ObjCProtocolDecl::protocol_iterator begin,
1074193326Sed                                   ObjCProtocolDecl::protocol_iterator end);
1075193326Sed
1076193326Sed  /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1077193326Sed  /// for the given selector.
1078193326Sed  llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
1079198092Srdivacky
1080198092Srdivackypublic:
1081193326Sed  CGObjCMac(CodeGen::CodeGenModule &cgm);
1082193326Sed
1083193326Sed  virtual llvm::Function *ModuleInitFunction();
1084198092Srdivacky
1085193326Sed  virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1086193326Sed                                              QualType ResultType,
1087193326Sed                                              Selector Sel,
1088193326Sed                                              llvm::Value *Receiver,
1089193326Sed                                              bool IsClassMessage,
1090193326Sed                                              const CallArgList &CallArgs,
1091193326Sed                                              const ObjCMethodDecl *Method);
1092193326Sed
1093198092Srdivacky  virtual CodeGen::RValue
1094193326Sed  GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1095193326Sed                           QualType ResultType,
1096193326Sed                           Selector Sel,
1097193326Sed                           const ObjCInterfaceDecl *Class,
1098193326Sed                           bool isCategoryImpl,
1099193326Sed                           llvm::Value *Receiver,
1100193326Sed                           bool IsClassMessage,
1101198092Srdivacky                           const CallArgList &CallArgs,
1102198092Srdivacky                           const ObjCMethodDecl *Method);
1103198092Srdivacky
1104193326Sed  virtual llvm::Value *GetClass(CGBuilderTy &Builder,
1105193326Sed                                const ObjCInterfaceDecl *ID);
1106193326Sed
1107193326Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel);
1108193326Sed
1109193326Sed  /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1110193326Sed  /// untyped one.
1111193326Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1112193326Sed                                   const ObjCMethodDecl *Method);
1113193326Sed
1114193326Sed  virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
1115193326Sed
1116193326Sed  virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
1117193326Sed
1118193326Sed  virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
1119193326Sed                                           const ObjCProtocolDecl *PD);
1120198092Srdivacky
1121193326Sed  virtual llvm::Constant *GetPropertyGetFunction();
1122193326Sed  virtual llvm::Constant *GetPropertySetFunction();
1123193326Sed  virtual llvm::Constant *EnumerationMutationFunction();
1124198092Srdivacky
1125193326Sed  virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1126193326Sed                                         const Stmt &S);
1127193326Sed  virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1128193326Sed                             const ObjCAtThrowStmt &S);
1129193326Sed  virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1130198092Srdivacky                                         llvm::Value *AddrWeakObj);
1131193326Sed  virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1132198092Srdivacky                                  llvm::Value *src, llvm::Value *dst);
1133193326Sed  virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1134193326Sed                                    llvm::Value *src, llvm::Value *dest);
1135193326Sed  virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1136198092Srdivacky                                  llvm::Value *src, llvm::Value *dest,
1137198092Srdivacky                                  llvm::Value *ivarOffset);
1138193326Sed  virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1139193326Sed                                        llvm::Value *src, llvm::Value *dest);
1140198092Srdivacky  virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1141198092Srdivacky                                        llvm::Value *dest, llvm::Value *src,
1142198092Srdivacky                                        QualType Ty);
1143198092Srdivacky
1144193326Sed  virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1145193326Sed                                      QualType ObjectTy,
1146193326Sed                                      llvm::Value *BaseValue,
1147193326Sed                                      const ObjCIvarDecl *Ivar,
1148193326Sed                                      unsigned CVRQualifiers);
1149193326Sed  virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1150193326Sed                                      const ObjCInterfaceDecl *Interface,
1151193326Sed                                      const ObjCIvarDecl *Ivar);
1152193326Sed};
1153198092Srdivacky
1154193326Sedclass CGObjCNonFragileABIMac : public CGObjCCommonMac {
1155193326Sedprivate:
1156193326Sed  ObjCNonFragileABITypesHelper ObjCTypes;
1157193326Sed  llvm::GlobalVariable* ObjCEmptyCacheVar;
1158193326Sed  llvm::GlobalVariable* ObjCEmptyVtableVar;
1159198092Srdivacky
1160193326Sed  /// SuperClassReferences - uniqued super class references.
1161193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
1162198092Srdivacky
1163193326Sed  /// MetaClassReferences - uniqued meta class references.
1164193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
1165193326Sed
1166193326Sed  /// EHTypeReferences - uniqued class ehtype references.
1167193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
1168198092Srdivacky
1169193326Sed  /// NonLegacyDispatchMethods - List of methods for which we do *not* generate
1170193326Sed  /// legacy messaging dispatch.
1171193326Sed  llvm::DenseSet<Selector> NonLegacyDispatchMethods;
1172198092Srdivacky
1173199482Srdivacky  /// DefinedMetaClasses - List of defined meta-classes.
1174199482Srdivacky  std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1175199482Srdivacky
1176193326Sed  /// LegacyDispatchedSelector - Returns true if SEL is not in the list of
1177193326Sed  /// NonLegacyDispatchMethods; false otherwise.
1178193326Sed  bool LegacyDispatchedSelector(Selector Sel);
1179198092Srdivacky
1180193326Sed  /// FinishNonFragileABIModule - Write out global data structures at the end of
1181193326Sed  /// processing a translation unit.
1182193326Sed  void FinishNonFragileABIModule();
1183193326Sed
1184193326Sed  /// AddModuleClassList - Add the given list of class pointers to the
1185193326Sed  /// module with the provided symbol and section names.
1186193326Sed  void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container,
1187193326Sed                          const char *SymbolName,
1188193326Sed                          const char *SectionName);
1189193326Sed
1190198092Srdivacky  llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1191198092Srdivacky                                              unsigned InstanceStart,
1192198092Srdivacky                                              unsigned InstanceSize,
1193198092Srdivacky                                              const ObjCImplementationDecl *ID);
1194193326Sed  llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
1195198092Srdivacky                                            llvm::Constant *IsAGV,
1196193326Sed                                            llvm::Constant *SuperClassGV,
1197193326Sed                                            llvm::Constant *ClassRoGV,
1198193326Sed                                            bool HiddenVisibility);
1199198092Srdivacky
1200193326Sed  llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
1201198092Srdivacky
1202193326Sed  llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
1203198092Srdivacky
1204193326Sed  /// EmitMethodList - Emit the method list for the given
1205193326Sed  /// implementation. The return value has type MethodListnfABITy.
1206198398Srdivacky  llvm::Constant *EmitMethodList(llvm::Twine Name,
1207193326Sed                                 const char *Section,
1208193326Sed                                 const ConstantVector &Methods);
1209193326Sed  /// EmitIvarList - Emit the ivar list for the given
1210193326Sed  /// implementation. If ForClass is true the list of class ivars
1211193326Sed  /// (i.e. metaclass ivars) is emitted, otherwise the list of
1212193326Sed  /// interface ivars will be emitted. The return value has type
1213193326Sed  /// IvarListnfABIPtrTy.
1214193326Sed  llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
1215198092Srdivacky
1216193326Sed  llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
1217193326Sed                                    const ObjCIvarDecl *Ivar,
1218193326Sed                                    unsigned long int offset);
1219198092Srdivacky
1220193326Sed  /// GetOrEmitProtocol - Get the protocol object for the given
1221193326Sed  /// declaration, emitting it if necessary. The return value has type
1222193326Sed  /// ProtocolPtrTy.
1223193326Sed  virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
1224198092Srdivacky
1225193326Sed  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1226193326Sed  /// object for the given declaration, emitting it if needed. These
1227193326Sed  /// forward references will be filled in with empty bodies if no
1228193326Sed  /// definition is seen. The return value has type ProtocolPtrTy.
1229193326Sed  virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
1230198092Srdivacky
1231193326Sed  /// EmitProtocolList - Generate the list of referenced
1232193326Sed  /// protocols. The return value has type ProtocolListPtrTy.
1233198398Srdivacky  llvm::Constant *EmitProtocolList(llvm::Twine Name,
1234193326Sed                                   ObjCProtocolDecl::protocol_iterator begin,
1235193326Sed                                   ObjCProtocolDecl::protocol_iterator end);
1236198092Srdivacky
1237193326Sed  CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1238193326Sed                                  QualType ResultType,
1239193326Sed                                  Selector Sel,
1240193326Sed                                  llvm::Value *Receiver,
1241193326Sed                                  QualType Arg0Ty,
1242193326Sed                                  bool IsSuper,
1243193326Sed                                  const CallArgList &CallArgs);
1244193326Sed
1245193326Sed  /// GetClassGlobal - Return the global variable for the Objective-C
1246193326Sed  /// class of the given name.
1247193326Sed  llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
1248198092Srdivacky
1249193326Sed  /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1250193326Sed  /// for the given class reference.
1251198092Srdivacky  llvm::Value *EmitClassRef(CGBuilderTy &Builder,
1252193326Sed                            const ObjCInterfaceDecl *ID);
1253198092Srdivacky
1254193326Sed  /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1255193326Sed  /// for the given super class reference.
1256198092Srdivacky  llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1257198092Srdivacky                                 const ObjCInterfaceDecl *ID);
1258198092Srdivacky
1259193326Sed  /// EmitMetaClassRef - Return a Value * of the address of _class_t
1260193326Sed  /// meta-data
1261198092Srdivacky  llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
1262193326Sed                                const ObjCInterfaceDecl *ID);
1263193326Sed
1264193326Sed  /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1265193326Sed  /// the given ivar.
1266193326Sed  ///
1267193326Sed  llvm::GlobalVariable * ObjCIvarOffsetVariable(
1268198092Srdivacky    const ObjCInterfaceDecl *ID,
1269198092Srdivacky    const ObjCIvarDecl *Ivar);
1270198092Srdivacky
1271193326Sed  /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1272193326Sed  /// for the given selector.
1273193326Sed  llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
1274193326Sed
1275193326Sed  /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
1276193326Sed  /// interface. The return value has type EHTypePtrTy.
1277193326Sed  llvm::Value *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
1278193326Sed                                  bool ForDefinition);
1279193326Sed
1280198092Srdivacky  const char *getMetaclassSymbolPrefix() const {
1281193326Sed    return "OBJC_METACLASS_$_";
1282193326Sed  }
1283198092Srdivacky
1284193326Sed  const char *getClassSymbolPrefix() const {
1285193326Sed    return "OBJC_CLASS_$_";
1286193326Sed  }
1287193326Sed
1288193326Sed  void GetClassSizeInfo(const ObjCImplementationDecl *OID,
1289193326Sed                        uint32_t &InstanceStart,
1290193326Sed                        uint32_t &InstanceSize);
1291198092Srdivacky
1292193326Sed  // Shamelessly stolen from Analysis/CFRefCount.cpp
1293193326Sed  Selector GetNullarySelector(const char* name) const {
1294193326Sed    IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1295193326Sed    return CGM.getContext().Selectors.getSelector(0, &II);
1296193326Sed  }
1297198092Srdivacky
1298193326Sed  Selector GetUnarySelector(const char* name) const {
1299193326Sed    IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1300193326Sed    return CGM.getContext().Selectors.getSelector(1, &II);
1301193326Sed  }
1302193326Sed
1303193326Sed  /// ImplementationIsNonLazy - Check whether the given category or
1304193326Sed  /// class implementation is "non-lazy".
1305193326Sed  bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
1306193326Sed
1307193326Sedpublic:
1308193326Sed  CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
1309193326Sed  // FIXME. All stubs for now!
1310193326Sed  virtual llvm::Function *ModuleInitFunction();
1311198092Srdivacky
1312193326Sed  virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1313193326Sed                                              QualType ResultType,
1314193326Sed                                              Selector Sel,
1315193326Sed                                              llvm::Value *Receiver,
1316193326Sed                                              bool IsClassMessage,
1317193326Sed                                              const CallArgList &CallArgs,
1318193326Sed                                              const ObjCMethodDecl *Method);
1319198092Srdivacky
1320198092Srdivacky  virtual CodeGen::RValue
1321193326Sed  GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1322193326Sed                           QualType ResultType,
1323193326Sed                           Selector Sel,
1324193326Sed                           const ObjCInterfaceDecl *Class,
1325193326Sed                           bool isCategoryImpl,
1326193326Sed                           llvm::Value *Receiver,
1327193326Sed                           bool IsClassMessage,
1328198092Srdivacky                           const CallArgList &CallArgs,
1329198092Srdivacky                           const ObjCMethodDecl *Method);
1330198092Srdivacky
1331193326Sed  virtual llvm::Value *GetClass(CGBuilderTy &Builder,
1332193326Sed                                const ObjCInterfaceDecl *ID);
1333198092Srdivacky
1334193326Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel)
1335193326Sed    { return EmitSelector(Builder, Sel); }
1336193326Sed
1337193326Sed  /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1338193326Sed  /// untyped one.
1339193326Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1340193326Sed                                   const ObjCMethodDecl *Method)
1341193326Sed    { return EmitSelector(Builder, Method->getSelector()); }
1342198092Srdivacky
1343193326Sed  virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
1344198092Srdivacky
1345193326Sed  virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
1346193326Sed  virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
1347193326Sed                                           const ObjCProtocolDecl *PD);
1348198092Srdivacky
1349198092Srdivacky  virtual llvm::Constant *GetPropertyGetFunction() {
1350193326Sed    return ObjCTypes.getGetPropertyFn();
1351193326Sed  }
1352198092Srdivacky  virtual llvm::Constant *GetPropertySetFunction() {
1353198092Srdivacky    return ObjCTypes.getSetPropertyFn();
1354193326Sed  }
1355193326Sed  virtual llvm::Constant *EnumerationMutationFunction() {
1356193326Sed    return ObjCTypes.getEnumerationMutationFn();
1357193326Sed  }
1358198092Srdivacky
1359193326Sed  virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1360193326Sed                                         const Stmt &S);
1361193326Sed  virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1362193326Sed                             const ObjCAtThrowStmt &S);
1363193326Sed  virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1364193326Sed                                         llvm::Value *AddrWeakObj);
1365193326Sed  virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1366193326Sed                                  llvm::Value *src, llvm::Value *dst);
1367193326Sed  virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1368193326Sed                                    llvm::Value *src, llvm::Value *dest);
1369193326Sed  virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1370198092Srdivacky                                  llvm::Value *src, llvm::Value *dest,
1371198092Srdivacky                                  llvm::Value *ivarOffset);
1372193326Sed  virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1373193326Sed                                        llvm::Value *src, llvm::Value *dest);
1374198092Srdivacky  virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1375198092Srdivacky                                        llvm::Value *dest, llvm::Value *src,
1376198092Srdivacky                                        QualType Ty);
1377193326Sed  virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1378193326Sed                                      QualType ObjectTy,
1379193326Sed                                      llvm::Value *BaseValue,
1380193326Sed                                      const ObjCIvarDecl *Ivar,
1381193326Sed                                      unsigned CVRQualifiers);
1382193326Sed  virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1383193326Sed                                      const ObjCInterfaceDecl *Interface,
1384193326Sed                                      const ObjCIvarDecl *Ivar);
1385193326Sed};
1386198092Srdivacky
1387193326Sed} // end anonymous namespace
1388193326Sed
1389193326Sed/* *** Helper Functions *** */
1390193326Sed
1391193326Sed/// getConstantGEP() - Help routine to construct simple GEPs.
1392198092Srdivackystatic llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
1393198092Srdivacky                                      llvm::Constant *C,
1394193326Sed                                      unsigned idx0,
1395193326Sed                                      unsigned idx1) {
1396193326Sed  llvm::Value *Idxs[] = {
1397198092Srdivacky    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1398198092Srdivacky    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
1399193326Sed  };
1400193326Sed  return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
1401193326Sed}
1402193326Sed
1403193326Sed/// hasObjCExceptionAttribute - Return true if this class or any super
1404193326Sed/// class has the __objc_exception__ attribute.
1405198092Srdivackystatic bool hasObjCExceptionAttribute(ASTContext &Context,
1406194613Sed                                      const ObjCInterfaceDecl *OID) {
1407195341Sed  if (OID->hasAttr<ObjCExceptionAttr>())
1408193326Sed    return true;
1409193326Sed  if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
1410194613Sed    return hasObjCExceptionAttribute(Context, Super);
1411193326Sed  return false;
1412193326Sed}
1413193326Sed
1414193326Sed/* *** CGObjCMac Public Interface *** */
1415198092Srdivacky
1416193326SedCGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
1417198092Srdivacky                                                    ObjCTypes(cgm) {
1418193326Sed  ObjCABI = 1;
1419198092Srdivacky  EmitImageInfo();
1420193326Sed}
1421193326Sed
1422193326Sed/// GetClass - Return a reference to the class for the given interface
1423193326Sed/// decl.
1424193326Sedllvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
1425193326Sed                                 const ObjCInterfaceDecl *ID) {
1426193326Sed  return EmitClassRef(Builder, ID);
1427193326Sed}
1428193326Sed
1429193326Sed/// GetSelector - Return the pointer to the unique'd string for this selector.
1430193326Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) {
1431193326Sed  return EmitSelector(Builder, Sel);
1432193326Sed}
1433193326Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
1434198092Srdivacky                                    *Method) {
1435193326Sed  return EmitSelector(Builder, Method->getSelector());
1436193326Sed}
1437193326Sed
1438193326Sed/// Generate a constant CFString object.
1439198092Srdivacky/*
1440198092Srdivacky  struct __builtin_CFString {
1441198092Srdivacky  const int *isa; // point to __CFConstantStringClassReference
1442198092Srdivacky  int flags;
1443198092Srdivacky  const char *str;
1444198092Srdivacky  long length;
1445198092Srdivacky  };
1446193326Sed*/
1447193326Sed
1448193326Sedllvm::Constant *CGObjCCommonMac::GenerateConstantString(
1449193326Sed  const ObjCStringLiteral *SL) {
1450193326Sed  return CGM.GetAddrOfConstantCFString(SL->getString());
1451193326Sed}
1452193326Sed
1453193326Sed/// Generates a message send where the super is the receiver.  This is
1454193326Sed/// a message send to self with special delivery semantics indicating
1455193326Sed/// which class's method should be called.
1456193326SedCodeGen::RValue
1457193326SedCGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1458193326Sed                                    QualType ResultType,
1459193326Sed                                    Selector Sel,
1460193326Sed                                    const ObjCInterfaceDecl *Class,
1461193326Sed                                    bool isCategoryImpl,
1462193326Sed                                    llvm::Value *Receiver,
1463193326Sed                                    bool IsClassMessage,
1464198092Srdivacky                                    const CodeGen::CallArgList &CallArgs,
1465198092Srdivacky                                    const ObjCMethodDecl *Method) {
1466193326Sed  // Create and init a super structure; this is a (receiver, class)
1467193326Sed  // pair we will pass to objc_msgSendSuper.
1468198092Srdivacky  llvm::Value *ObjCSuper =
1469193326Sed    CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
1470198092Srdivacky  llvm::Value *ReceiverAsObject =
1471193326Sed    CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
1472198092Srdivacky  CGF.Builder.CreateStore(ReceiverAsObject,
1473193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 0));
1474193326Sed
1475193326Sed  // If this is a class message the metaclass is passed as the target.
1476193326Sed  llvm::Value *Target;
1477193326Sed  if (IsClassMessage) {
1478193326Sed    if (isCategoryImpl) {
1479193326Sed      // Message sent to 'super' in a class method defined in a category
1480193326Sed      // implementation requires an odd treatment.
1481193326Sed      // If we are in a class method, we must retrieve the
1482193326Sed      // _metaclass_ for the current class, pointed at by
1483193326Sed      // the class's "isa" pointer.  The following assumes that
1484193326Sed      // isa" is the first ivar in a class (which it must be).
1485193326Sed      Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1486193326Sed      Target = CGF.Builder.CreateStructGEP(Target, 0);
1487193326Sed      Target = CGF.Builder.CreateLoad(Target);
1488198092Srdivacky    } else {
1489193326Sed      llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1490193326Sed      llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1491193326Sed      llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1492193326Sed      Target = Super;
1493198092Srdivacky    }
1494199482Srdivacky  }
1495199482Srdivacky  else if (isCategoryImpl)
1496193326Sed    Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1497199482Srdivacky  else {
1498199482Srdivacky    llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1499199482Srdivacky    ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1500199482Srdivacky    Target = CGF.Builder.CreateLoad(ClassPtr);
1501193326Sed  }
1502193326Sed  // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1503193326Sed  // ObjCTypes types.
1504198092Srdivacky  const llvm::Type *ClassTy =
1505193326Sed    CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
1506193326Sed  Target = CGF.Builder.CreateBitCast(Target, ClassTy);
1507198092Srdivacky  CGF.Builder.CreateStore(Target,
1508193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 1));
1509198092Srdivacky  return EmitLegacyMessageSend(CGF, ResultType,
1510193326Sed                               EmitSelector(CGF.Builder, Sel),
1511193326Sed                               ObjCSuper, ObjCTypes.SuperPtrCTy,
1512198092Srdivacky                               true, CallArgs, Method, ObjCTypes);
1513193326Sed}
1514198092Srdivacky
1515198092Srdivacky/// Generate code for a message send expression.
1516193326SedCodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1517193326Sed                                               QualType ResultType,
1518193326Sed                                               Selector Sel,
1519193326Sed                                               llvm::Value *Receiver,
1520193326Sed                                               bool IsClassMessage,
1521193326Sed                                               const CallArgList &CallArgs,
1522193326Sed                                               const ObjCMethodDecl *Method) {
1523193326Sed  return EmitLegacyMessageSend(CGF, ResultType,
1524193326Sed                               EmitSelector(CGF.Builder, Sel),
1525193326Sed                               Receiver, CGF.getContext().getObjCIdType(),
1526198092Srdivacky                               false, CallArgs, Method, ObjCTypes);
1527193326Sed}
1528193326Sed
1529198092SrdivackyCodeGen::RValue
1530198092SrdivackyCGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
1531198092Srdivacky                                       QualType ResultType,
1532198092Srdivacky                                       llvm::Value *Sel,
1533198092Srdivacky                                       llvm::Value *Arg0,
1534198092Srdivacky                                       QualType Arg0Ty,
1535198092Srdivacky                                       bool IsSuper,
1536198092Srdivacky                                       const CallArgList &CallArgs,
1537198092Srdivacky                                       const ObjCMethodDecl *Method,
1538198092Srdivacky                                       const ObjCCommonTypesHelper &ObjCTypes) {
1539193326Sed  CallArgList ActualArgs;
1540193326Sed  if (!IsSuper)
1541193326Sed    Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
1542193326Sed  ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
1543193326Sed  ActualArgs.push_back(std::make_pair(RValue::get(Sel),
1544193326Sed                                      CGF.getContext().getObjCSelType()));
1545193326Sed  ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
1546198092Srdivacky
1547193326Sed  CodeGenTypes &Types = CGM.getTypes();
1548193326Sed  const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
1549198092Srdivacky  const llvm::FunctionType *FTy =
1550198092Srdivacky    Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
1551198092Srdivacky
1552193326Sed  llvm::Constant *Fn = NULL;
1553193326Sed  if (CGM.ReturnTypeUsesSret(FnInfo)) {
1554193326Sed    Fn = (ObjCABI == 2) ?  ObjCTypes.getSendStretFn2(IsSuper)
1555198092Srdivacky      : ObjCTypes.getSendStretFn(IsSuper);
1556193326Sed  } else if (ResultType->isFloatingType()) {
1557193326Sed    if (ObjCABI == 2) {
1558198092Srdivacky      if (const BuiltinType *BT = ResultType->getAs<BuiltinType>()) {
1559193326Sed        BuiltinType::Kind k = BT->getKind();
1560193326Sed        Fn = (k == BuiltinType::LongDouble) ? ObjCTypes.getSendFpretFn2(IsSuper)
1561198092Srdivacky          : ObjCTypes.getSendFn2(IsSuper);
1562194179Sed      } else {
1563194179Sed        Fn = ObjCTypes.getSendFn2(IsSuper);
1564193326Sed      }
1565198092Srdivacky    } else
1566193326Sed      // FIXME. This currently matches gcc's API for x86-32. May need to change
1567193326Sed      // for others if we have their API.
1568193326Sed      Fn = ObjCTypes.getSendFpretFn(IsSuper);
1569193326Sed  } else {
1570193326Sed    Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
1571198092Srdivacky      : ObjCTypes.getSendFn(IsSuper);
1572193326Sed  }
1573193326Sed  assert(Fn && "EmitLegacyMessageSend - unknown API");
1574198092Srdivacky  Fn = llvm::ConstantExpr::getBitCast(Fn,
1575198092Srdivacky                                      llvm::PointerType::getUnqual(FTy));
1576193326Sed  return CGF.EmitCall(FnInfo, Fn, ActualArgs);
1577193326Sed}
1578193326Sed
1579198092Srdivackyllvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
1580193326Sed                                            const ObjCProtocolDecl *PD) {
1581193326Sed  // FIXME: I don't understand why gcc generates this, or where it is
1582193326Sed  // resolved. Investigate. Its also wasteful to look this up over and over.
1583193326Sed  LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1584193326Sed
1585193326Sed  return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
1586193326Sed                                        ObjCTypes.ExternalProtocolPtrTy);
1587193326Sed}
1588193326Sed
1589193326Sedvoid CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
1590193326Sed  // FIXME: We shouldn't need this, the protocol decl should contain enough
1591193326Sed  // information to tell us whether this was a declaration or a definition.
1592193326Sed  DefinedProtocols.insert(PD->getIdentifier());
1593193326Sed
1594193326Sed  // If we have generated a forward reference to this protocol, emit
1595193326Sed  // it now. Otherwise do nothing, the protocol objects are lazily
1596193326Sed  // emitted.
1597198092Srdivacky  if (Protocols.count(PD->getIdentifier()))
1598193326Sed    GetOrEmitProtocol(PD);
1599193326Sed}
1600193326Sed
1601193326Sedllvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
1602193326Sed  if (DefinedProtocols.count(PD->getIdentifier()))
1603193326Sed    return GetOrEmitProtocol(PD);
1604193326Sed  return GetOrEmitProtocolRef(PD);
1605193326Sed}
1606193326Sed
1607193326Sed/*
1608198092Srdivacky// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1609198092Srdivackystruct _objc_protocol {
1610198092Srdivackystruct _objc_protocol_extension *isa;
1611198092Srdivackychar *protocol_name;
1612198092Srdivackystruct _objc_protocol_list *protocol_list;
1613198092Srdivackystruct _objc__method_prototype_list *instance_methods;
1614198092Srdivackystruct _objc__method_prototype_list *class_methods
1615198092Srdivacky};
1616193326Sed
1617198092SrdivackySee EmitProtocolExtension().
1618193326Sed*/
1619193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1620193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1621193326Sed
1622193326Sed  // Early exit if a defining object has already been generated.
1623193326Sed  if (Entry && Entry->hasInitializer())
1624193326Sed    return Entry;
1625193326Sed
1626193326Sed  // FIXME: I don't understand why gcc generates this, or where it is
1627193326Sed  // resolved. Investigate. Its also wasteful to look this up over and over.
1628193326Sed  LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1629193326Sed
1630193326Sed  // Construct method lists.
1631193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1632193326Sed  std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
1633198092Srdivacky  for (ObjCProtocolDecl::instmeth_iterator
1634195341Sed         i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
1635193326Sed    ObjCMethodDecl *MD = *i;
1636193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
1637193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1638193326Sed      OptInstanceMethods.push_back(C);
1639193326Sed    } else {
1640193326Sed      InstanceMethods.push_back(C);
1641198092Srdivacky    }
1642193326Sed  }
1643193326Sed
1644198092Srdivacky  for (ObjCProtocolDecl::classmeth_iterator
1645195341Sed         i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
1646193326Sed    ObjCMethodDecl *MD = *i;
1647193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
1648193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1649193326Sed      OptClassMethods.push_back(C);
1650193326Sed    } else {
1651193326Sed      ClassMethods.push_back(C);
1652198092Srdivacky    }
1653193326Sed  }
1654193326Sed
1655193326Sed  std::vector<llvm::Constant*> Values(5);
1656193326Sed  Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
1657193326Sed  Values[1] = GetClassName(PD->getIdentifier());
1658198092Srdivacky  Values[2] =
1659198398Srdivacky    EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
1660193326Sed                     PD->protocol_begin(),
1661193326Sed                     PD->protocol_end());
1662198092Srdivacky  Values[3] =
1663198398Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
1664193326Sed                       "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1665193326Sed                       InstanceMethods);
1666198092Srdivacky  Values[4] =
1667198398Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
1668193326Sed                       "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1669193326Sed                       ClassMethods);
1670193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
1671193326Sed                                                   Values);
1672198092Srdivacky
1673193326Sed  if (Entry) {
1674193326Sed    // Already created, fix the linkage and update the initializer.
1675193326Sed    Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
1676193326Sed    Entry->setInitializer(Init);
1677193326Sed  } else {
1678198092Srdivacky    Entry =
1679198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
1680193326Sed                               llvm::GlobalValue::InternalLinkage,
1681198092Srdivacky                               Init,
1682198398Srdivacky                               "\01L_OBJC_PROTOCOL_" + PD->getName());
1683193326Sed    Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
1684193326Sed    Entry->setAlignment(4);
1685193326Sed    // FIXME: Is this necessary? Why only for protocol?
1686193326Sed    Entry->setAlignment(4);
1687193326Sed  }
1688198092Srdivacky  CGM.AddUsedGlobal(Entry);
1689193326Sed
1690193326Sed  return Entry;
1691193326Sed}
1692193326Sed
1693193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
1694193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1695193326Sed
1696193326Sed  if (!Entry) {
1697193326Sed    // We use the initializer as a marker of whether this is a forward
1698193326Sed    // reference or not. At module finalization we add the empty
1699193326Sed    // contents for protocols which were referenced but never defined.
1700198092Srdivacky    Entry =
1701198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
1702193326Sed                               llvm::GlobalValue::ExternalLinkage,
1703193326Sed                               0,
1704198398Srdivacky                               "\01L_OBJC_PROTOCOL_" + PD->getName());
1705193326Sed    Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
1706193326Sed    Entry->setAlignment(4);
1707193326Sed    // FIXME: Is this necessary? Why only for protocol?
1708193326Sed    Entry->setAlignment(4);
1709193326Sed  }
1710198092Srdivacky
1711193326Sed  return Entry;
1712193326Sed}
1713193326Sed
1714193326Sed/*
1715193326Sed  struct _objc_protocol_extension {
1716198092Srdivacky  uint32_t size;
1717198092Srdivacky  struct objc_method_description_list *optional_instance_methods;
1718198092Srdivacky  struct objc_method_description_list *optional_class_methods;
1719198092Srdivacky  struct objc_property_list *instance_properties;
1720193326Sed  };
1721193326Sed*/
1722193326Sedllvm::Constant *
1723193326SedCGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1724193326Sed                                 const ConstantVector &OptInstanceMethods,
1725193326Sed                                 const ConstantVector &OptClassMethods) {
1726198092Srdivacky  uint64_t Size =
1727193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
1728193326Sed  std::vector<llvm::Constant*> Values(4);
1729193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
1730198092Srdivacky  Values[1] =
1731198092Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
1732198398Srdivacky                       + PD->getName(),
1733193326Sed                       "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1734193326Sed                       OptInstanceMethods);
1735198092Srdivacky  Values[2] =
1736198398Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
1737193326Sed                       "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1738193326Sed                       OptClassMethods);
1739198398Srdivacky  Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
1740193326Sed                               0, PD, ObjCTypes);
1741193326Sed
1742193326Sed  // Return null if no extension bits are used.
1743198092Srdivacky  if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
1744193326Sed      Values[3]->isNullValue())
1745193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
1746193326Sed
1747198092Srdivacky  llvm::Constant *Init =
1748193326Sed    llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
1749193326Sed
1750193326Sed  // No special section, but goes in llvm.used
1751198398Srdivacky  return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
1752198092Srdivacky                           Init,
1753193326Sed                           0, 0, true);
1754193326Sed}
1755193326Sed
1756193326Sed/*
1757193326Sed  struct objc_protocol_list {
1758198092Srdivacky  struct objc_protocol_list *next;
1759198092Srdivacky  long count;
1760198092Srdivacky  Protocol *list[];
1761193326Sed  };
1762193326Sed*/
1763193326Sedllvm::Constant *
1764198398SrdivackyCGObjCMac::EmitProtocolList(llvm::Twine Name,
1765193326Sed                            ObjCProtocolDecl::protocol_iterator begin,
1766193326Sed                            ObjCProtocolDecl::protocol_iterator end) {
1767193326Sed  std::vector<llvm::Constant*> ProtocolRefs;
1768193326Sed
1769193326Sed  for (; begin != end; ++begin)
1770193326Sed    ProtocolRefs.push_back(GetProtocolRef(*begin));
1771193326Sed
1772193326Sed  // Just return null for empty protocol lists
1773198092Srdivacky  if (ProtocolRefs.empty())
1774193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1775193326Sed
1776193326Sed  // This list is null terminated.
1777193326Sed  ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
1778193326Sed
1779193326Sed  std::vector<llvm::Constant*> Values(3);
1780193326Sed  // This field is only used by the runtime.
1781193326Sed  Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1782198092Srdivacky  Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
1783198092Srdivacky                                     ProtocolRefs.size() - 1);
1784198092Srdivacky  Values[2] =
1785198092Srdivacky    llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1786198092Srdivacky                                                  ProtocolRefs.size()),
1787193326Sed                             ProtocolRefs);
1788198092Srdivacky
1789198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
1790198092Srdivacky  llvm::GlobalVariable *GV =
1791193326Sed    CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1792193326Sed                      4, false);
1793193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
1794193326Sed}
1795193326Sed
1796193326Sed/*
1797193326Sed  struct _objc_property {
1798198092Srdivacky  const char * const name;
1799198092Srdivacky  const char * const attributes;
1800193326Sed  };
1801193326Sed
1802193326Sed  struct _objc_property_list {
1803198092Srdivacky  uint32_t entsize; // sizeof (struct _objc_property)
1804198092Srdivacky  uint32_t prop_count;
1805198092Srdivacky  struct _objc_property[prop_count];
1806193326Sed  };
1807193326Sed*/
1808198398Srdivackyllvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
1809198092Srdivacky                                       const Decl *Container,
1810198092Srdivacky                                       const ObjCContainerDecl *OCD,
1811198092Srdivacky                                       const ObjCCommonTypesHelper &ObjCTypes) {
1812193326Sed  std::vector<llvm::Constant*> Properties, Prop(2);
1813198092Srdivacky  for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
1814198092Srdivacky         E = OCD->prop_end(); I != E; ++I) {
1815193326Sed    const ObjCPropertyDecl *PD = *I;
1816193326Sed    Prop[0] = GetPropertyName(PD->getIdentifier());
1817193326Sed    Prop[1] = GetPropertyTypeString(PD, Container);
1818193326Sed    Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
1819193326Sed                                                   Prop));
1820193326Sed  }
1821193326Sed
1822193326Sed  // Return null for empty list.
1823193326Sed  if (Properties.empty())
1824193326Sed    return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
1825193326Sed
1826198092Srdivacky  unsigned PropertySize =
1827193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
1828193326Sed  std::vector<llvm::Constant*> Values(3);
1829193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
1830193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
1831198092Srdivacky  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
1832193326Sed                                             Properties.size());
1833193326Sed  Values[2] = llvm::ConstantArray::get(AT, Properties);
1834198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
1835193326Sed
1836198092Srdivacky  llvm::GlobalVariable *GV =
1837198092Srdivacky    CreateMetadataVar(Name, Init,
1838198092Srdivacky                      (ObjCABI == 2) ? "__DATA, __objc_const" :
1839193326Sed                      "__OBJC,__property,regular,no_dead_strip",
1840198092Srdivacky                      (ObjCABI == 2) ? 8 : 4,
1841193326Sed                      true);
1842193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
1843193326Sed}
1844193326Sed
1845193326Sed/*
1846193326Sed  struct objc_method_description_list {
1847198092Srdivacky  int count;
1848198092Srdivacky  struct objc_method_description list[];
1849193326Sed  };
1850193326Sed*/
1851193326Sedllvm::Constant *
1852193326SedCGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
1853193326Sed  std::vector<llvm::Constant*> Desc(2);
1854198092Srdivacky  Desc[0] =
1855198092Srdivacky    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1856198092Srdivacky                                   ObjCTypes.SelectorPtrTy);
1857193326Sed  Desc[1] = GetMethodVarType(MD);
1858193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
1859193326Sed                                   Desc);
1860193326Sed}
1861193326Sed
1862198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
1863193326Sed                                              const char *Section,
1864193326Sed                                              const ConstantVector &Methods) {
1865193326Sed  // Return null for empty list.
1866193326Sed  if (Methods.empty())
1867193326Sed    return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
1868193326Sed
1869193326Sed  std::vector<llvm::Constant*> Values(2);
1870193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
1871198092Srdivacky  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
1872193326Sed                                             Methods.size());
1873193326Sed  Values[1] = llvm::ConstantArray::get(AT, Methods);
1874198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
1875193326Sed
1876193326Sed  llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
1877198092Srdivacky  return llvm::ConstantExpr::getBitCast(GV,
1878193326Sed                                        ObjCTypes.MethodDescriptionListPtrTy);
1879193326Sed}
1880193326Sed
1881193326Sed/*
1882193326Sed  struct _objc_category {
1883198092Srdivacky  char *category_name;
1884198092Srdivacky  char *class_name;
1885198092Srdivacky  struct _objc_method_list *instance_methods;
1886198092Srdivacky  struct _objc_method_list *class_methods;
1887198092Srdivacky  struct _objc_protocol_list *protocols;
1888198092Srdivacky  uint32_t size; // <rdar://4585769>
1889198092Srdivacky  struct _objc_property_list *instance_properties;
1890193326Sed  };
1891198092Srdivacky*/
1892193326Sedvoid CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
1893193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
1894193326Sed
1895193326Sed  // FIXME: This is poor design, the OCD should have a pointer to the category
1896193326Sed  // decl. Additionally, note that Category can be null for the @implementation
1897193326Sed  // w/o an @interface case. Sema should just create one for us as it does for
1898193326Sed  // @implementation so everyone else can live life under a clear blue sky.
1899193326Sed  const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
1900198092Srdivacky  const ObjCCategoryDecl *Category =
1901193326Sed    Interface->FindCategoryDeclaration(OCD->getIdentifier());
1902193326Sed
1903198398Srdivacky  llvm::SmallString<256> ExtName;
1904198398Srdivacky  llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
1905198398Srdivacky                                     << OCD->getName();
1906198398Srdivacky
1907193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1908198092Srdivacky  for (ObjCCategoryImplDecl::instmeth_iterator
1909195341Sed         i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
1910193326Sed    // Instance methods should always be defined.
1911193326Sed    InstanceMethods.push_back(GetMethodConstant(*i));
1912193326Sed  }
1913198092Srdivacky  for (ObjCCategoryImplDecl::classmeth_iterator
1914195341Sed         i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
1915193326Sed    // Class methods should always be defined.
1916193326Sed    ClassMethods.push_back(GetMethodConstant(*i));
1917193326Sed  }
1918193326Sed
1919193326Sed  std::vector<llvm::Constant*> Values(7);
1920193326Sed  Values[0] = GetClassName(OCD->getIdentifier());
1921193326Sed  Values[1] = GetClassName(Interface->getIdentifier());
1922193326Sed  LazySymbols.insert(Interface->getIdentifier());
1923198092Srdivacky  Values[2] =
1924198398Srdivacky    EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
1925193326Sed                   "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1926193326Sed                   InstanceMethods);
1927198092Srdivacky  Values[3] =
1928198398Srdivacky    EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
1929193326Sed                   "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1930193326Sed                   ClassMethods);
1931193326Sed  if (Category) {
1932198092Srdivacky    Values[4] =
1933198398Srdivacky      EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
1934193326Sed                       Category->protocol_begin(),
1935193326Sed                       Category->protocol_end());
1936193326Sed  } else {
1937193326Sed    Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1938193326Sed  }
1939193326Sed  Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
1940193326Sed
1941193326Sed  // If there is no category @interface then there can be no properties.
1942193326Sed  if (Category) {
1943198398Srdivacky    Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
1944193326Sed                                 OCD, Category, ObjCTypes);
1945193326Sed  } else {
1946193326Sed    Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
1947193326Sed  }
1948198092Srdivacky
1949193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
1950193326Sed                                                   Values);
1951193326Sed
1952198092Srdivacky  llvm::GlobalVariable *GV =
1953198398Srdivacky    CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
1954193326Sed                      "__OBJC,__category,regular,no_dead_strip",
1955193326Sed                      4, true);
1956193326Sed  DefinedCategories.push_back(GV);
1957193326Sed}
1958193326Sed
1959193326Sed// FIXME: Get from somewhere?
1960193326Sedenum ClassFlags {
1961193326Sed  eClassFlags_Factory              = 0x00001,
1962193326Sed  eClassFlags_Meta                 = 0x00002,
1963193326Sed  // <rdr://5142207>
1964193326Sed  eClassFlags_HasCXXStructors      = 0x02000,
1965193326Sed  eClassFlags_Hidden               = 0x20000,
1966193326Sed  eClassFlags_ABI2_Hidden          = 0x00010,
1967193326Sed  eClassFlags_ABI2_HasCXXStructors = 0x00004   // <rdr://4923634>
1968193326Sed};
1969193326Sed
1970193326Sed/*
1971193326Sed  struct _objc_class {
1972198092Srdivacky  Class isa;
1973198092Srdivacky  Class super_class;
1974198092Srdivacky  const char *name;
1975198092Srdivacky  long version;
1976198092Srdivacky  long info;
1977198092Srdivacky  long instance_size;
1978198092Srdivacky  struct _objc_ivar_list *ivars;
1979198092Srdivacky  struct _objc_method_list *methods;
1980198092Srdivacky  struct _objc_cache *cache;
1981198092Srdivacky  struct _objc_protocol_list *protocols;
1982198092Srdivacky  // Objective-C 1.0 extensions (<rdr://4585769>)
1983198092Srdivacky  const char *ivar_layout;
1984198092Srdivacky  struct _objc_class_ext *ext;
1985193326Sed  };
1986193326Sed
1987193326Sed  See EmitClassExtension();
1988198092Srdivacky*/
1989193326Sedvoid CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
1990193326Sed  DefinedSymbols.insert(ID->getIdentifier());
1991193326Sed
1992193326Sed  std::string ClassName = ID->getNameAsString();
1993193326Sed  // FIXME: Gross
1994198092Srdivacky  ObjCInterfaceDecl *Interface =
1995193326Sed    const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
1996198092Srdivacky  llvm::Constant *Protocols =
1997198398Srdivacky    EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
1998193326Sed                     Interface->protocol_begin(),
1999193326Sed                     Interface->protocol_end());
2000193326Sed  unsigned Flags = eClassFlags_Factory;
2001198092Srdivacky  unsigned Size =
2002193326Sed    CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8;
2003193326Sed
2004193326Sed  // FIXME: Set CXX-structors flag.
2005193326Sed  if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
2006193326Sed    Flags |= eClassFlags_Hidden;
2007193326Sed
2008193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2009198092Srdivacky  for (ObjCImplementationDecl::instmeth_iterator
2010195341Sed         i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
2011193326Sed    // Instance methods should always be defined.
2012193326Sed    InstanceMethods.push_back(GetMethodConstant(*i));
2013193326Sed  }
2014198092Srdivacky  for (ObjCImplementationDecl::classmeth_iterator
2015195341Sed         i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
2016193326Sed    // Class methods should always be defined.
2017193326Sed    ClassMethods.push_back(GetMethodConstant(*i));
2018193326Sed  }
2019193326Sed
2020198092Srdivacky  for (ObjCImplementationDecl::propimpl_iterator
2021195341Sed         i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
2022193326Sed    ObjCPropertyImplDecl *PID = *i;
2023193326Sed
2024193326Sed    if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2025193326Sed      ObjCPropertyDecl *PD = PID->getPropertyDecl();
2026193326Sed
2027193326Sed      if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
2028193326Sed        if (llvm::Constant *C = GetMethodConstant(MD))
2029193326Sed          InstanceMethods.push_back(C);
2030193326Sed      if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
2031193326Sed        if (llvm::Constant *C = GetMethodConstant(MD))
2032193326Sed          InstanceMethods.push_back(C);
2033193326Sed    }
2034193326Sed  }
2035193326Sed
2036193326Sed  std::vector<llvm::Constant*> Values(12);
2037193326Sed  Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
2038193326Sed  if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
2039193326Sed    // Record a reference to the super class.
2040193326Sed    LazySymbols.insert(Super->getIdentifier());
2041193326Sed
2042198092Srdivacky    Values[ 1] =
2043193326Sed      llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
2044193326Sed                                     ObjCTypes.ClassPtrTy);
2045193326Sed  } else {
2046193326Sed    Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
2047193326Sed  }
2048193326Sed  Values[ 2] = GetClassName(ID->getIdentifier());
2049193326Sed  // Version is always 0.
2050193326Sed  Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2051193326Sed  Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2052193326Sed  Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
2053193326Sed  Values[ 6] = EmitIvarList(ID, false);
2054198092Srdivacky  Values[ 7] =
2055198398Srdivacky    EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
2056193326Sed                   "__OBJC,__inst_meth,regular,no_dead_strip",
2057193326Sed                   InstanceMethods);
2058193326Sed  // cache is always NULL.
2059193326Sed  Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
2060193326Sed  Values[ 9] = Protocols;
2061198092Srdivacky  Values[10] = BuildIvarLayout(ID, true);
2062193326Sed  Values[11] = EmitClassExtension(ID);
2063193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
2064193326Sed                                                   Values);
2065199482Srdivacky  std::string Name("\01L_OBJC_CLASS_");
2066199482Srdivacky  Name += ClassName;
2067199482Srdivacky  const char *Section = "__OBJC,__class,regular,no_dead_strip";
2068199482Srdivacky  // Check for a forward reference.
2069199482Srdivacky  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2070199482Srdivacky  if (GV) {
2071199482Srdivacky    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2072199482Srdivacky           "Forward metaclass reference has incorrect type.");
2073199482Srdivacky    GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2074199482Srdivacky    GV->setInitializer(Init);
2075199482Srdivacky    GV->setSection(Section);
2076199482Srdivacky    GV->setAlignment(4);
2077199482Srdivacky    CGM.AddUsedGlobal(GV);
2078199482Srdivacky  }
2079199482Srdivacky  else
2080199482Srdivacky    GV = CreateMetadataVar(Name, Init, Section, 4, true);
2081193326Sed  DefinedClasses.push_back(GV);
2082193326Sed}
2083193326Sed
2084193326Sedllvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2085193326Sed                                         llvm::Constant *Protocols,
2086193326Sed                                         const ConstantVector &Methods) {
2087193326Sed  unsigned Flags = eClassFlags_Meta;
2088193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
2089193326Sed
2090193326Sed  if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
2091193326Sed    Flags |= eClassFlags_Hidden;
2092198092Srdivacky
2093193326Sed  std::vector<llvm::Constant*> Values(12);
2094193326Sed  // The isa for the metaclass is the root of the hierarchy.
2095193326Sed  const ObjCInterfaceDecl *Root = ID->getClassInterface();
2096193326Sed  while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2097193326Sed    Root = Super;
2098198092Srdivacky  Values[ 0] =
2099193326Sed    llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
2100193326Sed                                   ObjCTypes.ClassPtrTy);
2101193326Sed  // The super class for the metaclass is emitted as the name of the
2102193326Sed  // super class. The runtime fixes this up to point to the
2103193326Sed  // *metaclass* for the super class.
2104193326Sed  if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
2105198092Srdivacky    Values[ 1] =
2106193326Sed      llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
2107193326Sed                                     ObjCTypes.ClassPtrTy);
2108193326Sed  } else {
2109193326Sed    Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
2110193326Sed  }
2111193326Sed  Values[ 2] = GetClassName(ID->getIdentifier());
2112193326Sed  // Version is always 0.
2113193326Sed  Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2114193326Sed  Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2115193326Sed  Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
2116193326Sed  Values[ 6] = EmitIvarList(ID, true);
2117198092Srdivacky  Values[ 7] =
2118193326Sed    EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
2119193326Sed                   "__OBJC,__cls_meth,regular,no_dead_strip",
2120193326Sed                   Methods);
2121193326Sed  // cache is always NULL.
2122193326Sed  Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
2123193326Sed  Values[ 9] = Protocols;
2124193326Sed  // ivar_layout for metaclass is always NULL.
2125193326Sed  Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
2126193326Sed  // The class extension is always unused for metaclasses.
2127193326Sed  Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
2128193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
2129193326Sed                                                   Values);
2130193326Sed
2131193326Sed  std::string Name("\01L_OBJC_METACLASS_");
2132193326Sed  Name += ID->getNameAsCString();
2133193326Sed
2134193326Sed  // Check for a forward reference.
2135193326Sed  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2136193326Sed  if (GV) {
2137193326Sed    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2138193326Sed           "Forward metaclass reference has incorrect type.");
2139193326Sed    GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2140193326Sed    GV->setInitializer(Init);
2141193326Sed  } else {
2142198092Srdivacky    GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2143193326Sed                                  llvm::GlobalValue::InternalLinkage,
2144198092Srdivacky                                  Init, Name);
2145193326Sed  }
2146193326Sed  GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
2147193326Sed  GV->setAlignment(4);
2148198092Srdivacky  CGM.AddUsedGlobal(GV);
2149193326Sed
2150193326Sed  return GV;
2151193326Sed}
2152193326Sed
2153198092Srdivackyllvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
2154193326Sed  std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
2155193326Sed
2156193326Sed  // FIXME: Should we look these up somewhere other than the module. Its a bit
2157193326Sed  // silly since we only generate these while processing an implementation, so
2158193326Sed  // exactly one pointer would work if know when we entered/exitted an
2159193326Sed  // implementation block.
2160193326Sed
2161193326Sed  // Check for an existing forward reference.
2162193326Sed  // Previously, metaclass with internal linkage may have been defined.
2163193326Sed  // pass 'true' as 2nd argument so it is returned.
2164198092Srdivacky  if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2165198092Srdivacky                                                                   true)) {
2166193326Sed    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2167193326Sed           "Forward metaclass reference has incorrect type.");
2168193326Sed    return GV;
2169193326Sed  } else {
2170193326Sed    // Generate as an external reference to keep a consistent
2171193326Sed    // module. This will be patched up when we emit the metaclass.
2172198092Srdivacky    return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2173193326Sed                                    llvm::GlobalValue::ExternalLinkage,
2174193326Sed                                    0,
2175198092Srdivacky                                    Name);
2176193326Sed  }
2177193326Sed}
2178193326Sed
2179199482Srdivackyllvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2180199482Srdivacky  std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2181199482Srdivacky
2182199482Srdivacky  if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2183199482Srdivacky                                                                   true)) {
2184199482Srdivacky    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2185199482Srdivacky           "Forward class metadata reference has incorrect type.");
2186199482Srdivacky    return GV;
2187199482Srdivacky  } else {
2188199482Srdivacky    return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2189199482Srdivacky                                    llvm::GlobalValue::ExternalLinkage,
2190199482Srdivacky                                    0,
2191199482Srdivacky                                    Name);
2192199482Srdivacky  }
2193199482Srdivacky}
2194199482Srdivacky
2195193326Sed/*
2196193326Sed  struct objc_class_ext {
2197198092Srdivacky  uint32_t size;
2198198092Srdivacky  const char *weak_ivar_layout;
2199198092Srdivacky  struct _objc_property_list *properties;
2200193326Sed  };
2201193326Sed*/
2202193326Sedllvm::Constant *
2203193326SedCGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
2204198092Srdivacky  uint64_t Size =
2205193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
2206193326Sed
2207193326Sed  std::vector<llvm::Constant*> Values(3);
2208193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
2209193326Sed  Values[1] = BuildIvarLayout(ID, false);
2210198398Srdivacky  Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
2211193326Sed                               ID, ID->getClassInterface(), ObjCTypes);
2212193326Sed
2213193326Sed  // Return null if no extension bits are used.
2214193326Sed  if (Values[1]->isNullValue() && Values[2]->isNullValue())
2215193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
2216193326Sed
2217198092Srdivacky  llvm::Constant *Init =
2218193326Sed    llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
2219198398Srdivacky  return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
2220198092Srdivacky                           Init, "__OBJC,__class_ext,regular,no_dead_strip",
2221193326Sed                           4, true);
2222193326Sed}
2223193326Sed
2224193326Sed/*
2225193326Sed  struct objc_ivar {
2226198092Srdivacky  char *ivar_name;
2227198092Srdivacky  char *ivar_type;
2228198092Srdivacky  int ivar_offset;
2229193326Sed  };
2230193326Sed
2231193326Sed  struct objc_ivar_list {
2232198092Srdivacky  int ivar_count;
2233198092Srdivacky  struct objc_ivar list[count];
2234193326Sed  };
2235198092Srdivacky*/
2236193326Sedllvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
2237193326Sed                                        bool ForClass) {
2238193326Sed  std::vector<llvm::Constant*> Ivars, Ivar(3);
2239193326Sed
2240193326Sed  // When emitting the root class GCC emits ivar entries for the
2241193326Sed  // actual class structure. It is not clear if we need to follow this
2242193326Sed  // behavior; for now lets try and get away with not doing it. If so,
2243193326Sed  // the cleanest solution would be to make up an ObjCInterfaceDecl
2244193326Sed  // for the class.
2245193326Sed  if (ForClass)
2246193326Sed    return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
2247198092Srdivacky
2248198092Srdivacky  ObjCInterfaceDecl *OID =
2249193326Sed    const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
2250198092Srdivacky
2251193326Sed  llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
2252193576Sed  CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
2253198092Srdivacky
2254193326Sed  for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2255193326Sed    ObjCIvarDecl *IVD = OIvars[i];
2256193576Sed    // Ignore unnamed bit-fields.
2257193576Sed    if (!IVD->getDeclName())
2258198092Srdivacky      continue;
2259193326Sed    Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2260193326Sed    Ivar[1] = GetMethodVarType(IVD);
2261198092Srdivacky    Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
2262193326Sed                                     ComputeIvarBaseOffset(CGM, OID, IVD));
2263193326Sed    Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
2264193326Sed  }
2265193326Sed
2266193326Sed  // Return null for empty list.
2267193326Sed  if (Ivars.empty())
2268193326Sed    return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
2269193326Sed
2270193326Sed  std::vector<llvm::Constant*> Values(2);
2271193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
2272193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
2273193326Sed                                             Ivars.size());
2274193326Sed  Values[1] = llvm::ConstantArray::get(AT, Ivars);
2275198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
2276193326Sed
2277193326Sed  llvm::GlobalVariable *GV;
2278193326Sed  if (ForClass)
2279198398Srdivacky    GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
2280198092Srdivacky                           Init, "__OBJC,__class_vars,regular,no_dead_strip",
2281193326Sed                           4, true);
2282193326Sed  else
2283198398Srdivacky    GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
2284193326Sed                           Init, "__OBJC,__instance_vars,regular,no_dead_strip",
2285193326Sed                           4, true);
2286193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
2287193326Sed}
2288193326Sed
2289193326Sed/*
2290193326Sed  struct objc_method {
2291198092Srdivacky  SEL method_name;
2292198092Srdivacky  char *method_types;
2293198092Srdivacky  void *method;
2294193326Sed  };
2295198092Srdivacky
2296193326Sed  struct objc_method_list {
2297198092Srdivacky  struct objc_method_list *obsolete;
2298198092Srdivacky  int count;
2299198092Srdivacky  struct objc_method methods_list[count];
2300193326Sed  };
2301193326Sed*/
2302193326Sed
2303193326Sed/// GetMethodConstant - Return a struct objc_method constant for the
2304193326Sed/// given method if it has been defined. The result is null if the
2305193326Sed/// method has not been defined. The return value has type MethodPtrTy.
2306193326Sedllvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
2307193326Sed  // FIXME: Use DenseMap::lookup
2308193326Sed  llvm::Function *Fn = MethodDefinitions[MD];
2309193326Sed  if (!Fn)
2310193326Sed    return 0;
2311198092Srdivacky
2312193326Sed  std::vector<llvm::Constant*> Method(3);
2313198092Srdivacky  Method[0] =
2314193326Sed    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
2315193326Sed                                   ObjCTypes.SelectorPtrTy);
2316193326Sed  Method[1] = GetMethodVarType(MD);
2317193326Sed  Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
2318193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
2319193326Sed}
2320193326Sed
2321198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
2322193326Sed                                          const char *Section,
2323193326Sed                                          const ConstantVector &Methods) {
2324193326Sed  // Return null for empty list.
2325193326Sed  if (Methods.empty())
2326193326Sed    return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
2327193326Sed
2328193326Sed  std::vector<llvm::Constant*> Values(3);
2329193326Sed  Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
2330193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
2331193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
2332193326Sed                                             Methods.size());
2333193326Sed  Values[2] = llvm::ConstantArray::get(AT, Methods);
2334198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
2335193326Sed
2336193326Sed  llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
2337193326Sed  return llvm::ConstantExpr::getBitCast(GV,
2338193326Sed                                        ObjCTypes.MethodListPtrTy);
2339193326Sed}
2340193326Sed
2341193326Sedllvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
2342198092Srdivacky                                                const ObjCContainerDecl *CD) {
2343198398Srdivacky  llvm::SmallString<256> Name;
2344193326Sed  GetNameForMethod(OMD, CD, Name);
2345193326Sed
2346193326Sed  CodeGenTypes &Types = CGM.getTypes();
2347193326Sed  const llvm::FunctionType *MethodTy =
2348193326Sed    Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
2349198092Srdivacky  llvm::Function *Method =
2350193326Sed    llvm::Function::Create(MethodTy,
2351193326Sed                           llvm::GlobalValue::InternalLinkage,
2352198398Srdivacky                           Name.str(),
2353193326Sed                           &CGM.getModule());
2354193326Sed  MethodDefinitions.insert(std::make_pair(OMD, Method));
2355193326Sed
2356193326Sed  return Method;
2357193326Sed}
2358193326Sed
2359193326Sedllvm::GlobalVariable *
2360198398SrdivackyCGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
2361193326Sed                                   llvm::Constant *Init,
2362193326Sed                                   const char *Section,
2363193326Sed                                   unsigned Align,
2364193326Sed                                   bool AddToUsed) {
2365193326Sed  const llvm::Type *Ty = Init->getType();
2366198092Srdivacky  llvm::GlobalVariable *GV =
2367198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Ty, false,
2368198092Srdivacky                             llvm::GlobalValue::InternalLinkage, Init, Name);
2369193326Sed  if (Section)
2370193326Sed    GV->setSection(Section);
2371193326Sed  if (Align)
2372193326Sed    GV->setAlignment(Align);
2373193326Sed  if (AddToUsed)
2374198092Srdivacky    CGM.AddUsedGlobal(GV);
2375193326Sed  return GV;
2376193326Sed}
2377193326Sed
2378198092Srdivackyllvm::Function *CGObjCMac::ModuleInitFunction() {
2379193326Sed  // Abuse this interface function as a place to finalize.
2380193326Sed  FinishModule();
2381193326Sed  return NULL;
2382193326Sed}
2383193326Sed
2384193326Sedllvm::Constant *CGObjCMac::GetPropertyGetFunction() {
2385193326Sed  return ObjCTypes.getGetPropertyFn();
2386193326Sed}
2387193326Sed
2388193326Sedllvm::Constant *CGObjCMac::GetPropertySetFunction() {
2389193326Sed  return ObjCTypes.getSetPropertyFn();
2390193326Sed}
2391193326Sed
2392193326Sedllvm::Constant *CGObjCMac::EnumerationMutationFunction() {
2393193326Sed  return ObjCTypes.getEnumerationMutationFn();
2394193326Sed}
2395193326Sed
2396198092Srdivacky/*
2397193326Sed
2398198092Srdivacky  Objective-C setjmp-longjmp (sjlj) Exception Handling
2399198092Srdivacky  --
2400193326Sed
2401198092Srdivacky  The basic framework for a @try-catch-finally is as follows:
2402198092Srdivacky  {
2403193326Sed  objc_exception_data d;
2404193326Sed  id _rethrow = null;
2405193326Sed  bool _call_try_exit = true;
2406198092Srdivacky
2407193326Sed  objc_exception_try_enter(&d);
2408193326Sed  if (!setjmp(d.jmp_buf)) {
2409198092Srdivacky  ... try body ...
2410193326Sed  } else {
2411198092Srdivacky  // exception path
2412198092Srdivacky  id _caught = objc_exception_extract(&d);
2413198092Srdivacky
2414198092Srdivacky  // enter new try scope for handlers
2415198092Srdivacky  if (!setjmp(d.jmp_buf)) {
2416198092Srdivacky  ... match exception and execute catch blocks ...
2417198092Srdivacky
2418198092Srdivacky  // fell off end, rethrow.
2419198092Srdivacky  _rethrow = _caught;
2420198092Srdivacky  ... jump-through-finally to finally_rethrow ...
2421198092Srdivacky  } else {
2422198092Srdivacky  // exception in catch block
2423198092Srdivacky  _rethrow = objc_exception_extract(&d);
2424198092Srdivacky  _call_try_exit = false;
2425198092Srdivacky  ... jump-through-finally to finally_rethrow ...
2426193326Sed  }
2427198092Srdivacky  }
2428193326Sed  ... jump-through-finally to finally_end ...
2429193326Sed
2430198092Srdivacky  finally:
2431193326Sed  if (_call_try_exit)
2432198092Srdivacky  objc_exception_try_exit(&d);
2433193326Sed
2434193326Sed  ... finally block ....
2435193326Sed  ... dispatch to finally destination ...
2436193326Sed
2437198092Srdivacky  finally_rethrow:
2438193326Sed  objc_exception_throw(_rethrow);
2439193326Sed
2440198092Srdivacky  finally_end:
2441198092Srdivacky  }
2442193326Sed
2443198092Srdivacky  This framework differs slightly from the one gcc uses, in that gcc
2444198092Srdivacky  uses _rethrow to determine if objc_exception_try_exit should be called
2445198092Srdivacky  and if the object should be rethrown. This breaks in the face of
2446198092Srdivacky  throwing nil and introduces unnecessary branches.
2447193326Sed
2448198092Srdivacky  We specialize this framework for a few particular circumstances:
2449193326Sed
2450198092Srdivacky  - If there are no catch blocks, then we avoid emitting the second
2451198092Srdivacky  exception handling context.
2452193326Sed
2453198092Srdivacky  - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
2454198092Srdivacky  e)) we avoid emitting the code to rethrow an uncaught exception.
2455193326Sed
2456198092Srdivacky  - FIXME: If there is no @finally block we can do a few more
2457198092Srdivacky  simplifications.
2458193326Sed
2459198092Srdivacky  Rethrows and Jumps-Through-Finally
2460198092Srdivacky  --
2461193326Sed
2462198092Srdivacky  Support for implicit rethrows and jumping through the finally block is
2463198092Srdivacky  handled by storing the current exception-handling context in
2464198092Srdivacky  ObjCEHStack.
2465193326Sed
2466198092Srdivacky  In order to implement proper @finally semantics, we support one basic
2467198092Srdivacky  mechanism for jumping through the finally block to an arbitrary
2468198092Srdivacky  destination. Constructs which generate exits from a @try or @catch
2469198092Srdivacky  block use this mechanism to implement the proper semantics by chaining
2470198092Srdivacky  jumps, as necessary.
2471193326Sed
2472198092Srdivacky  This mechanism works like the one used for indirect goto: we
2473198092Srdivacky  arbitrarily assign an ID to each destination and store the ID for the
2474198092Srdivacky  destination in a variable prior to entering the finally block. At the
2475198092Srdivacky  end of the finally block we simply create a switch to the proper
2476198092Srdivacky  destination.
2477198092Srdivacky
2478198092Srdivacky  Code gen for @synchronized(expr) stmt;
2479198092Srdivacky  Effectively generating code for:
2480198092Srdivacky  objc_sync_enter(expr);
2481198092Srdivacky  @try stmt @finally { objc_sync_exit(expr); }
2482193326Sed*/
2483193326Sed
2484193326Sedvoid CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2485193326Sed                                          const Stmt &S) {
2486193326Sed  bool isTry = isa<ObjCAtTryStmt>(S);
2487193326Sed  // Create various blocks we refer to for handling @finally.
2488193326Sed  llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
2489193326Sed  llvm::BasicBlock *FinallyExit = CGF.createBasicBlock("finally.exit");
2490193326Sed  llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit");
2491193326Sed  llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
2492193326Sed  llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
2493198092Srdivacky
2494193326Sed  // For @synchronized, call objc_sync_enter(sync.expr). The
2495193326Sed  // evaluation of the expression must occur before we enter the
2496193326Sed  // @synchronized. We can safely avoid a temp here because jumps into
2497193326Sed  // @synchronized are illegal & this will dominate uses.
2498193326Sed  llvm::Value *SyncArg = 0;
2499193326Sed  if (!isTry) {
2500198092Srdivacky    SyncArg =
2501193326Sed      CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2502193326Sed    SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
2503193326Sed    CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg);
2504193326Sed  }
2505193326Sed
2506193326Sed  // Push an EH context entry, used for handling rethrows and jumps
2507193326Sed  // through finally.
2508193326Sed  CGF.PushCleanupBlock(FinallyBlock);
2509193326Sed
2510193326Sed  CGF.ObjCEHValueStack.push_back(0);
2511198092Srdivacky
2512193326Sed  // Allocate memory for the exception data and rethrow pointer.
2513193326Sed  llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2514193326Sed                                                    "exceptiondata.ptr");
2515198092Srdivacky  llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy,
2516193326Sed                                                 "_rethrow");
2517198092Srdivacky  llvm::Value *CallTryExitPtr = CGF.CreateTempAlloca(
2518198092Srdivacky                                               llvm::Type::getInt1Ty(VMContext),
2519193326Sed                                                     "_call_try_exit");
2520198092Srdivacky  CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext),
2521198092Srdivacky                          CallTryExitPtr);
2522198092Srdivacky
2523193326Sed  // Enter a new try block and call setjmp.
2524193326Sed  CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData);
2525198092Srdivacky  llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0,
2526193326Sed                                                       "jmpbufarray");
2527193326Sed  JmpBufPtr = CGF.Builder.CreateStructGEP(JmpBufPtr, 0, "tmp");
2528193326Sed  llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(),
2529193326Sed                                                     JmpBufPtr, "result");
2530193326Sed
2531193326Sed  llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
2532193326Sed  llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
2533198092Srdivacky  CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"),
2534193326Sed                           TryHandler, TryBlock);
2535193326Sed
2536193326Sed  // Emit the @try block.
2537193326Sed  CGF.EmitBlock(TryBlock);
2538198092Srdivacky  CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
2539198092Srdivacky               : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
2540193326Sed  CGF.EmitBranchThroughCleanup(FinallyEnd);
2541198092Srdivacky
2542193326Sed  // Emit the "exception in @try" block.
2543193326Sed  CGF.EmitBlock(TryHandler);
2544193326Sed
2545193326Sed  // Retrieve the exception object.  We may emit multiple blocks but
2546193326Sed  // nothing can cross this so the value is already in SSA form.
2547193326Sed  llvm::Value *Caught =
2548193326Sed    CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
2549193326Sed                           ExceptionData, "caught");
2550193326Sed  CGF.ObjCEHValueStack.back() = Caught;
2551198092Srdivacky  if (!isTry) {
2552193326Sed    CGF.Builder.CreateStore(Caught, RethrowPtr);
2553198092Srdivacky    CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext),
2554198092Srdivacky                            CallTryExitPtr);
2555193326Sed    CGF.EmitBranchThroughCleanup(FinallyRethrow);
2556198092Srdivacky  } else if (const ObjCAtCatchStmt* CatchStmt =
2557198092Srdivacky             cast<ObjCAtTryStmt>(S).getCatchStmts()) {
2558193326Sed    // Enter a new exception try block (in case a @catch block throws
2559193326Sed    // an exception).
2560193326Sed    CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData);
2561198092Srdivacky
2562193326Sed    llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(),
2563193326Sed                                                       JmpBufPtr, "result");
2564193326Sed    llvm::Value *Threw = CGF.Builder.CreateIsNotNull(SetJmpResult, "threw");
2565193326Sed
2566193326Sed    llvm::BasicBlock *CatchBlock = CGF.createBasicBlock("catch");
2567193326Sed    llvm::BasicBlock *CatchHandler = CGF.createBasicBlock("catch.handler");
2568193326Sed    CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
2569198092Srdivacky
2570193326Sed    CGF.EmitBlock(CatchBlock);
2571198092Srdivacky
2572193326Sed    // Handle catch list. As a special case we check if everything is
2573193326Sed    // matched and avoid generating code for falling off the end if
2574193326Sed    // so.
2575193326Sed    bool AllMatched = false;
2576193326Sed    for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
2577193326Sed      llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch");
2578193326Sed
2579193326Sed      const ParmVarDecl *CatchParam = CatchStmt->getCatchParamDecl();
2580198092Srdivacky      const ObjCObjectPointerType *OPT = 0;
2581193326Sed
2582193326Sed      // catch(...) always matches.
2583193326Sed      if (!CatchParam) {
2584193326Sed        AllMatched = true;
2585193326Sed      } else {
2586198092Srdivacky        OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
2587198092Srdivacky
2588198092Srdivacky        // catch(id e) always matches.
2589193326Sed        // FIXME: For the time being we also match id<X>; this should
2590193326Sed        // be rejected by Sema instead.
2591198092Srdivacky        if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
2592193326Sed          AllMatched = true;
2593193326Sed      }
2594198092Srdivacky
2595198092Srdivacky      if (AllMatched) {
2596193326Sed        if (CatchParam) {
2597193326Sed          CGF.EmitLocalBlockVarDecl(*CatchParam);
2598193326Sed          assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
2599193326Sed          CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
2600193326Sed        }
2601198092Srdivacky
2602193326Sed        CGF.EmitStmt(CatchStmt->getCatchBody());
2603193326Sed        CGF.EmitBranchThroughCleanup(FinallyEnd);
2604193326Sed        break;
2605193326Sed      }
2606198092Srdivacky
2607198092Srdivacky      assert(OPT && "Unexpected non-object pointer type in @catch");
2608198092Srdivacky      QualType T = OPT->getPointeeType();
2609198092Srdivacky      const ObjCInterfaceType *ObjCType = T->getAs<ObjCInterfaceType>();
2610193326Sed      assert(ObjCType && "Catch parameter must have Objective-C type!");
2611193326Sed
2612193326Sed      // Check if the @catch block matches the exception object.
2613193326Sed      llvm::Value *Class = EmitClassRef(CGF.Builder, ObjCType->getDecl());
2614198092Srdivacky
2615193326Sed      llvm::Value *Match =
2616193326Sed        CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
2617193326Sed                                Class, Caught, "match");
2618198092Srdivacky
2619193326Sed      llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("matched");
2620198092Srdivacky
2621198092Srdivacky      CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
2622193326Sed                               MatchedBlock, NextCatchBlock);
2623198092Srdivacky
2624193326Sed      // Emit the @catch block.
2625193326Sed      CGF.EmitBlock(MatchedBlock);
2626193326Sed      CGF.EmitLocalBlockVarDecl(*CatchParam);
2627193326Sed      assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
2628193326Sed
2629198092Srdivacky      llvm::Value *Tmp =
2630198092Srdivacky        CGF.Builder.CreateBitCast(Caught,
2631198092Srdivacky                                  CGF.ConvertType(CatchParam->getType()),
2632193326Sed                                  "tmp");
2633193326Sed      CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
2634198092Srdivacky
2635193326Sed      CGF.EmitStmt(CatchStmt->getCatchBody());
2636193326Sed      CGF.EmitBranchThroughCleanup(FinallyEnd);
2637198092Srdivacky
2638193326Sed      CGF.EmitBlock(NextCatchBlock);
2639193326Sed    }
2640193326Sed
2641193326Sed    if (!AllMatched) {
2642193326Sed      // None of the handlers caught the exception, so store it to be
2643193326Sed      // rethrown at the end of the @finally block.
2644193326Sed      CGF.Builder.CreateStore(Caught, RethrowPtr);
2645193326Sed      CGF.EmitBranchThroughCleanup(FinallyRethrow);
2646193326Sed    }
2647198092Srdivacky
2648193326Sed    // Emit the exception handler for the @catch blocks.
2649198092Srdivacky    CGF.EmitBlock(CatchHandler);
2650193326Sed    CGF.Builder.CreateStore(
2651198092Srdivacky      CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
2652198092Srdivacky                             ExceptionData),
2653198092Srdivacky      RethrowPtr);
2654198092Srdivacky    CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext),
2655198092Srdivacky                            CallTryExitPtr);
2656193326Sed    CGF.EmitBranchThroughCleanup(FinallyRethrow);
2657193326Sed  } else {
2658193326Sed    CGF.Builder.CreateStore(Caught, RethrowPtr);
2659198092Srdivacky    CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext),
2660198092Srdivacky                            CallTryExitPtr);
2661193326Sed    CGF.EmitBranchThroughCleanup(FinallyRethrow);
2662193326Sed  }
2663198092Srdivacky
2664193326Sed  // Pop the exception-handling stack entry. It is important to do
2665193326Sed  // this now, because the code in the @finally block is not in this
2666193326Sed  // context.
2667193326Sed  CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
2668193326Sed
2669193326Sed  CGF.ObjCEHValueStack.pop_back();
2670198092Srdivacky
2671193326Sed  // Emit the @finally block.
2672193326Sed  CGF.EmitBlock(FinallyBlock);
2673193326Sed  llvm::Value* CallTryExit = CGF.Builder.CreateLoad(CallTryExitPtr, "tmp");
2674198092Srdivacky
2675193326Sed  CGF.Builder.CreateCondBr(CallTryExit, FinallyExit, FinallyNoExit);
2676198092Srdivacky
2677193326Sed  CGF.EmitBlock(FinallyExit);
2678193326Sed  CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData);
2679193326Sed
2680193326Sed  CGF.EmitBlock(FinallyNoExit);
2681193326Sed  if (isTry) {
2682198092Srdivacky    if (const ObjCAtFinallyStmt* FinallyStmt =
2683198092Srdivacky        cast<ObjCAtTryStmt>(S).getFinallyStmt())
2684193326Sed      CGF.EmitStmt(FinallyStmt->getFinallyBody());
2685193326Sed  } else {
2686193326Sed    // Emit objc_sync_exit(expr); as finally's sole statement for
2687193326Sed    // @synchronized.
2688193326Sed    CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg);
2689193326Sed  }
2690193326Sed
2691193326Sed  // Emit the switch block
2692193326Sed  if (Info.SwitchBlock)
2693193326Sed    CGF.EmitBlock(Info.SwitchBlock);
2694193326Sed  if (Info.EndBlock)
2695193326Sed    CGF.EmitBlock(Info.EndBlock);
2696198092Srdivacky
2697193326Sed  CGF.EmitBlock(FinallyRethrow);
2698198092Srdivacky  CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(),
2699193326Sed                         CGF.Builder.CreateLoad(RethrowPtr));
2700193326Sed  CGF.Builder.CreateUnreachable();
2701198092Srdivacky
2702193326Sed  CGF.EmitBlock(FinallyEnd);
2703193326Sed}
2704193326Sed
2705193326Sedvoid CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
2706193326Sed                              const ObjCAtThrowStmt &S) {
2707193326Sed  llvm::Value *ExceptionAsObject;
2708198092Srdivacky
2709193326Sed  if (const Expr *ThrowExpr = S.getThrowExpr()) {
2710193326Sed    llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
2711198092Srdivacky    ExceptionAsObject =
2712193326Sed      CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
2713193326Sed  } else {
2714198092Srdivacky    assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
2715193326Sed           "Unexpected rethrow outside @catch block.");
2716193326Sed    ExceptionAsObject = CGF.ObjCEHValueStack.back();
2717193326Sed  }
2718198092Srdivacky
2719193326Sed  CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject);
2720193326Sed  CGF.Builder.CreateUnreachable();
2721193326Sed
2722193326Sed  // Clear the insertion point to indicate we are in unreachable code.
2723193326Sed  CGF.Builder.ClearInsertionPoint();
2724193326Sed}
2725193326Sed
2726193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak
2727193326Sed/// object: objc_read_weak (id *src)
2728193326Sed///
2729193326Sedllvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
2730198092Srdivacky                                          llvm::Value *AddrWeakObj) {
2731193326Sed  const llvm::Type* DestTy =
2732198092Srdivacky    cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
2733198092Srdivacky  AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
2734198092Srdivacky                                          ObjCTypes.PtrObjectPtrTy);
2735193326Sed  llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
2736193326Sed                                                  AddrWeakObj, "weakread");
2737193326Sed  read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
2738193326Sed  return read_weak;
2739193326Sed}
2740193326Sed
2741193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
2742193326Sed/// objc_assign_weak (id src, id *dst)
2743193326Sed///
2744193326Sedvoid CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
2745198092Srdivacky                                   llvm::Value *src, llvm::Value *dst) {
2746193326Sed  const llvm::Type * SrcTy = src->getType();
2747193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
2748193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
2749193326Sed    assert(Size <= 8 && "does not support size > 8");
2750193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2751198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2752193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2753193326Sed  }
2754193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2755193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2756193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
2757193326Sed                          src, dst, "weakassign");
2758193326Sed  return;
2759193326Sed}
2760193326Sed
2761193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
2762193326Sed/// objc_assign_global (id src, id *dst)
2763193326Sed///
2764193326Sedvoid CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
2765198092Srdivacky                                     llvm::Value *src, llvm::Value *dst) {
2766193326Sed  const llvm::Type * SrcTy = src->getType();
2767193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
2768193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
2769193326Sed    assert(Size <= 8 && "does not support size > 8");
2770193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2771198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2772193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2773193326Sed  }
2774193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2775193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2776193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
2777193326Sed                          src, dst, "globalassign");
2778193326Sed  return;
2779193326Sed}
2780193326Sed
2781193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
2782198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
2783193326Sed///
2784193326Sedvoid CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
2785198092Srdivacky                                   llvm::Value *src, llvm::Value *dst,
2786198092Srdivacky                                   llvm::Value *ivarOffset) {
2787198092Srdivacky  assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
2788193326Sed  const llvm::Type * SrcTy = src->getType();
2789193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
2790193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
2791193326Sed    assert(Size <= 8 && "does not support size > 8");
2792193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2793198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2794193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2795193326Sed  }
2796193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2797193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2798198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
2799198092Srdivacky                          src, dst, ivarOffset);
2800193326Sed  return;
2801193326Sed}
2802193326Sed
2803193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
2804193326Sed/// objc_assign_strongCast (id src, id *dst)
2805193326Sed///
2806193326Sedvoid CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
2807198092Srdivacky                                         llvm::Value *src, llvm::Value *dst) {
2808193326Sed  const llvm::Type * SrcTy = src->getType();
2809193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
2810193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
2811193326Sed    assert(Size <= 8 && "does not support size > 8");
2812193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2813198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2814193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2815193326Sed  }
2816193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2817193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2818193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
2819193326Sed                          src, dst, "weakassign");
2820193326Sed  return;
2821193326Sed}
2822193326Sed
2823198092Srdivackyvoid CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
2824198092Srdivacky                                         llvm::Value *DestPtr,
2825198092Srdivacky                                         llvm::Value *SrcPtr,
2826198092Srdivacky                                         QualType Ty) {
2827198092Srdivacky  // Get size info for this aggregate.
2828198092Srdivacky  std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty);
2829198092Srdivacky  unsigned long size = TypeInfo.first/8;
2830198092Srdivacky  SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
2831198092Srdivacky  DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
2832198092Srdivacky  llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size);
2833198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
2834198092Srdivacky                          DestPtr, SrcPtr, N);
2835198092Srdivacky  return;
2836198092Srdivacky}
2837198092Srdivacky
2838193326Sed/// EmitObjCValueForIvar - Code Gen for ivar reference.
2839193326Sed///
2840193326SedLValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
2841193326Sed                                       QualType ObjectTy,
2842193326Sed                                       llvm::Value *BaseValue,
2843193326Sed                                       const ObjCIvarDecl *Ivar,
2844193326Sed                                       unsigned CVRQualifiers) {
2845198092Srdivacky  const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl();
2846193326Sed  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
2847193326Sed                                  EmitIvarOffset(CGF, ID, Ivar));
2848193326Sed}
2849193326Sed
2850193326Sedllvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
2851193326Sed                                       const ObjCInterfaceDecl *Interface,
2852193326Sed                                       const ObjCIvarDecl *Ivar) {
2853193326Sed  uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
2854193326Sed  return llvm::ConstantInt::get(
2855198092Srdivacky    CGM.getTypes().ConvertType(CGM.getContext().LongTy),
2856198092Srdivacky    Offset);
2857193326Sed}
2858193326Sed
2859193326Sed/* *** Private Interface *** */
2860193326Sed
2861193326Sed/// EmitImageInfo - Emit the image info marker used to encode some module
2862193326Sed/// level information.
2863193326Sed///
2864193326Sed/// See: <rdr://4810609&4810587&4810587>
2865193326Sed/// struct IMAGE_INFO {
2866193326Sed///   unsigned version;
2867193326Sed///   unsigned flags;
2868193326Sed/// };
2869193326Sedenum ImageInfoFlags {
2870193326Sed  eImageInfo_FixAndContinue      = (1 << 0), // FIXME: Not sure what
2871193326Sed                                             // this implies.
2872198092Srdivacky  eImageInfo_GarbageCollected    = (1 << 1),
2873198092Srdivacky  eImageInfo_GCOnly              = (1 << 2),
2874193326Sed  eImageInfo_OptimizedByDyld     = (1 << 3), // FIXME: When is this set.
2875193326Sed
2876193326Sed  // A flag indicating that the module has no instances of an
2877193326Sed  // @synthesize of a superclass variable. <rdar://problem/6803242>
2878193326Sed  eImageInfo_CorrectedSynthesize = (1 << 4)
2879193326Sed};
2880193326Sed
2881193326Sedvoid CGObjCMac::EmitImageInfo() {
2882193326Sed  unsigned version = 0; // Version is unused?
2883193326Sed  unsigned flags = 0;
2884193326Sed
2885193326Sed  // FIXME: Fix and continue?
2886193326Sed  if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
2887193326Sed    flags |= eImageInfo_GarbageCollected;
2888193326Sed  if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
2889193326Sed    flags |= eImageInfo_GCOnly;
2890198092Srdivacky
2891193326Sed  // We never allow @synthesize of a superclass property.
2892193326Sed  flags |= eImageInfo_CorrectedSynthesize;
2893193326Sed
2894193326Sed  // Emitted as int[2];
2895193326Sed  llvm::Constant *values[2] = {
2896198092Srdivacky    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), version),
2897198092Srdivacky    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), flags)
2898193326Sed  };
2899198092Srdivacky  llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext), 2);
2900193326Sed
2901193326Sed  const char *Section;
2902193326Sed  if (ObjCABI == 1)
2903193326Sed    Section = "__OBJC, __image_info,regular";
2904193326Sed  else
2905193326Sed    Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
2906198092Srdivacky  llvm::GlobalVariable *GV =
2907193326Sed    CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
2908193326Sed                      llvm::ConstantArray::get(AT, values, 2),
2909193326Sed                      Section,
2910193326Sed                      0,
2911193326Sed                      true);
2912193326Sed  GV->setConstant(true);
2913193326Sed}
2914193326Sed
2915193326Sed
2916193326Sed// struct objc_module {
2917193326Sed//   unsigned long version;
2918193326Sed//   unsigned long size;
2919193326Sed//   const char *name;
2920193326Sed//   Symtab symtab;
2921193326Sed// };
2922193326Sed
2923193326Sed// FIXME: Get from somewhere
2924193326Sedstatic const int ModuleVersion = 7;
2925193326Sed
2926193326Sedvoid CGObjCMac::EmitModuleInfo() {
2927193326Sed  uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
2928198092Srdivacky
2929193326Sed  std::vector<llvm::Constant*> Values(4);
2930193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
2931193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
2932193326Sed  // This used to be the filename, now it is unused. <rdr://4327263>
2933193326Sed  Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
2934193326Sed  Values[3] = EmitModuleSymbols();
2935198092Srdivacky  CreateMetadataVar("\01L_OBJC_MODULES",
2936193326Sed                    llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
2937193326Sed                    "__OBJC,__module_info,regular,no_dead_strip",
2938193326Sed                    4, true);
2939193326Sed}
2940193326Sed
2941193326Sedllvm::Constant *CGObjCMac::EmitModuleSymbols() {
2942193326Sed  unsigned NumClasses = DefinedClasses.size();
2943193326Sed  unsigned NumCategories = DefinedCategories.size();
2944193326Sed
2945193326Sed  // Return null if no symbols were defined.
2946193326Sed  if (!NumClasses && !NumCategories)
2947193326Sed    return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
2948193326Sed
2949193326Sed  std::vector<llvm::Constant*> Values(5);
2950193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2951193326Sed  Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
2952193326Sed  Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
2953193326Sed  Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
2954193326Sed
2955193326Sed  // The runtime expects exactly the list of defined classes followed
2956193326Sed  // by the list of defined categories, in a single array.
2957193326Sed  std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
2958193326Sed  for (unsigned i=0; i<NumClasses; i++)
2959193326Sed    Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
2960193326Sed                                                ObjCTypes.Int8PtrTy);
2961193326Sed  for (unsigned i=0; i<NumCategories; i++)
2962198092Srdivacky    Symbols[NumClasses + i] =
2963193326Sed      llvm::ConstantExpr::getBitCast(DefinedCategories[i],
2964193326Sed                                     ObjCTypes.Int8PtrTy);
2965193326Sed
2966198092Srdivacky  Values[4] =
2967193326Sed    llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
2968193326Sed                                                  NumClasses + NumCategories),
2969193326Sed                             Symbols);
2970193326Sed
2971198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
2972193326Sed
2973193326Sed  llvm::GlobalVariable *GV =
2974193326Sed    CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
2975193326Sed                      "__OBJC,__symbols,regular,no_dead_strip",
2976193326Sed                      4, true);
2977193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
2978193326Sed}
2979193326Sed
2980198092Srdivackyllvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
2981193326Sed                                     const ObjCInterfaceDecl *ID) {
2982193326Sed  LazySymbols.insert(ID->getIdentifier());
2983193326Sed
2984193326Sed  llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
2985198092Srdivacky
2986193326Sed  if (!Entry) {
2987198092Srdivacky    llvm::Constant *Casted =
2988193326Sed      llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
2989193326Sed                                     ObjCTypes.ClassPtrTy);
2990198092Srdivacky    Entry =
2991193326Sed      CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
2992193326Sed                        "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
2993193326Sed                        4, true);
2994193326Sed  }
2995193326Sed
2996193326Sed  return Builder.CreateLoad(Entry, false, "tmp");
2997193326Sed}
2998193326Sed
2999193326Sedllvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) {
3000193326Sed  llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
3001198092Srdivacky
3002193326Sed  if (!Entry) {
3003198092Srdivacky    llvm::Constant *Casted =
3004193326Sed      llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
3005193326Sed                                     ObjCTypes.SelectorPtrTy);
3006198092Srdivacky    Entry =
3007193326Sed      CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3008193326Sed                        "__OBJC,__message_refs,literal_pointers,no_dead_strip",
3009193326Sed                        4, true);
3010193326Sed  }
3011193326Sed
3012193326Sed  return Builder.CreateLoad(Entry, false, "tmp");
3013193326Sed}
3014193326Sed
3015193326Sedllvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
3016193326Sed  llvm::GlobalVariable *&Entry = ClassNames[Ident];
3017193326Sed
3018193326Sed  if (!Entry)
3019198092Srdivacky    Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3020198398Srdivacky                          llvm::ConstantArray::get(VMContext,
3021198398Srdivacky                                                   Ident->getNameStart()),
3022193326Sed                              "__TEXT,__cstring,cstring_literals",
3023193326Sed                              1, true);
3024193326Sed
3025198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3026193326Sed}
3027193326Sed
3028193326Sed/// GetIvarLayoutName - Returns a unique constant for the given
3029193326Sed/// ivar layout bitmap.
3030193326Sedllvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
3031198092Srdivacky                                       const ObjCCommonTypesHelper &ObjCTypes) {
3032193326Sed  return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
3033193326Sed}
3034193326Sed
3035198092Srdivackystatic Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
3036193326Sed  if (FQT.isObjCGCStrong())
3037198092Srdivacky    return Qualifiers::Strong;
3038193326Sed
3039193326Sed  if (FQT.isObjCGCWeak())
3040198092Srdivacky    return Qualifiers::Weak;
3041193326Sed
3042198092Srdivacky  if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
3043198092Srdivacky    return Qualifiers::Strong;
3044193326Sed
3045198092Srdivacky  if (const PointerType *PT = FQT->getAs<PointerType>())
3046193326Sed    return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
3047193326Sed
3048198092Srdivacky  return Qualifiers::GCNone;
3049193326Sed}
3050193326Sed
3051193326Sedvoid CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
3052198092Srdivacky                                                unsigned int BytePos,
3053193326Sed                                                bool ForStrongLayout,
3054193326Sed                                                bool &HasUnion) {
3055193326Sed  const RecordDecl *RD = RT->getDecl();
3056193326Sed  // FIXME - Use iterator.
3057195341Sed  llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
3058193326Sed  const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
3059198092Srdivacky  const llvm::StructLayout *RecLayout =
3060193326Sed    CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
3061198092Srdivacky
3062193326Sed  BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3063193326Sed                      ForStrongLayout, HasUnion);
3064193326Sed}
3065193326Sed
3066193326Sedvoid CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
3067198092Srdivacky                             const llvm::StructLayout *Layout,
3068198092Srdivacky                             const RecordDecl *RD,
3069193326Sed                             const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
3070198092Srdivacky                             unsigned int BytePos, bool ForStrongLayout,
3071198092Srdivacky                             bool &HasUnion) {
3072193326Sed  bool IsUnion = (RD && RD->isUnion());
3073193326Sed  uint64_t MaxUnionIvarSize = 0;
3074193326Sed  uint64_t MaxSkippedUnionIvarSize = 0;
3075193326Sed  FieldDecl *MaxField = 0;
3076193326Sed  FieldDecl *MaxSkippedField = 0;
3077193326Sed  FieldDecl *LastFieldBitfield = 0;
3078193326Sed  uint64_t MaxFieldOffset = 0;
3079193326Sed  uint64_t MaxSkippedFieldOffset = 0;
3080193326Sed  uint64_t LastBitfieldOffset = 0;
3081198092Srdivacky
3082193326Sed  if (RecFields.empty())
3083193326Sed    return;
3084193326Sed  unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3085193326Sed  unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3086193326Sed
3087193326Sed  for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
3088193326Sed    FieldDecl *Field = RecFields[i];
3089193326Sed    uint64_t FieldOffset;
3090198092Srdivacky    if (RD) {
3091198092Srdivacky      if (Field->isBitField()) {
3092198092Srdivacky        CodeGenTypes::BitFieldInfo Info = CGM.getTypes().getBitFieldInfo(Field);
3093198092Srdivacky
3094198092Srdivacky        const llvm::Type *Ty =
3095198092Srdivacky          CGM.getTypes().ConvertTypeForMemRecursive(Field->getType());
3096198092Srdivacky        uint64_t TypeSize =
3097198092Srdivacky          CGM.getTypes().getTargetData().getTypeAllocSize(Ty);
3098198092Srdivacky        FieldOffset = Info.FieldNo * TypeSize;
3099198092Srdivacky      } else
3100198092Srdivacky        FieldOffset =
3101198092Srdivacky          Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
3102198092Srdivacky    } else
3103193326Sed      FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
3104193326Sed
3105193326Sed    // Skip over unnamed or bitfields
3106193326Sed    if (!Field->getIdentifier() || Field->isBitField()) {
3107193326Sed      LastFieldBitfield = Field;
3108193326Sed      LastBitfieldOffset = FieldOffset;
3109193326Sed      continue;
3110193326Sed    }
3111193326Sed
3112193326Sed    LastFieldBitfield = 0;
3113193326Sed    QualType FQT = Field->getType();
3114193326Sed    if (FQT->isRecordType() || FQT->isUnionType()) {
3115193326Sed      if (FQT->isUnionType())
3116193326Sed        HasUnion = true;
3117193326Sed
3118198092Srdivacky      BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
3119193326Sed                                BytePos + FieldOffset,
3120193326Sed                                ForStrongLayout, HasUnion);
3121193326Sed      continue;
3122193326Sed    }
3123198092Srdivacky
3124193326Sed    if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3125198092Srdivacky      const ConstantArrayType *CArray =
3126193326Sed        dyn_cast_or_null<ConstantArrayType>(Array);
3127193326Sed      uint64_t ElCount = CArray->getSize().getZExtValue();
3128193326Sed      assert(CArray && "only array with known element size is supported");
3129193326Sed      FQT = CArray->getElementType();
3130193326Sed      while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3131193326Sed        const ConstantArrayType *CArray =
3132193326Sed          dyn_cast_or_null<ConstantArrayType>(Array);
3133193326Sed        ElCount *= CArray->getSize().getZExtValue();
3134193326Sed        FQT = CArray->getElementType();
3135193326Sed      }
3136198092Srdivacky
3137198092Srdivacky      assert(!FQT->isUnionType() &&
3138193326Sed             "layout for array of unions not supported");
3139193326Sed      if (FQT->isRecordType()) {
3140193326Sed        int OldIndex = IvarsInfo.size() - 1;
3141193326Sed        int OldSkIndex = SkipIvars.size() -1;
3142198092Srdivacky
3143198092Srdivacky        const RecordType *RT = FQT->getAs<RecordType>();
3144193326Sed        BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
3145193326Sed                                  ForStrongLayout, HasUnion);
3146198092Srdivacky
3147193326Sed        // Replicate layout information for each array element. Note that
3148193326Sed        // one element is already done.
3149193326Sed        uint64_t ElIx = 1;
3150198092Srdivacky        for (int FirstIndex = IvarsInfo.size() - 1,
3151198092Srdivacky               FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
3152193326Sed          uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
3153193326Sed          for (int i = OldIndex+1; i <= FirstIndex; ++i)
3154193326Sed            IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
3155193326Sed                                        IvarsInfo[i].ivar_size));
3156193326Sed          for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
3157193326Sed            SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
3158193326Sed                                        SkipIvars[i].ivar_size));
3159193326Sed        }
3160193326Sed        continue;
3161193326Sed      }
3162193326Sed    }
3163193326Sed    // At this point, we are done with Record/Union and array there of.
3164193326Sed    // For other arrays we are down to its element type.
3165198092Srdivacky    Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
3166193326Sed
3167193326Sed    unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
3168198092Srdivacky    if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3169198092Srdivacky        || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
3170193326Sed      if (IsUnion) {
3171193326Sed        uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
3172193326Sed        if (UnionIvarSize > MaxUnionIvarSize) {
3173193326Sed          MaxUnionIvarSize = UnionIvarSize;
3174193326Sed          MaxField = Field;
3175193326Sed          MaxFieldOffset = FieldOffset;
3176193326Sed        }
3177193326Sed      } else {
3178193326Sed        IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
3179193326Sed                                    FieldSize / WordSizeInBits));
3180193326Sed      }
3181198092Srdivacky    } else if ((ForStrongLayout &&
3182198092Srdivacky                (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3183198092Srdivacky               || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
3184193326Sed      if (IsUnion) {
3185193326Sed        // FIXME: Why the asymmetry? We divide by word size in bits on other
3186193326Sed        // side.
3187193326Sed        uint64_t UnionIvarSize = FieldSize;
3188193326Sed        if (UnionIvarSize > MaxSkippedUnionIvarSize) {
3189193326Sed          MaxSkippedUnionIvarSize = UnionIvarSize;
3190193326Sed          MaxSkippedField = Field;
3191193326Sed          MaxSkippedFieldOffset = FieldOffset;
3192193326Sed        }
3193193326Sed      } else {
3194193326Sed        // FIXME: Why the asymmetry, we divide by byte size in bits here?
3195193326Sed        SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
3196193326Sed                                    FieldSize / ByteSizeInBits));
3197193326Sed      }
3198193326Sed    }
3199193326Sed  }
3200193326Sed
3201193326Sed  if (LastFieldBitfield) {
3202193326Sed    // Last field was a bitfield. Must update skip info.
3203193326Sed    Expr *BitWidth = LastFieldBitfield->getBitWidth();
3204193326Sed    uint64_t BitFieldSize =
3205193326Sed      BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
3206193326Sed    GC_IVAR skivar;
3207193326Sed    skivar.ivar_bytepos = BytePos + LastBitfieldOffset;
3208198092Srdivacky    skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3209198092Srdivacky      + ((BitFieldSize % ByteSizeInBits) != 0);
3210198092Srdivacky    SkipIvars.push_back(skivar);
3211193326Sed  }
3212198092Srdivacky
3213193326Sed  if (MaxField)
3214198092Srdivacky    IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
3215193326Sed                                MaxUnionIvarSize));
3216193326Sed  if (MaxSkippedField)
3217193326Sed    SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
3218193326Sed                                MaxSkippedUnionIvarSize));
3219193326Sed}
3220193326Sed
3221193326Sed/// BuildIvarLayout - Builds ivar layout bitmap for the class
3222193326Sed/// implementation for the __strong or __weak case.
3223198092Srdivacky/// The layout map displays which words in ivar list must be skipped
3224198092Srdivacky/// and which must be scanned by GC (see below). String is built of bytes.
3225198092Srdivacky/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
3226193326Sed/// of words to skip and right nibble is count of words to scan. So, each
3227198092Srdivacky/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
3228193326Sed/// represented by a 0x00 byte which also ends the string.
3229193326Sed/// 1. when ForStrongLayout is true, following ivars are scanned:
3230193326Sed/// - id, Class
3231193326Sed/// - object *
3232193326Sed/// - __strong anything
3233198092Srdivacky///
3234193326Sed/// 2. When ForStrongLayout is false, following ivars are scanned:
3235193326Sed/// - __weak anything
3236193326Sed///
3237193326Sedllvm::Constant *CGObjCCommonMac::BuildIvarLayout(
3238198092Srdivacky  const ObjCImplementationDecl *OMD,
3239198092Srdivacky  bool ForStrongLayout) {
3240193326Sed  bool hasUnion = false;
3241198092Srdivacky
3242193326Sed  unsigned int WordsToScan, WordsToSkip;
3243198092Srdivacky  const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
3244193326Sed  if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
3245193326Sed    return llvm::Constant::getNullValue(PtrTy);
3246198092Srdivacky
3247193326Sed  llvm::SmallVector<FieldDecl*, 32> RecFields;
3248193326Sed  const ObjCInterfaceDecl *OI = OMD->getClassInterface();
3249193326Sed  CGM.getContext().CollectObjCIvars(OI, RecFields);
3250198092Srdivacky
3251193326Sed  // Add this implementations synthesized ivars.
3252193326Sed  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
3253193326Sed  CGM.getContext().CollectSynthesizedIvars(OI, Ivars);
3254193326Sed  for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
3255193326Sed    RecFields.push_back(cast<FieldDecl>(Ivars[k]));
3256198092Srdivacky
3257193326Sed  if (RecFields.empty())
3258193326Sed    return llvm::Constant::getNullValue(PtrTy);
3259198092Srdivacky
3260198092Srdivacky  SkipIvars.clear();
3261193326Sed  IvarsInfo.clear();
3262198092Srdivacky
3263193326Sed  BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
3264193326Sed  if (IvarsInfo.empty())
3265193326Sed    return llvm::Constant::getNullValue(PtrTy);
3266198092Srdivacky
3267193326Sed  // Sort on byte position in case we encounterred a union nested in
3268193326Sed  // the ivar list.
3269193326Sed  if (hasUnion && !IvarsInfo.empty())
3270193326Sed    std::sort(IvarsInfo.begin(), IvarsInfo.end());
3271193326Sed  if (hasUnion && !SkipIvars.empty())
3272193326Sed    std::sort(SkipIvars.begin(), SkipIvars.end());
3273198092Srdivacky
3274193326Sed  // Build the string of skip/scan nibbles
3275193326Sed  llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
3276198092Srdivacky  unsigned int WordSize =
3277193326Sed    CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
3278193326Sed  if (IvarsInfo[0].ivar_bytepos == 0) {
3279193326Sed    WordsToSkip = 0;
3280193326Sed    WordsToScan = IvarsInfo[0].ivar_size;
3281193326Sed  } else {
3282193326Sed    WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3283193326Sed    WordsToScan = IvarsInfo[0].ivar_size;
3284193326Sed  }
3285193326Sed  for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
3286198092Srdivacky    unsigned int TailPrevGCObjC =
3287193326Sed      IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
3288193326Sed    if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
3289193326Sed      // consecutive 'scanned' object pointers.
3290193326Sed      WordsToScan += IvarsInfo[i].ivar_size;
3291193326Sed    } else {
3292193326Sed      // Skip over 'gc'able object pointer which lay over each other.
3293193326Sed      if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
3294193326Sed        continue;
3295193326Sed      // Must skip over 1 or more words. We save current skip/scan values
3296193326Sed      //  and start a new pair.
3297193326Sed      SKIP_SCAN SkScan;
3298193326Sed      SkScan.skip = WordsToSkip;
3299193326Sed      SkScan.scan = WordsToScan;
3300193326Sed      SkipScanIvars.push_back(SkScan);
3301198092Srdivacky
3302193326Sed      // Skip the hole.
3303193326Sed      SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3304193326Sed      SkScan.scan = 0;
3305193326Sed      SkipScanIvars.push_back(SkScan);
3306193326Sed      WordsToSkip = 0;
3307193326Sed      WordsToScan = IvarsInfo[i].ivar_size;
3308193326Sed    }
3309193326Sed  }
3310193326Sed  if (WordsToScan > 0) {
3311193326Sed    SKIP_SCAN SkScan;
3312193326Sed    SkScan.skip = WordsToSkip;
3313193326Sed    SkScan.scan = WordsToScan;
3314193326Sed    SkipScanIvars.push_back(SkScan);
3315193326Sed  }
3316198092Srdivacky
3317193326Sed  bool BytesSkipped = false;
3318193326Sed  if (!SkipIvars.empty()) {
3319193326Sed    unsigned int LastIndex = SkipIvars.size()-1;
3320198092Srdivacky    int LastByteSkipped =
3321198092Srdivacky      SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
3322193326Sed    LastIndex = IvarsInfo.size()-1;
3323198092Srdivacky    int LastByteScanned =
3324198092Srdivacky      IvarsInfo[LastIndex].ivar_bytepos +
3325198092Srdivacky      IvarsInfo[LastIndex].ivar_size * WordSize;
3326193326Sed    BytesSkipped = (LastByteSkipped > LastByteScanned);
3327193326Sed    // Compute number of bytes to skip at the tail end of the last ivar scanned.
3328193326Sed    if (BytesSkipped) {
3329193326Sed      unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
3330193326Sed      SKIP_SCAN SkScan;
3331193326Sed      SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3332193326Sed      SkScan.scan = 0;
3333193326Sed      SkipScanIvars.push_back(SkScan);
3334193326Sed    }
3335193326Sed  }
3336193326Sed  // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3337193326Sed  // as 0xMN.
3338193326Sed  int SkipScan = SkipScanIvars.size()-1;
3339193326Sed  for (int i = 0; i <= SkipScan; i++) {
3340193326Sed    if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3341193326Sed        && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3342193326Sed      // 0xM0 followed by 0x0N detected.
3343193326Sed      SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
3344193326Sed      for (int j = i+1; j < SkipScan; j++)
3345193326Sed        SkipScanIvars[j] = SkipScanIvars[j+1];
3346193326Sed      --SkipScan;
3347193326Sed    }
3348193326Sed  }
3349198092Srdivacky
3350193326Sed  // Generate the string.
3351193326Sed  std::string BitMap;
3352193326Sed  for (int i = 0; i <= SkipScan; i++) {
3353193326Sed    unsigned char byte;
3354193326Sed    unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
3355193326Sed    unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
3356193326Sed    unsigned int skip_big  = SkipScanIvars[i].skip / 0xf;
3357193326Sed    unsigned int scan_big  = SkipScanIvars[i].scan / 0xf;
3358193326Sed
3359193326Sed    if (skip_small > 0 || skip_big > 0)
3360193326Sed      BytesSkipped = true;
3361193326Sed    // first skip big.
3362193326Sed    for (unsigned int ix = 0; ix < skip_big; ix++)
3363193326Sed      BitMap += (unsigned char)(0xf0);
3364198092Srdivacky
3365193326Sed    // next (skip small, scan)
3366193326Sed    if (skip_small) {
3367193326Sed      byte = skip_small << 4;
3368193326Sed      if (scan_big > 0) {
3369193326Sed        byte |= 0xf;
3370193326Sed        --scan_big;
3371193326Sed      } else if (scan_small) {
3372193326Sed        byte |= scan_small;
3373193326Sed        scan_small = 0;
3374193326Sed      }
3375193326Sed      BitMap += byte;
3376193326Sed    }
3377193326Sed    // next scan big
3378193326Sed    for (unsigned int ix = 0; ix < scan_big; ix++)
3379193326Sed      BitMap += (unsigned char)(0x0f);
3380193326Sed    // last scan small
3381193326Sed    if (scan_small) {
3382193326Sed      byte = scan_small;
3383193326Sed      BitMap += byte;
3384193326Sed    }
3385193326Sed  }
3386193326Sed  // null terminate string.
3387193326Sed  unsigned char zero = 0;
3388193326Sed  BitMap += zero;
3389198092Srdivacky
3390193326Sed  if (CGM.getLangOptions().ObjCGCBitmapPrint) {
3391198092Srdivacky    printf("\n%s ivar layout for class '%s': ",
3392193326Sed           ForStrongLayout ? "strong" : "weak",
3393193326Sed           OMD->getClassInterface()->getNameAsCString());
3394193326Sed    const unsigned char *s = (unsigned char*)BitMap.c_str();
3395193326Sed    for (unsigned i = 0; i < BitMap.size(); i++)
3396193326Sed      if (!(s[i] & 0xf0))
3397193326Sed        printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
3398193326Sed      else
3399193326Sed        printf("0x%x%s",  s[i], s[i] != 0 ? ", " : "");
3400193326Sed    printf("\n");
3401193326Sed  }
3402198092Srdivacky  llvm::GlobalVariable * Entry =
3403198092Srdivacky    CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3404198092Srdivacky                      llvm::ConstantArray::get(VMContext, BitMap.c_str()),
3405198092Srdivacky                      "__TEXT,__cstring,cstring_literals",
3406198092Srdivacky                      1, true);
3407198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3408193326Sed}
3409193326Sed
3410193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
3411193326Sed  llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3412193326Sed
3413193326Sed  // FIXME: Avoid std::string copying.
3414193326Sed  if (!Entry)
3415198092Srdivacky    Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
3416198092Srdivacky                        llvm::ConstantArray::get(VMContext, Sel.getAsString()),
3417193326Sed                              "__TEXT,__cstring,cstring_literals",
3418193326Sed                              1, true);
3419193326Sed
3420198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3421193326Sed}
3422193326Sed
3423193326Sed// FIXME: Merge into a single cstring creation function.
3424193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
3425193326Sed  return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
3426193326Sed}
3427193326Sed
3428193326Sed// FIXME: Merge into a single cstring creation function.
3429193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) {
3430193326Sed  return GetMethodVarName(&CGM.getContext().Idents.get(Name));
3431193326Sed}
3432193326Sed
3433193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
3434193326Sed  std::string TypeStr;
3435193326Sed  CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
3436193326Sed
3437193326Sed  llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3438193326Sed
3439193326Sed  if (!Entry)
3440193326Sed    Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
3441198092Srdivacky                              llvm::ConstantArray::get(VMContext, TypeStr),
3442193326Sed                              "__TEXT,__cstring,cstring_literals",
3443193326Sed                              1, true);
3444198092Srdivacky
3445198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3446193326Sed}
3447193326Sed
3448193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
3449193326Sed  std::string TypeStr;
3450193326Sed  CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
3451193326Sed                                                TypeStr);
3452193326Sed
3453193326Sed  llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3454193326Sed
3455193326Sed  if (!Entry)
3456193326Sed    Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
3457198092Srdivacky                              llvm::ConstantArray::get(VMContext, TypeStr),
3458193326Sed                              "__TEXT,__cstring,cstring_literals",
3459193326Sed                              1, true);
3460193326Sed
3461198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3462193326Sed}
3463193326Sed
3464193326Sed// FIXME: Merge into a single cstring creation function.
3465193326Sedllvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
3466193326Sed  llvm::GlobalVariable *&Entry = PropertyNames[Ident];
3467198092Srdivacky
3468193326Sed  if (!Entry)
3469198092Srdivacky    Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
3470198398Srdivacky                          llvm::ConstantArray::get(VMContext,
3471198398Srdivacky                                                   Ident->getNameStart()),
3472193326Sed                              "__TEXT,__cstring,cstring_literals",
3473193326Sed                              1, true);
3474193326Sed
3475198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3476193326Sed}
3477193326Sed
3478193326Sed// FIXME: Merge into a single cstring creation function.
3479193326Sed// FIXME: This Decl should be more precise.
3480193326Sedllvm::Constant *
3481198092SrdivackyCGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
3482198092Srdivacky                                       const Decl *Container) {
3483193326Sed  std::string TypeStr;
3484193326Sed  CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
3485193326Sed  return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
3486193326Sed}
3487193326Sed
3488198092Srdivackyvoid CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
3489193326Sed                                       const ObjCContainerDecl *CD,
3490198398Srdivacky                                       llvm::SmallVectorImpl<char> &Name) {
3491198398Srdivacky  llvm::raw_svector_ostream OS(Name);
3492193326Sed  assert (CD && "Missing container decl in GetNameForMethod");
3493198398Srdivacky  OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
3494198398Srdivacky     << '[' << CD->getName();
3495198092Srdivacky  if (const ObjCCategoryImplDecl *CID =
3496198398Srdivacky      dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
3497198398Srdivacky    OS << '(' << CID->getNameAsString() << ')';
3498198398Srdivacky  OS << ' ' << D->getSelector().getAsString() << ']';
3499193326Sed}
3500193326Sed
3501193326Sedvoid CGObjCMac::FinishModule() {
3502193326Sed  EmitModuleInfo();
3503193326Sed
3504193326Sed  // Emit the dummy bodies for any protocols which were referenced but
3505193326Sed  // never defined.
3506198092Srdivacky  for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
3507198092Srdivacky         I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
3508198092Srdivacky    if (I->second->hasInitializer())
3509193326Sed      continue;
3510193326Sed
3511193326Sed    std::vector<llvm::Constant*> Values(5);
3512193326Sed    Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3513198092Srdivacky    Values[1] = GetClassName(I->first);
3514193326Sed    Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3515193326Sed    Values[3] = Values[4] =
3516193326Sed      llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
3517198092Srdivacky    I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
3518198092Srdivacky    I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
3519193326Sed                                                        Values));
3520198092Srdivacky    CGM.AddUsedGlobal(I->second);
3521193326Sed  }
3522193326Sed
3523193326Sed  // Add assembler directives to add lazy undefined symbol references
3524193326Sed  // for classes which are referenced but not defined. This is
3525193326Sed  // important for correct linker interaction.
3526198092Srdivacky  //
3527198092Srdivacky  // FIXME: It would be nice if we had an LLVM construct for this.
3528198092Srdivacky  if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
3529198092Srdivacky    llvm::SmallString<256> Asm;
3530198092Srdivacky    Asm += CGM.getModule().getModuleInlineAsm();
3531198092Srdivacky    if (!Asm.empty() && Asm.back() != '\n')
3532198092Srdivacky      Asm += '\n';
3533193326Sed
3534198092Srdivacky    llvm::raw_svector_ostream OS(Asm);
3535198092Srdivacky    for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
3536198092Srdivacky           e = LazySymbols.end(); I != e; ++I)
3537198092Srdivacky      OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
3538198092Srdivacky    for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
3539198092Srdivacky           e = DefinedSymbols.end(); I != e; ++I)
3540198092Srdivacky      OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
3541198092Srdivacky         << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
3542198092Srdivacky
3543198092Srdivacky    CGM.getModule().setModuleInlineAsm(OS.str());
3544193326Sed  }
3545193326Sed}
3546193326Sed
3547198092SrdivackyCGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
3548193326Sed  : CGObjCCommonMac(cgm),
3549198092Srdivacky    ObjCTypes(cgm) {
3550193326Sed  ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
3551193326Sed  ObjCABI = 2;
3552193326Sed}
3553193326Sed
3554193326Sed/* *** */
3555193326Sed
3556193326SedObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
3557198092Srdivacky  : VMContext(cgm.getLLVMContext()), CGM(cgm) {
3558193326Sed  CodeGen::CodeGenTypes &Types = CGM.getTypes();
3559193326Sed  ASTContext &Ctx = CGM.getContext();
3560198092Srdivacky
3561193326Sed  ShortTy = Types.ConvertType(Ctx.ShortTy);
3562193326Sed  IntTy = Types.ConvertType(Ctx.IntTy);
3563193326Sed  LongTy = Types.ConvertType(Ctx.LongTy);
3564193326Sed  LongLongTy = Types.ConvertType(Ctx.LongLongTy);
3565198092Srdivacky  Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
3566198092Srdivacky
3567193326Sed  ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
3568193326Sed  PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
3569193326Sed  SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
3570198092Srdivacky
3571193326Sed  // FIXME: It would be nice to unify this with the opaque type, so that the IR
3572193326Sed  // comes out a bit cleaner.
3573193326Sed  const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
3574193326Sed  ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
3575198092Srdivacky
3576193326Sed  // I'm not sure I like this. The implicit coordination is a bit
3577193326Sed  // gross. We should solve this in a reasonable fashion because this
3578193326Sed  // is a pretty common task (match some runtime data structure with
3579193326Sed  // an LLVM data structure).
3580198092Srdivacky
3581193326Sed  // FIXME: This is leaked.
3582193326Sed  // FIXME: Merge with rewriter code?
3583198092Srdivacky
3584193326Sed  // struct _objc_super {
3585193326Sed  //   id self;
3586193326Sed  //   Class cls;
3587193326Sed  // }
3588193326Sed  RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
3589193326Sed                                      SourceLocation(),
3590198092Srdivacky                                      &Ctx.Idents.get("_objc_super"));
3591195341Sed  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
3592198092Srdivacky                                Ctx.getObjCIdType(), 0, 0, false));
3593198092Srdivacky  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
3594198092Srdivacky                                Ctx.getObjCClassType(), 0, 0, false));
3595193326Sed  RD->completeDefinition(Ctx);
3596198092Srdivacky
3597193326Sed  SuperCTy = Ctx.getTagDeclType(RD);
3598193326Sed  SuperPtrCTy = Ctx.getPointerType(SuperCTy);
3599198092Srdivacky
3600193326Sed  SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
3601198092Srdivacky  SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
3602198092Srdivacky
3603193326Sed  // struct _prop_t {
3604193326Sed  //   char *name;
3605198092Srdivacky  //   char *attributes;
3606193326Sed  // }
3607198092Srdivacky  PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
3608198092Srdivacky  CGM.getModule().addTypeName("struct._prop_t",
3609193326Sed                              PropertyTy);
3610198092Srdivacky
3611193326Sed  // struct _prop_list_t {
3612193326Sed  //   uint32_t entsize;      // sizeof(struct _prop_t)
3613193326Sed  //   uint32_t count_of_properties;
3614193326Sed  //   struct _prop_t prop_list[count_of_properties];
3615193326Sed  // }
3616198092Srdivacky  PropertyListTy = llvm::StructType::get(VMContext, IntTy,
3617193326Sed                                         IntTy,
3618193326Sed                                         llvm::ArrayType::get(PropertyTy, 0),
3619193326Sed                                         NULL);
3620198092Srdivacky  CGM.getModule().addTypeName("struct._prop_list_t",
3621193326Sed                              PropertyListTy);
3622193326Sed  // struct _prop_list_t *
3623193326Sed  PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
3624198092Srdivacky
3625193326Sed  // struct _objc_method {
3626193326Sed  //   SEL _cmd;
3627193326Sed  //   char *method_type;
3628193326Sed  //   char *_imp;
3629193326Sed  // }
3630198092Srdivacky  MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
3631193326Sed                                   Int8PtrTy,
3632193326Sed                                   Int8PtrTy,
3633193326Sed                                   NULL);
3634193326Sed  CGM.getModule().addTypeName("struct._objc_method", MethodTy);
3635198092Srdivacky
3636193326Sed  // struct _objc_cache *
3637198092Srdivacky  CacheTy = llvm::OpaqueType::get(VMContext);
3638193326Sed  CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
3639193326Sed  CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
3640193326Sed}
3641193326Sed
3642198092SrdivackyObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
3643198092Srdivacky  : ObjCCommonTypesHelper(cgm) {
3644193326Sed  // struct _objc_method_description {
3645193326Sed  //   SEL name;
3646193326Sed  //   char *types;
3647193326Sed  // }
3648198092Srdivacky  MethodDescriptionTy =
3649198092Srdivacky    llvm::StructType::get(VMContext, SelectorPtrTy,
3650193326Sed                          Int8PtrTy,
3651193326Sed                          NULL);
3652198092Srdivacky  CGM.getModule().addTypeName("struct._objc_method_description",
3653193326Sed                              MethodDescriptionTy);
3654193326Sed
3655193326Sed  // struct _objc_method_description_list {
3656193326Sed  //   int count;
3657193326Sed  //   struct _objc_method_description[1];
3658193326Sed  // }
3659198092Srdivacky  MethodDescriptionListTy =
3660198092Srdivacky    llvm::StructType::get(VMContext, IntTy,
3661193326Sed                          llvm::ArrayType::get(MethodDescriptionTy, 0),
3662193326Sed                          NULL);
3663198092Srdivacky  CGM.getModule().addTypeName("struct._objc_method_description_list",
3664193326Sed                              MethodDescriptionListTy);
3665198092Srdivacky
3666193326Sed  // struct _objc_method_description_list *
3667198092Srdivacky  MethodDescriptionListPtrTy =
3668193326Sed    llvm::PointerType::getUnqual(MethodDescriptionListTy);
3669193326Sed
3670193326Sed  // Protocol description structures
3671193326Sed
3672193326Sed  // struct _objc_protocol_extension {
3673193326Sed  //   uint32_t size;  // sizeof(struct _objc_protocol_extension)
3674193326Sed  //   struct _objc_method_description_list *optional_instance_methods;
3675193326Sed  //   struct _objc_method_description_list *optional_class_methods;
3676193326Sed  //   struct _objc_property_list *instance_properties;
3677193326Sed  // }
3678198092Srdivacky  ProtocolExtensionTy =
3679198092Srdivacky    llvm::StructType::get(VMContext, IntTy,
3680193326Sed                          MethodDescriptionListPtrTy,
3681193326Sed                          MethodDescriptionListPtrTy,
3682193326Sed                          PropertyListPtrTy,
3683193326Sed                          NULL);
3684198092Srdivacky  CGM.getModule().addTypeName("struct._objc_protocol_extension",
3685193326Sed                              ProtocolExtensionTy);
3686198092Srdivacky
3687193326Sed  // struct _objc_protocol_extension *
3688193326Sed  ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
3689193326Sed
3690193326Sed  // Handle recursive construction of Protocol and ProtocolList types
3691193326Sed
3692198092Srdivacky  llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
3693198092Srdivacky  llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
3694193326Sed
3695198092Srdivacky  const llvm::Type *T =
3696198092Srdivacky    llvm::StructType::get(VMContext,
3697198092Srdivacky                          llvm::PointerType::getUnqual(ProtocolListTyHolder),
3698193326Sed                          LongTy,
3699193326Sed                          llvm::ArrayType::get(ProtocolTyHolder, 0),
3700193326Sed                          NULL);
3701193326Sed  cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
3702193326Sed
3703193326Sed  // struct _objc_protocol {
3704193326Sed  //   struct _objc_protocol_extension *isa;
3705193326Sed  //   char *protocol_name;
3706193326Sed  //   struct _objc_protocol **_objc_protocol_list;
3707193326Sed  //   struct _objc_method_description_list *instance_methods;
3708193326Sed  //   struct _objc_method_description_list *class_methods;
3709193326Sed  // }
3710198092Srdivacky  T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
3711193326Sed                            Int8PtrTy,
3712193326Sed                            llvm::PointerType::getUnqual(ProtocolListTyHolder),
3713193326Sed                            MethodDescriptionListPtrTy,
3714193326Sed                            MethodDescriptionListPtrTy,
3715193326Sed                            NULL);
3716193326Sed  cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
3717193326Sed
3718193326Sed  ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
3719198092Srdivacky  CGM.getModule().addTypeName("struct._objc_protocol_list",
3720193326Sed                              ProtocolListTy);
3721193326Sed  // struct _objc_protocol_list *
3722193326Sed  ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
3723193326Sed
3724193326Sed  ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
3725193326Sed  CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
3726193326Sed  ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
3727193326Sed
3728193326Sed  // Class description structures
3729193326Sed
3730193326Sed  // struct _objc_ivar {
3731193326Sed  //   char *ivar_name;
3732193326Sed  //   char *ivar_type;
3733193326Sed  //   int  ivar_offset;
3734193326Sed  // }
3735198092Srdivacky  IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
3736198092Srdivacky                                 Int8PtrTy,
3737198092Srdivacky                                 IntTy,
3738193326Sed                                 NULL);
3739193326Sed  CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
3740193326Sed
3741193326Sed  // struct _objc_ivar_list *
3742198092Srdivacky  IvarListTy = llvm::OpaqueType::get(VMContext);
3743193326Sed  CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
3744193326Sed  IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
3745193326Sed
3746193326Sed  // struct _objc_method_list *
3747198092Srdivacky  MethodListTy = llvm::OpaqueType::get(VMContext);
3748193326Sed  CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
3749193326Sed  MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
3750193326Sed
3751193326Sed  // struct _objc_class_extension *
3752198092Srdivacky  ClassExtensionTy =
3753198092Srdivacky    llvm::StructType::get(VMContext, IntTy,
3754193326Sed                          Int8PtrTy,
3755193326Sed                          PropertyListPtrTy,
3756193326Sed                          NULL);
3757193326Sed  CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
3758193326Sed  ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
3759193326Sed
3760198092Srdivacky  llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
3761193326Sed
3762193326Sed  // struct _objc_class {
3763193326Sed  //   Class isa;
3764193326Sed  //   Class super_class;
3765193326Sed  //   char *name;
3766193326Sed  //   long version;
3767193326Sed  //   long info;
3768193326Sed  //   long instance_size;
3769193326Sed  //   struct _objc_ivar_list *ivars;
3770193326Sed  //   struct _objc_method_list *methods;
3771193326Sed  //   struct _objc_cache *cache;
3772193326Sed  //   struct _objc_protocol_list *protocols;
3773193326Sed  //   char *ivar_layout;
3774193326Sed  //   struct _objc_class_ext *ext;
3775193326Sed  // };
3776198092Srdivacky  T = llvm::StructType::get(VMContext,
3777193326Sed                            llvm::PointerType::getUnqual(ClassTyHolder),
3778198092Srdivacky                            llvm::PointerType::getUnqual(ClassTyHolder),
3779193326Sed                            Int8PtrTy,
3780193326Sed                            LongTy,
3781193326Sed                            LongTy,
3782193326Sed                            LongTy,
3783193326Sed                            IvarListPtrTy,
3784193326Sed                            MethodListPtrTy,
3785193326Sed                            CachePtrTy,
3786193326Sed                            ProtocolListPtrTy,
3787193326Sed                            Int8PtrTy,
3788193326Sed                            ClassExtensionPtrTy,
3789193326Sed                            NULL);
3790193326Sed  cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
3791198092Srdivacky
3792193326Sed  ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
3793193326Sed  CGM.getModule().addTypeName("struct._objc_class", ClassTy);
3794193326Sed  ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
3795193326Sed
3796193326Sed  // struct _objc_category {
3797193326Sed  //   char *category_name;
3798193326Sed  //   char *class_name;
3799193326Sed  //   struct _objc_method_list *instance_method;
3800193326Sed  //   struct _objc_method_list *class_method;
3801193326Sed  //   uint32_t size;  // sizeof(struct _objc_category)
3802193326Sed  //   struct _objc_property_list *instance_properties;// category's @property
3803193326Sed  // }
3804198092Srdivacky  CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
3805193326Sed                                     Int8PtrTy,
3806193326Sed                                     MethodListPtrTy,
3807193326Sed                                     MethodListPtrTy,
3808193326Sed                                     ProtocolListPtrTy,
3809193326Sed                                     IntTy,
3810193326Sed                                     PropertyListPtrTy,
3811193326Sed                                     NULL);
3812193326Sed  CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
3813193326Sed
3814193326Sed  // Global metadata structures
3815193326Sed
3816193326Sed  // struct _objc_symtab {
3817193326Sed  //   long sel_ref_cnt;
3818193326Sed  //   SEL *refs;
3819193326Sed  //   short cls_def_cnt;
3820193326Sed  //   short cat_def_cnt;
3821193326Sed  //   char *defs[cls_def_cnt + cat_def_cnt];
3822193326Sed  // }
3823198092Srdivacky  SymtabTy = llvm::StructType::get(VMContext, LongTy,
3824193326Sed                                   SelectorPtrTy,
3825193326Sed                                   ShortTy,
3826193326Sed                                   ShortTy,
3827193326Sed                                   llvm::ArrayType::get(Int8PtrTy, 0),
3828193326Sed                                   NULL);
3829193326Sed  CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
3830193326Sed  SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
3831193326Sed
3832193326Sed  // struct _objc_module {
3833193326Sed  //   long version;
3834193326Sed  //   long size;   // sizeof(struct _objc_module)
3835193326Sed  //   char *name;
3836193326Sed  //   struct _objc_symtab* symtab;
3837193326Sed  //  }
3838198092Srdivacky  ModuleTy =
3839198092Srdivacky    llvm::StructType::get(VMContext, LongTy,
3840193326Sed                          LongTy,
3841193326Sed                          Int8PtrTy,
3842193326Sed                          SymtabPtrTy,
3843193326Sed                          NULL);
3844193326Sed  CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
3845193326Sed
3846198092Srdivacky
3847193326Sed  // FIXME: This is the size of the setjmp buffer and should be target
3848193326Sed  // specific. 18 is what's used on 32-bit X86.
3849193326Sed  uint64_t SetJmpBufferSize = 18;
3850198092Srdivacky
3851193326Sed  // Exceptions
3852198092Srdivacky  const llvm::Type *StackPtrTy = llvm::ArrayType::get(
3853198092Srdivacky    llvm::Type::getInt8PtrTy(VMContext), 4);
3854198092Srdivacky
3855198092Srdivacky  ExceptionDataTy =
3856198092Srdivacky    llvm::StructType::get(VMContext, llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
3857198092Srdivacky                                                          SetJmpBufferSize),
3858193326Sed                          StackPtrTy, NULL);
3859198092Srdivacky  CGM.getModule().addTypeName("struct._objc_exception_data",
3860193326Sed                              ExceptionDataTy);
3861193326Sed
3862193326Sed}
3863193326Sed
3864198092SrdivackyObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
3865198092Srdivacky  : ObjCCommonTypesHelper(cgm) {
3866193326Sed  // struct _method_list_t {
3867193326Sed  //   uint32_t entsize;  // sizeof(struct _objc_method)
3868193326Sed  //   uint32_t method_count;
3869193326Sed  //   struct _objc_method method_list[method_count];
3870193326Sed  // }
3871198092Srdivacky  MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
3872193326Sed                                            IntTy,
3873193326Sed                                            llvm::ArrayType::get(MethodTy, 0),
3874193326Sed                                            NULL);
3875193326Sed  CGM.getModule().addTypeName("struct.__method_list_t",
3876193326Sed                              MethodListnfABITy);
3877193326Sed  // struct method_list_t *
3878193326Sed  MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
3879198092Srdivacky
3880193326Sed  // struct _protocol_t {
3881193326Sed  //   id isa;  // NULL
3882193326Sed  //   const char * const protocol_name;
3883193326Sed  //   const struct _protocol_list_t * protocol_list; // super protocols
3884193326Sed  //   const struct method_list_t * const instance_methods;
3885193326Sed  //   const struct method_list_t * const class_methods;
3886193326Sed  //   const struct method_list_t *optionalInstanceMethods;
3887193326Sed  //   const struct method_list_t *optionalClassMethods;
3888193326Sed  //   const struct _prop_list_t * properties;
3889193326Sed  //   const uint32_t size;  // sizeof(struct _protocol_t)
3890193326Sed  //   const uint32_t flags;  // = 0
3891193326Sed  // }
3892198092Srdivacky
3893193326Sed  // Holder for struct _protocol_list_t *
3894198092Srdivacky  llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
3895198092Srdivacky
3896198092Srdivacky  ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
3897193326Sed                                          Int8PtrTy,
3898193326Sed                                          llvm::PointerType::getUnqual(
3899193326Sed                                            ProtocolListTyHolder),
3900193326Sed                                          MethodListnfABIPtrTy,
3901193326Sed                                          MethodListnfABIPtrTy,
3902193326Sed                                          MethodListnfABIPtrTy,
3903193326Sed                                          MethodListnfABIPtrTy,
3904193326Sed                                          PropertyListPtrTy,
3905193326Sed                                          IntTy,
3906193326Sed                                          IntTy,
3907193326Sed                                          NULL);
3908193326Sed  CGM.getModule().addTypeName("struct._protocol_t",
3909193326Sed                              ProtocolnfABITy);
3910193326Sed
3911193326Sed  // struct _protocol_t*
3912193326Sed  ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
3913198092Srdivacky
3914193326Sed  // struct _protocol_list_t {
3915193326Sed  //   long protocol_count;   // Note, this is 32/64 bit
3916193326Sed  //   struct _protocol_t *[protocol_count];
3917193326Sed  // }
3918198092Srdivacky  ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
3919193326Sed                                              llvm::ArrayType::get(
3920193326Sed                                                ProtocolnfABIPtrTy, 0),
3921193326Sed                                              NULL);
3922193326Sed  CGM.getModule().addTypeName("struct._objc_protocol_list",
3923193326Sed                              ProtocolListnfABITy);
3924193326Sed  cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
3925198092Srdivacky    ProtocolListnfABITy);
3926198092Srdivacky
3927193326Sed  // struct _objc_protocol_list*
3928193326Sed  ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
3929198092Srdivacky
3930193326Sed  // struct _ivar_t {
3931193326Sed  //   unsigned long int *offset;  // pointer to ivar offset location
3932193326Sed  //   char *name;
3933193326Sed  //   char *type;
3934193326Sed  //   uint32_t alignment;
3935193326Sed  //   uint32_t size;
3936193326Sed  // }
3937198092Srdivacky  IvarnfABITy = llvm::StructType::get(VMContext,
3938198092Srdivacky                                      llvm::PointerType::getUnqual(LongTy),
3939193326Sed                                      Int8PtrTy,
3940193326Sed                                      Int8PtrTy,
3941193326Sed                                      IntTy,
3942193326Sed                                      IntTy,
3943193326Sed                                      NULL);
3944193326Sed  CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
3945198092Srdivacky
3946193326Sed  // struct _ivar_list_t {
3947193326Sed  //   uint32 entsize;  // sizeof(struct _ivar_t)
3948193326Sed  //   uint32 count;
3949193326Sed  //   struct _iver_t list[count];
3950193326Sed  // }
3951198092Srdivacky  IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
3952193326Sed                                          IntTy,
3953193326Sed                                          llvm::ArrayType::get(
3954198092Srdivacky                                            IvarnfABITy, 0),
3955193326Sed                                          NULL);
3956193326Sed  CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
3957198092Srdivacky
3958193326Sed  IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
3959198092Srdivacky
3960193326Sed  // struct _class_ro_t {
3961193326Sed  //   uint32_t const flags;
3962193326Sed  //   uint32_t const instanceStart;
3963193326Sed  //   uint32_t const instanceSize;
3964193326Sed  //   uint32_t const reserved;  // only when building for 64bit targets
3965193326Sed  //   const uint8_t * const ivarLayout;
3966193326Sed  //   const char *const name;
3967193326Sed  //   const struct _method_list_t * const baseMethods;
3968193326Sed  //   const struct _objc_protocol_list *const baseProtocols;
3969193326Sed  //   const struct _ivar_list_t *const ivars;
3970193326Sed  //   const uint8_t * const weakIvarLayout;
3971193326Sed  //   const struct _prop_list_t * const properties;
3972193326Sed  // }
3973198092Srdivacky
3974193326Sed  // FIXME. Add 'reserved' field in 64bit abi mode!
3975198092Srdivacky  ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
3976193326Sed                                         IntTy,
3977193326Sed                                         IntTy,
3978193326Sed                                         Int8PtrTy,
3979193326Sed                                         Int8PtrTy,
3980193326Sed                                         MethodListnfABIPtrTy,
3981193326Sed                                         ProtocolListnfABIPtrTy,
3982193326Sed                                         IvarListnfABIPtrTy,
3983193326Sed                                         Int8PtrTy,
3984193326Sed                                         PropertyListPtrTy,
3985193326Sed                                         NULL);
3986193326Sed  CGM.getModule().addTypeName("struct._class_ro_t",
3987193326Sed                              ClassRonfABITy);
3988198092Srdivacky
3989193326Sed  // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
3990193326Sed  std::vector<const llvm::Type*> Params;
3991193326Sed  Params.push_back(ObjectPtrTy);
3992193326Sed  Params.push_back(SelectorPtrTy);
3993193326Sed  ImpnfABITy = llvm::PointerType::getUnqual(
3994198092Srdivacky    llvm::FunctionType::get(ObjectPtrTy, Params, false));
3995198092Srdivacky
3996193326Sed  // struct _class_t {
3997193326Sed  //   struct _class_t *isa;
3998193326Sed  //   struct _class_t * const superclass;
3999193326Sed  //   void *cache;
4000193326Sed  //   IMP *vtable;
4001193326Sed  //   struct class_ro_t *ro;
4002193326Sed  // }
4003198092Srdivacky
4004198092Srdivacky  llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
4005198092Srdivacky  ClassnfABITy =
4006198092Srdivacky    llvm::StructType::get(VMContext,
4007198092Srdivacky                          llvm::PointerType::getUnqual(ClassTyHolder),
4008198092Srdivacky                          llvm::PointerType::getUnqual(ClassTyHolder),
4009198092Srdivacky                          CachePtrTy,
4010198092Srdivacky                          llvm::PointerType::getUnqual(ImpnfABITy),
4011198092Srdivacky                          llvm::PointerType::getUnqual(ClassRonfABITy),
4012198092Srdivacky                          NULL);
4013193326Sed  CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
4014193326Sed
4015193326Sed  cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
4016198092Srdivacky    ClassnfABITy);
4017198092Srdivacky
4018193326Sed  // LLVM for struct _class_t *
4019193326Sed  ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
4020198092Srdivacky
4021193326Sed  // struct _category_t {
4022193326Sed  //   const char * const name;
4023193326Sed  //   struct _class_t *const cls;
4024193326Sed  //   const struct _method_list_t * const instance_methods;
4025193326Sed  //   const struct _method_list_t * const class_methods;
4026193326Sed  //   const struct _protocol_list_t * const protocols;
4027193326Sed  //   const struct _prop_list_t * const properties;
4028193326Sed  // }
4029198092Srdivacky  CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
4030193326Sed                                          ClassnfABIPtrTy,
4031193326Sed                                          MethodListnfABIPtrTy,
4032193326Sed                                          MethodListnfABIPtrTy,
4033193326Sed                                          ProtocolListnfABIPtrTy,
4034193326Sed                                          PropertyListPtrTy,
4035193326Sed                                          NULL);
4036193326Sed  CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
4037198092Srdivacky
4038193326Sed  // New types for nonfragile abi messaging.
4039193326Sed  CodeGen::CodeGenTypes &Types = CGM.getTypes();
4040193326Sed  ASTContext &Ctx = CGM.getContext();
4041198092Srdivacky
4042193326Sed  // MessageRefTy - LLVM for:
4043193326Sed  // struct _message_ref_t {
4044193326Sed  //   IMP messenger;
4045193326Sed  //   SEL name;
4046193326Sed  // };
4047198092Srdivacky
4048193326Sed  // First the clang type for struct _message_ref_t
4049193326Sed  RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
4050193326Sed                                      SourceLocation(),
4051193326Sed                                      &Ctx.Idents.get("_message_ref_t"));
4052195341Sed  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
4053198092Srdivacky                                Ctx.VoidPtrTy, 0, 0, false));
4054195341Sed  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
4055198092Srdivacky                                Ctx.getObjCSelType(), 0, 0, false));
4056193326Sed  RD->completeDefinition(Ctx);
4057198092Srdivacky
4058193326Sed  MessageRefCTy = Ctx.getTagDeclType(RD);
4059193326Sed  MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4060193326Sed  MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
4061198092Srdivacky
4062193326Sed  // MessageRefPtrTy - LLVM for struct _message_ref_t*
4063193326Sed  MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
4064198092Srdivacky
4065193326Sed  // SuperMessageRefTy - LLVM for:
4066193326Sed  // struct _super_message_ref_t {
4067193326Sed  //   SUPER_IMP messenger;
4068193326Sed  //   SEL name;
4069193326Sed  // };
4070198092Srdivacky  SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
4071193326Sed                                            SelectorPtrTy,
4072193326Sed                                            NULL);
4073193326Sed  CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
4074198092Srdivacky
4075193326Sed  // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
4076198092Srdivacky  SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
4077193326Sed
4078198092Srdivacky
4079193326Sed  // struct objc_typeinfo {
4080193326Sed  //   const void** vtable; // objc_ehtype_vtable + 2
4081193326Sed  //   const char*  name;    // c++ typeinfo string
4082193326Sed  //   Class        cls;
4083193326Sed  // };
4084198092Srdivacky  EHTypeTy = llvm::StructType::get(VMContext,
4085198092Srdivacky                                   llvm::PointerType::getUnqual(Int8PtrTy),
4086193326Sed                                   Int8PtrTy,
4087193326Sed                                   ClassnfABIPtrTy,
4088193326Sed                                   NULL);
4089193326Sed  CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
4090193326Sed  EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
4091193326Sed}
4092193326Sed
4093198092Srdivackyllvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
4094193326Sed  FinishNonFragileABIModule();
4095198092Srdivacky
4096193326Sed  return NULL;
4097193326Sed}
4098193326Sed
4099198092Srdivackyvoid CGObjCNonFragileABIMac::AddModuleClassList(const
4100198092Srdivacky                                                std::vector<llvm::GlobalValue*>
4101198092Srdivacky                                                &Container,
4102193326Sed                                                const char *SymbolName,
4103193326Sed                                                const char *SectionName) {
4104193326Sed  unsigned NumClasses = Container.size();
4105198092Srdivacky
4106193326Sed  if (!NumClasses)
4107193326Sed    return;
4108198092Srdivacky
4109193326Sed  std::vector<llvm::Constant*> Symbols(NumClasses);
4110193326Sed  for (unsigned i=0; i<NumClasses; i++)
4111193326Sed    Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
4112193326Sed                                                ObjCTypes.Int8PtrTy);
4113198092Srdivacky  llvm::Constant* Init =
4114193326Sed    llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
4115193326Sed                                                  NumClasses),
4116193326Sed                             Symbols);
4117198092Srdivacky
4118193326Sed  llvm::GlobalVariable *GV =
4119198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
4120193326Sed                             llvm::GlobalValue::InternalLinkage,
4121193326Sed                             Init,
4122198092Srdivacky                             SymbolName);
4123193326Sed  GV->setAlignment(8);
4124193326Sed  GV->setSection(SectionName);
4125198092Srdivacky  CGM.AddUsedGlobal(GV);
4126193326Sed}
4127198092Srdivacky
4128193326Sedvoid CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4129193326Sed  // nonfragile abi has no module definition.
4130198092Srdivacky
4131193326Sed  // Build list of all implemented class addresses in array
4132193326Sed  // L_OBJC_LABEL_CLASS_$.
4133198092Srdivacky  AddModuleClassList(DefinedClasses,
4134193326Sed                     "\01L_OBJC_LABEL_CLASS_$",
4135193326Sed                     "__DATA, __objc_classlist, regular, no_dead_strip");
4136199482Srdivacky
4137199482Srdivacky  bool hasWeakImport = false;
4138199482Srdivacky  for (unsigned i = 0; i < DefinedClasses.size(); i++) {
4139199482Srdivacky    llvm::GlobalValue *IMPLGV = DefinedClasses[i];
4140199482Srdivacky    if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4141199482Srdivacky      continue;
4142199482Srdivacky    IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4143199482Srdivacky    hasWeakImport = true;
4144199482Srdivacky  }
4145199482Srdivacky
4146199482Srdivacky  if (hasWeakImport) {
4147199482Srdivacky    for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
4148199482Srdivacky      llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
4149199482Srdivacky      if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4150199482Srdivacky        continue;
4151199482Srdivacky      IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4152199482Srdivacky    }
4153199482Srdivacky  }
4154199482Srdivacky
4155198092Srdivacky  AddModuleClassList(DefinedNonLazyClasses,
4156193326Sed                     "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4157193326Sed                     "__DATA, __objc_nlclslist, regular, no_dead_strip");
4158198092Srdivacky
4159193326Sed  // Build list of all implemented category addresses in array
4160193326Sed  // L_OBJC_LABEL_CATEGORY_$.
4161198092Srdivacky  AddModuleClassList(DefinedCategories,
4162193326Sed                     "\01L_OBJC_LABEL_CATEGORY_$",
4163193326Sed                     "__DATA, __objc_catlist, regular, no_dead_strip");
4164198092Srdivacky  AddModuleClassList(DefinedNonLazyCategories,
4165193326Sed                     "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4166193326Sed                     "__DATA, __objc_nlcatlist, regular, no_dead_strip");
4167198092Srdivacky
4168193326Sed  //  static int L_OBJC_IMAGE_INFO[2] = { 0, flags };
4169193326Sed  // FIXME. flags can be 0 | 1 | 2 | 6. For now just use 0
4170193326Sed  std::vector<llvm::Constant*> Values(2);
4171193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, 0);
4172193326Sed  unsigned int flags = 0;
4173193326Sed  // FIXME: Fix and continue?
4174193326Sed  if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
4175193326Sed    flags |= eImageInfo_GarbageCollected;
4176193326Sed  if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
4177193326Sed    flags |= eImageInfo_GCOnly;
4178193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4179193326Sed  llvm::Constant* Init = llvm::ConstantArray::get(
4180198092Srdivacky    llvm::ArrayType::get(ObjCTypes.IntTy, 2),
4181198092Srdivacky    Values);
4182193326Sed  llvm::GlobalVariable *IMGV =
4183198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
4184193326Sed                             llvm::GlobalValue::InternalLinkage,
4185193326Sed                             Init,
4186198092Srdivacky                             "\01L_OBJC_IMAGE_INFO");
4187193326Sed  IMGV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip");
4188193326Sed  IMGV->setConstant(true);
4189198092Srdivacky  CGM.AddUsedGlobal(IMGV);
4190193326Sed}
4191193326Sed
4192193326Sed/// LegacyDispatchedSelector - Returns true if SEL is not in the list of
4193193326Sed/// NonLegacyDispatchMethods; false otherwise. What this means is that
4194198092Srdivacky/// except for the 19 selectors in the list, we generate 32bit-style
4195193326Sed/// message dispatch call for all the rest.
4196193326Sed///
4197193326Sedbool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) {
4198193326Sed  if (NonLegacyDispatchMethods.empty()) {
4199193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("alloc"));
4200193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("class"));
4201193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("self"));
4202193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("isFlipped"));
4203193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("length"));
4204193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("count"));
4205193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("retain"));
4206193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("release"));
4207193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("autorelease"));
4208193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("hash"));
4209198092Srdivacky
4210193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("allocWithZone"));
4211193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
4212193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
4213193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("objectForKey"));
4214193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
4215193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("isEqualToString"));
4216193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("isEqual"));
4217193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("addObject"));
4218198092Srdivacky    // "countByEnumeratingWithState:objects:count"
4219193326Sed    IdentifierInfo *KeyIdents[] = {
4220198092Srdivacky      &CGM.getContext().Idents.get("countByEnumeratingWithState"),
4221198092Srdivacky      &CGM.getContext().Idents.get("objects"),
4222198092Srdivacky      &CGM.getContext().Idents.get("count")
4223193326Sed    };
4224193326Sed    NonLegacyDispatchMethods.insert(
4225193326Sed      CGM.getContext().Selectors.getSelector(3, KeyIdents));
4226193326Sed  }
4227193326Sed  return (NonLegacyDispatchMethods.count(Sel) == 0);
4228193326Sed}
4229193326Sed
4230193326Sed// Metadata flags
4231193326Sedenum MetaDataDlags {
4232193326Sed  CLS = 0x0,
4233193326Sed  CLS_META = 0x1,
4234193326Sed  CLS_ROOT = 0x2,
4235193326Sed  OBJC2_CLS_HIDDEN = 0x10,
4236193326Sed  CLS_EXCEPTION = 0x20
4237193326Sed};
4238193326Sed/// BuildClassRoTInitializer - generate meta-data for:
4239193326Sed/// struct _class_ro_t {
4240193326Sed///   uint32_t const flags;
4241193326Sed///   uint32_t const instanceStart;
4242193326Sed///   uint32_t const instanceSize;
4243193326Sed///   uint32_t const reserved;  // only when building for 64bit targets
4244193326Sed///   const uint8_t * const ivarLayout;
4245193326Sed///   const char *const name;
4246193326Sed///   const struct _method_list_t * const baseMethods;
4247193326Sed///   const struct _protocol_list_t *const baseProtocols;
4248193326Sed///   const struct _ivar_list_t *const ivars;
4249193326Sed///   const uint8_t * const weakIvarLayout;
4250193326Sed///   const struct _prop_list_t * const properties;
4251193326Sed/// }
4252193326Sed///
4253193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
4254198092Srdivacky  unsigned flags,
4255198092Srdivacky  unsigned InstanceStart,
4256198092Srdivacky  unsigned InstanceSize,
4257198092Srdivacky  const ObjCImplementationDecl *ID) {
4258193326Sed  std::string ClassName = ID->getNameAsString();
4259193326Sed  std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
4260193326Sed  Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4261193326Sed  Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
4262193326Sed  Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
4263193326Sed  // FIXME. For 64bit targets add 0 here.
4264198092Srdivacky  Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4265198092Srdivacky    : BuildIvarLayout(ID, true);
4266193326Sed  Values[ 4] = GetClassName(ID->getIdentifier());
4267193326Sed  // const struct _method_list_t * const baseMethods;
4268193326Sed  std::vector<llvm::Constant*> Methods;
4269193326Sed  std::string MethodListName("\01l_OBJC_$_");
4270193326Sed  if (flags & CLS_META) {
4271193326Sed    MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
4272198092Srdivacky    for (ObjCImplementationDecl::classmeth_iterator
4273195341Sed           i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
4274193326Sed      // Class methods should always be defined.
4275193326Sed      Methods.push_back(GetMethodConstant(*i));
4276193326Sed    }
4277193326Sed  } else {
4278193326Sed    MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
4279198092Srdivacky    for (ObjCImplementationDecl::instmeth_iterator
4280195341Sed           i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
4281193326Sed      // Instance methods should always be defined.
4282193326Sed      Methods.push_back(GetMethodConstant(*i));
4283193326Sed    }
4284198092Srdivacky    for (ObjCImplementationDecl::propimpl_iterator
4285195341Sed           i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
4286193326Sed      ObjCPropertyImplDecl *PID = *i;
4287198092Srdivacky
4288193326Sed      if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4289193326Sed        ObjCPropertyDecl *PD = PID->getPropertyDecl();
4290198092Srdivacky
4291193326Sed        if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
4292193326Sed          if (llvm::Constant *C = GetMethodConstant(MD))
4293193326Sed            Methods.push_back(C);
4294193326Sed        if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
4295193326Sed          if (llvm::Constant *C = GetMethodConstant(MD))
4296193326Sed            Methods.push_back(C);
4297193326Sed      }
4298193326Sed    }
4299193326Sed  }
4300198092Srdivacky  Values[ 5] = EmitMethodList(MethodListName,
4301198092Srdivacky                              "__DATA, __objc_const", Methods);
4302198092Srdivacky
4303193326Sed  const ObjCInterfaceDecl *OID = ID->getClassInterface();
4304193326Sed  assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
4305198092Srdivacky  Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
4306198398Srdivacky                                + OID->getName(),
4307193326Sed                                OID->protocol_begin(),
4308193326Sed                                OID->protocol_end());
4309198092Srdivacky
4310193326Sed  if (flags & CLS_META)
4311193326Sed    Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
4312193326Sed  else
4313193326Sed    Values[ 7] = EmitIvarList(ID);
4314198092Srdivacky  Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4315198092Srdivacky    : BuildIvarLayout(ID, false);
4316193326Sed  if (flags & CLS_META)
4317193326Sed    Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
4318193326Sed  else
4319198398Srdivacky    Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4320198398Srdivacky                                  ID, ID->getClassInterface(), ObjCTypes);
4321193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
4322193326Sed                                                   Values);
4323193326Sed  llvm::GlobalVariable *CLASS_RO_GV =
4324198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
4325198092Srdivacky                             llvm::GlobalValue::InternalLinkage,
4326198092Srdivacky                             Init,
4327198092Srdivacky                             (flags & CLS_META) ?
4328198092Srdivacky                             std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
4329198092Srdivacky                             std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
4330193326Sed  CLASS_RO_GV->setAlignment(
4331193326Sed    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassRonfABITy));
4332193326Sed  CLASS_RO_GV->setSection("__DATA, __objc_const");
4333193326Sed  return CLASS_RO_GV;
4334193326Sed
4335193326Sed}
4336193326Sed
4337193326Sed/// BuildClassMetaData - This routine defines that to-level meta-data
4338193326Sed/// for the given ClassName for:
4339193326Sed/// struct _class_t {
4340193326Sed///   struct _class_t *isa;
4341193326Sed///   struct _class_t * const superclass;
4342193326Sed///   void *cache;
4343193326Sed///   IMP *vtable;
4344193326Sed///   struct class_ro_t *ro;
4345193326Sed/// }
4346193326Sed///
4347193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
4348198092Srdivacky  std::string &ClassName,
4349198092Srdivacky  llvm::Constant *IsAGV,
4350198092Srdivacky  llvm::Constant *SuperClassGV,
4351198092Srdivacky  llvm::Constant *ClassRoGV,
4352198092Srdivacky  bool HiddenVisibility) {
4353193326Sed  std::vector<llvm::Constant*> Values(5);
4354193326Sed  Values[0] = IsAGV;
4355198092Srdivacky  Values[1] = SuperClassGV;
4356198092Srdivacky  if (!Values[1])
4357198092Srdivacky    Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
4358193326Sed  Values[2] = ObjCEmptyCacheVar;  // &ObjCEmptyCacheVar
4359193326Sed  Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4360193326Sed  Values[4] = ClassRoGV;                 // &CLASS_RO_GV
4361198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
4362193326Sed                                                   Values);
4363193326Sed  llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4364193326Sed  GV->setInitializer(Init);
4365193326Sed  GV->setSection("__DATA, __objc_data");
4366193326Sed  GV->setAlignment(
4367193326Sed    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassnfABITy));
4368193326Sed  if (HiddenVisibility)
4369193326Sed    GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4370193326Sed  return GV;
4371193326Sed}
4372193326Sed
4373198092Srdivackybool
4374193326SedCGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
4375195341Sed  return OD->getClassMethod(GetNullarySelector("load")) != 0;
4376193326Sed}
4377193326Sed
4378193326Sedvoid CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
4379193326Sed                                              uint32_t &InstanceStart,
4380193326Sed                                              uint32_t &InstanceSize) {
4381198092Srdivacky  const ASTRecordLayout &RL =
4382193326Sed    CGM.getContext().getASTObjCImplementationLayout(OID);
4383198092Srdivacky
4384193326Sed  // InstanceSize is really instance end.
4385198092Srdivacky  InstanceSize = llvm::RoundUpToAlignment(RL.getDataSize(), 8) / 8;
4386193326Sed
4387193326Sed  // If there are no fields, the start is the same as the end.
4388193326Sed  if (!RL.getFieldCount())
4389193326Sed    InstanceStart = InstanceSize;
4390193326Sed  else
4391193326Sed    InstanceStart = RL.getFieldOffset(0) / 8;
4392193326Sed}
4393193326Sed
4394193326Sedvoid CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
4395193326Sed  std::string ClassName = ID->getNameAsString();
4396193326Sed  if (!ObjCEmptyCacheVar) {
4397193326Sed    ObjCEmptyCacheVar = new llvm::GlobalVariable(
4398198092Srdivacky      CGM.getModule(),
4399198092Srdivacky      ObjCTypes.CacheTy,
4400198092Srdivacky      false,
4401198092Srdivacky      llvm::GlobalValue::ExternalLinkage,
4402198092Srdivacky      0,
4403198092Srdivacky      "_objc_empty_cache");
4404198092Srdivacky
4405193326Sed    ObjCEmptyVtableVar = new llvm::GlobalVariable(
4406198092Srdivacky      CGM.getModule(),
4407198092Srdivacky      ObjCTypes.ImpnfABITy,
4408198092Srdivacky      false,
4409198092Srdivacky      llvm::GlobalValue::ExternalLinkage,
4410198092Srdivacky      0,
4411198092Srdivacky      "_objc_empty_vtable");
4412193326Sed  }
4413198092Srdivacky  assert(ID->getClassInterface() &&
4414193326Sed         "CGObjCNonFragileABIMac::GenerateClass - class is 0");
4415193326Sed  // FIXME: Is this correct (that meta class size is never computed)?
4416198092Srdivacky  uint32_t InstanceStart =
4417193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
4418193326Sed  uint32_t InstanceSize = InstanceStart;
4419193326Sed  uint32_t flags = CLS_META;
4420193326Sed  std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4421193326Sed  std::string ObjCClassName(getClassSymbolPrefix());
4422198092Srdivacky
4423193326Sed  llvm::GlobalVariable *SuperClassGV, *IsAGV;
4424198092Srdivacky
4425198092Srdivacky  bool classIsHidden =
4426193326Sed    CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden;
4427193326Sed  if (classIsHidden)
4428193326Sed    flags |= OBJC2_CLS_HIDDEN;
4429193326Sed  if (!ID->getClassInterface()->getSuperClass()) {
4430193326Sed    // class is root
4431193326Sed    flags |= CLS_ROOT;
4432193326Sed    SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
4433193326Sed    IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
4434193326Sed  } else {
4435193326Sed    // Has a root. Current class is not a root.
4436193326Sed    const ObjCInterfaceDecl *Root = ID->getClassInterface();
4437193326Sed    while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4438193326Sed      Root = Super;
4439193326Sed    IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
4440193326Sed    // work on super class metadata symbol.
4441198092Srdivacky    std::string SuperClassName =
4442193326Sed      ObjCMetaClassName + ID->getClassInterface()->getSuperClass()->getNameAsString();
4443193326Sed    SuperClassGV = GetClassGlobal(SuperClassName);
4444199482Srdivacky    if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
4445199482Srdivacky      SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
4446193326Sed  }
4447193326Sed  llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4448193326Sed                                                               InstanceStart,
4449193326Sed                                                               InstanceSize,ID);
4450193326Sed  std::string TClassName = ObjCMetaClassName + ClassName;
4451198092Srdivacky  llvm::GlobalVariable *MetaTClass =
4452193326Sed    BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4453193326Sed                       classIsHidden);
4454199482Srdivacky  DefinedMetaClasses.push_back(MetaTClass);
4455193326Sed
4456193326Sed  // Metadata for the class
4457193326Sed  flags = CLS;
4458193326Sed  if (classIsHidden)
4459193326Sed    flags |= OBJC2_CLS_HIDDEN;
4460193326Sed
4461194613Sed  if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
4462193326Sed    flags |= CLS_EXCEPTION;
4463193326Sed
4464193326Sed  if (!ID->getClassInterface()->getSuperClass()) {
4465193326Sed    flags |= CLS_ROOT;
4466193326Sed    SuperClassGV = 0;
4467193326Sed  } else {
4468193326Sed    // Has a root. Current class is not a root.
4469193326Sed    std::string RootClassName =
4470193326Sed      ID->getClassInterface()->getSuperClass()->getNameAsString();
4471193326Sed    SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
4472199482Srdivacky    if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
4473199482Srdivacky      SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
4474193326Sed  }
4475193326Sed  GetClassSizeInfo(ID, InstanceStart, InstanceSize);
4476193326Sed  CLASS_RO_GV = BuildClassRoTInitializer(flags,
4477193326Sed                                         InstanceStart,
4478198092Srdivacky                                         InstanceSize,
4479193326Sed                                         ID);
4480198092Srdivacky
4481193326Sed  TClassName = ObjCClassName + ClassName;
4482198092Srdivacky  llvm::GlobalVariable *ClassMD =
4483193326Sed    BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
4484193326Sed                       classIsHidden);
4485193326Sed  DefinedClasses.push_back(ClassMD);
4486193326Sed
4487193326Sed  // Determine if this class is also "non-lazy".
4488193326Sed  if (ImplementationIsNonLazy(ID))
4489193326Sed    DefinedNonLazyClasses.push_back(ClassMD);
4490193326Sed
4491193326Sed  // Force the definition of the EHType if necessary.
4492193326Sed  if (flags & CLS_EXCEPTION)
4493193326Sed    GetInterfaceEHType(ID->getClassInterface(), true);
4494193326Sed}
4495193326Sed
4496193326Sed/// GenerateProtocolRef - This routine is called to generate code for
4497193326Sed/// a protocol reference expression; as in:
4498193326Sed/// @code
4499193326Sed///   @protocol(Proto1);
4500193326Sed/// @endcode
4501193326Sed/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
4502193326Sed/// which will hold address of the protocol meta-data.
4503193326Sed///
4504193326Sedllvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
4505198092Srdivacky                                                         const ObjCProtocolDecl *PD) {
4506198092Srdivacky
4507193326Sed  // This routine is called for @protocol only. So, we must build definition
4508193326Sed  // of protocol's meta-data (not a reference to it!)
4509193326Sed  //
4510198092Srdivacky  llvm::Constant *Init =
4511198092Srdivacky    llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
4512198092Srdivacky                                   ObjCTypes.ExternalProtocolPtrTy);
4513198092Srdivacky
4514193326Sed  std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
4515193326Sed  ProtocolName += PD->getNameAsCString();
4516198092Srdivacky
4517193326Sed  llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
4518193326Sed  if (PTGV)
4519193326Sed    return Builder.CreateLoad(PTGV, false, "tmp");
4520193326Sed  PTGV = new llvm::GlobalVariable(
4521198092Srdivacky    CGM.getModule(),
4522198092Srdivacky    Init->getType(), false,
4523198092Srdivacky    llvm::GlobalValue::WeakAnyLinkage,
4524198092Srdivacky    Init,
4525198092Srdivacky    ProtocolName);
4526193326Sed  PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
4527193326Sed  PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4528198092Srdivacky  CGM.AddUsedGlobal(PTGV);
4529193326Sed  return Builder.CreateLoad(PTGV, false, "tmp");
4530193326Sed}
4531193326Sed
4532193326Sed/// GenerateCategory - Build metadata for a category implementation.
4533193326Sed/// struct _category_t {
4534193326Sed///   const char * const name;
4535193326Sed///   struct _class_t *const cls;
4536193326Sed///   const struct _method_list_t * const instance_methods;
4537193326Sed///   const struct _method_list_t * const class_methods;
4538193326Sed///   const struct _protocol_list_t * const protocols;
4539193326Sed///   const struct _prop_list_t * const properties;
4540193326Sed/// }
4541193326Sed///
4542193326Sedvoid CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
4543193326Sed  const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
4544193326Sed  const char *Prefix = "\01l_OBJC_$_CATEGORY_";
4545198092Srdivacky  std::string ExtCatName(Prefix + Interface->getNameAsString()+
4546198092Srdivacky                         "_$_" + OCD->getNameAsString());
4547198092Srdivacky  std::string ExtClassName(getClassSymbolPrefix() +
4548193326Sed                           Interface->getNameAsString());
4549198092Srdivacky
4550193326Sed  std::vector<llvm::Constant*> Values(6);
4551193326Sed  Values[0] = GetClassName(OCD->getIdentifier());
4552193326Sed  // meta-class entry symbol
4553193326Sed  llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
4554199482Srdivacky  if (Interface->hasAttr<WeakImportAttr>())
4555199482Srdivacky    ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
4556199482Srdivacky
4557193326Sed  Values[1] = ClassGV;
4558193326Sed  std::vector<llvm::Constant*> Methods;
4559193326Sed  std::string MethodListName(Prefix);
4560198092Srdivacky  MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
4561193326Sed    "_$_" + OCD->getNameAsString();
4562198092Srdivacky
4563198092Srdivacky  for (ObjCCategoryImplDecl::instmeth_iterator
4564195341Sed         i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
4565193326Sed    // Instance methods should always be defined.
4566193326Sed    Methods.push_back(GetMethodConstant(*i));
4567193326Sed  }
4568198092Srdivacky
4569198092Srdivacky  Values[2] = EmitMethodList(MethodListName,
4570198092Srdivacky                             "__DATA, __objc_const",
4571193326Sed                             Methods);
4572193326Sed
4573193326Sed  MethodListName = Prefix;
4574193326Sed  MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
4575193326Sed    OCD->getNameAsString();
4576193326Sed  Methods.clear();
4577198092Srdivacky  for (ObjCCategoryImplDecl::classmeth_iterator
4578195341Sed         i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
4579193326Sed    // Class methods should always be defined.
4580193326Sed    Methods.push_back(GetMethodConstant(*i));
4581193326Sed  }
4582198092Srdivacky
4583198092Srdivacky  Values[3] = EmitMethodList(MethodListName,
4584198092Srdivacky                             "__DATA, __objc_const",
4585193326Sed                             Methods);
4586198092Srdivacky  const ObjCCategoryDecl *Category =
4587193326Sed    Interface->FindCategoryDeclaration(OCD->getIdentifier());
4588193326Sed  if (Category) {
4589198398Srdivacky    llvm::SmallString<256> ExtName;
4590198398Srdivacky    llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
4591198398Srdivacky                                       << OCD->getName();
4592193326Sed    Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
4593198398Srdivacky                                 + Interface->getName() + "_$_"
4594198398Srdivacky                                 + Category->getName(),
4595193326Sed                                 Category->protocol_begin(),
4596193326Sed                                 Category->protocol_end());
4597198398Srdivacky    Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
4598198398Srdivacky                                 OCD, Category, ObjCTypes);
4599198092Srdivacky  } else {
4600193326Sed    Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
4601193326Sed    Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
4602193326Sed  }
4603198092Srdivacky
4604198092Srdivacky  llvm::Constant *Init =
4605198092Srdivacky    llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
4606193326Sed                              Values);
4607193326Sed  llvm::GlobalVariable *GCATV
4608198092Srdivacky    = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
4609193326Sed                               false,
4610193326Sed                               llvm::GlobalValue::InternalLinkage,
4611193326Sed                               Init,
4612198092Srdivacky                               ExtCatName);
4613193326Sed  GCATV->setAlignment(
4614193326Sed    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.CategorynfABITy));
4615193326Sed  GCATV->setSection("__DATA, __objc_const");
4616198092Srdivacky  CGM.AddUsedGlobal(GCATV);
4617193326Sed  DefinedCategories.push_back(GCATV);
4618193326Sed
4619193326Sed  // Determine if this category is also "non-lazy".
4620193326Sed  if (ImplementationIsNonLazy(OCD))
4621193326Sed    DefinedNonLazyCategories.push_back(GCATV);
4622193326Sed}
4623193326Sed
4624193326Sed/// GetMethodConstant - Return a struct objc_method constant for the
4625193326Sed/// given method if it has been defined. The result is null if the
4626193326Sed/// method has not been defined. The return value has type MethodPtrTy.
4627193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
4628198092Srdivacky  const ObjCMethodDecl *MD) {
4629193326Sed  // FIXME: Use DenseMap::lookup
4630193326Sed  llvm::Function *Fn = MethodDefinitions[MD];
4631193326Sed  if (!Fn)
4632193326Sed    return 0;
4633198092Srdivacky
4634193326Sed  std::vector<llvm::Constant*> Method(3);
4635198092Srdivacky  Method[0] =
4636198092Srdivacky    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
4637198092Srdivacky                                   ObjCTypes.SelectorPtrTy);
4638193326Sed  Method[1] = GetMethodVarType(MD);
4639193326Sed  Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
4640193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
4641193326Sed}
4642193326Sed
4643193326Sed/// EmitMethodList - Build meta-data for method declarations
4644193326Sed/// struct _method_list_t {
4645193326Sed///   uint32_t entsize;  // sizeof(struct _objc_method)
4646193326Sed///   uint32_t method_count;
4647193326Sed///   struct _objc_method method_list[method_count];
4648193326Sed/// }
4649193326Sed///
4650198398Srdivackyllvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
4651198398Srdivacky                                                       const char *Section,
4652198398Srdivacky                                                const ConstantVector &Methods) {
4653193326Sed  // Return null for empty list.
4654193326Sed  if (Methods.empty())
4655193326Sed    return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
4656198092Srdivacky
4657193326Sed  std::vector<llvm::Constant*> Values(3);
4658193326Sed  // sizeof(struct _objc_method)
4659193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
4660193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4661193326Sed  // method_count
4662193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
4663193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
4664193326Sed                                             Methods.size());
4665193326Sed  Values[2] = llvm::ConstantArray::get(AT, Methods);
4666198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
4667198092Srdivacky
4668193326Sed  llvm::GlobalVariable *GV =
4669198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
4670193326Sed                             llvm::GlobalValue::InternalLinkage,
4671193326Sed                             Init,
4672198092Srdivacky                             Name);
4673193326Sed  GV->setAlignment(
4674193326Sed    CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
4675193326Sed  GV->setSection(Section);
4676198092Srdivacky  CGM.AddUsedGlobal(GV);
4677193326Sed  return llvm::ConstantExpr::getBitCast(GV,
4678193326Sed                                        ObjCTypes.MethodListnfABIPtrTy);
4679193326Sed}
4680193326Sed
4681193326Sed/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
4682193326Sed/// the given ivar.
4683193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(
4684198092Srdivacky  const ObjCInterfaceDecl *ID,
4685198092Srdivacky  const ObjCIvarDecl *Ivar) {
4686193326Sed  // FIXME: We shouldn't need to do this lookup.
4687193326Sed  unsigned Index;
4688198092Srdivacky  const ObjCInterfaceDecl *Container =
4689193326Sed    FindIvarInterface(CGM.getContext(), ID, Ivar, Index);
4690193326Sed  assert(Container && "Unable to find ivar container!");
4691193326Sed  std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
4692193326Sed    '.' + Ivar->getNameAsString();
4693198092Srdivacky  llvm::GlobalVariable *IvarOffsetGV =
4694193326Sed    CGM.getModule().getGlobalVariable(Name);
4695193326Sed  if (!IvarOffsetGV)
4696198092Srdivacky    IvarOffsetGV =
4697198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
4698193326Sed                               false,
4699193326Sed                               llvm::GlobalValue::ExternalLinkage,
4700193326Sed                               0,
4701198092Srdivacky                               Name);
4702193326Sed  return IvarOffsetGV;
4703193326Sed}
4704193326Sed
4705193326Sedllvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar(
4706198092Srdivacky  const ObjCInterfaceDecl *ID,
4707198092Srdivacky  const ObjCIvarDecl *Ivar,
4708198092Srdivacky  unsigned long int Offset) {
4709193326Sed  llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
4710198092Srdivacky  IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
4711193326Sed                                                      Offset));
4712193326Sed  IvarOffsetGV->setAlignment(
4713193326Sed    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy));
4714193326Sed
4715193326Sed  // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
4716193326Sed  // well (i.e., in ObjCIvarOffsetVariable).
4717193326Sed  if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
4718193326Sed      Ivar->getAccessControl() == ObjCIvarDecl::Package ||
4719193326Sed      CGM.getDeclVisibilityMode(ID) == LangOptions::Hidden)
4720193326Sed    IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4721193326Sed  else
4722193326Sed    IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
4723193326Sed  IvarOffsetGV->setSection("__DATA, __objc_const");
4724193326Sed  return IvarOffsetGV;
4725193326Sed}
4726193326Sed
4727193326Sed/// EmitIvarList - Emit the ivar list for the given
4728193326Sed/// implementation. The return value has type
4729193326Sed/// IvarListnfABIPtrTy.
4730193326Sed///  struct _ivar_t {
4731193326Sed///   unsigned long int *offset;  // pointer to ivar offset location
4732193326Sed///   char *name;
4733193326Sed///   char *type;
4734193326Sed///   uint32_t alignment;
4735193326Sed///   uint32_t size;
4736193326Sed/// }
4737193326Sed/// struct _ivar_list_t {
4738193326Sed///   uint32 entsize;  // sizeof(struct _ivar_t)
4739193326Sed///   uint32 count;
4740193326Sed///   struct _iver_t list[count];
4741193326Sed/// }
4742193326Sed///
4743193326Sed
4744193326Sedllvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
4745198092Srdivacky  const ObjCImplementationDecl *ID) {
4746198092Srdivacky
4747193326Sed  std::vector<llvm::Constant*> Ivars, Ivar(5);
4748198092Srdivacky
4749193326Sed  const ObjCInterfaceDecl *OID = ID->getClassInterface();
4750193326Sed  assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
4751198092Srdivacky
4752193326Sed  // FIXME. Consolidate this with similar code in GenerateClass.
4753198092Srdivacky
4754193326Sed  // Collect declared and synthesized ivars in a small vector.
4755193326Sed  llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
4756193576Sed  CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
4757198092Srdivacky
4758193326Sed  for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
4759193326Sed    ObjCIvarDecl *IVD = OIvars[i];
4760193576Sed    // Ignore unnamed bit-fields.
4761193576Sed    if (!IVD->getDeclName())
4762193576Sed      continue;
4763198092Srdivacky    Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
4764193326Sed                                ComputeIvarBaseOffset(CGM, ID, IVD));
4765193326Sed    Ivar[1] = GetMethodVarName(IVD->getIdentifier());
4766193326Sed    Ivar[2] = GetMethodVarType(IVD);
4767193326Sed    const llvm::Type *FieldTy =
4768193326Sed      CGM.getTypes().ConvertTypeForMem(IVD->getType());
4769193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
4770193326Sed    unsigned Align = CGM.getContext().getPreferredTypeAlign(
4771198092Srdivacky      IVD->getType().getTypePtr()) >> 3;
4772193326Sed    Align = llvm::Log2_32(Align);
4773193326Sed    Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
4774193326Sed    // NOTE. Size of a bitfield does not match gcc's, because of the
4775193326Sed    // way bitfields are treated special in each. But I am told that
4776193326Sed    // 'size' for bitfield ivars is ignored by the runtime so it does
4777193326Sed    // not matter.  If it matters, there is enough info to get the
4778193326Sed    // bitfield right!
4779193326Sed    Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4780193326Sed    Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
4781193326Sed  }
4782193326Sed  // Return null for empty list.
4783193326Sed  if (Ivars.empty())
4784193326Sed    return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
4785193326Sed  std::vector<llvm::Constant*> Values(3);
4786193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
4787193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4788193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
4789193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
4790193326Sed                                             Ivars.size());
4791193326Sed  Values[2] = llvm::ConstantArray::get(AT, Ivars);
4792198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
4793193326Sed  const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
4794193326Sed  llvm::GlobalVariable *GV =
4795198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
4796193326Sed                             llvm::GlobalValue::InternalLinkage,
4797193326Sed                             Init,
4798198398Srdivacky                             Prefix + OID->getName());
4799193326Sed  GV->setAlignment(
4800193326Sed    CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
4801193326Sed  GV->setSection("__DATA, __objc_const");
4802198092Srdivacky
4803198092Srdivacky  CGM.AddUsedGlobal(GV);
4804198092Srdivacky  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
4805193326Sed}
4806193326Sed
4807193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
4808198092Srdivacky  const ObjCProtocolDecl *PD) {
4809193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
4810198092Srdivacky
4811193326Sed  if (!Entry) {
4812193326Sed    // We use the initializer as a marker of whether this is a forward
4813193326Sed    // reference or not. At module finalization we add the empty
4814193326Sed    // contents for protocols which were referenced but never defined.
4815198092Srdivacky    Entry =
4816198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
4817198092Srdivacky                               llvm::GlobalValue::ExternalLinkage,
4818198092Srdivacky                               0,
4819198398Srdivacky                               "\01l_OBJC_PROTOCOL_$_" + PD->getName());
4820193326Sed    Entry->setSection("__DATA,__datacoal_nt,coalesced");
4821193326Sed  }
4822198092Srdivacky
4823193326Sed  return Entry;
4824193326Sed}
4825193326Sed
4826193326Sed/// GetOrEmitProtocol - Generate the protocol meta-data:
4827193326Sed/// @code
4828193326Sed/// struct _protocol_t {
4829193326Sed///   id isa;  // NULL
4830193326Sed///   const char * const protocol_name;
4831193326Sed///   const struct _protocol_list_t * protocol_list; // super protocols
4832193326Sed///   const struct method_list_t * const instance_methods;
4833193326Sed///   const struct method_list_t * const class_methods;
4834193326Sed///   const struct method_list_t *optionalInstanceMethods;
4835193326Sed///   const struct method_list_t *optionalClassMethods;
4836193326Sed///   const struct _prop_list_t * properties;
4837193326Sed///   const uint32_t size;  // sizeof(struct _protocol_t)
4838193326Sed///   const uint32_t flags;  // = 0
4839193326Sed/// }
4840193326Sed/// @endcode
4841193326Sed///
4842193326Sed
4843193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
4844198092Srdivacky  const ObjCProtocolDecl *PD) {
4845193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
4846198092Srdivacky
4847193326Sed  // Early exit if a defining object has already been generated.
4848193326Sed  if (Entry && Entry->hasInitializer())
4849193326Sed    return Entry;
4850193326Sed
4851193326Sed  // Construct method lists.
4852193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
4853193326Sed  std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
4854198092Srdivacky  for (ObjCProtocolDecl::instmeth_iterator
4855195341Sed         i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
4856193326Sed    ObjCMethodDecl *MD = *i;
4857193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
4858193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
4859193326Sed      OptInstanceMethods.push_back(C);
4860193326Sed    } else {
4861193326Sed      InstanceMethods.push_back(C);
4862198092Srdivacky    }
4863193326Sed  }
4864198092Srdivacky
4865198092Srdivacky  for (ObjCProtocolDecl::classmeth_iterator
4866195341Sed         i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
4867193326Sed    ObjCMethodDecl *MD = *i;
4868193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
4869193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
4870193326Sed      OptClassMethods.push_back(C);
4871193326Sed    } else {
4872193326Sed      ClassMethods.push_back(C);
4873198092Srdivacky    }
4874193326Sed  }
4875198092Srdivacky
4876193326Sed  std::vector<llvm::Constant*> Values(10);
4877193326Sed  // isa is NULL
4878193326Sed  Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
4879193326Sed  Values[1] = GetClassName(PD->getIdentifier());
4880198398Srdivacky  Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
4881198398Srdivacky                               PD->protocol_begin(),
4882198398Srdivacky                               PD->protocol_end());
4883198092Srdivacky
4884193326Sed  Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
4885198398Srdivacky                             + PD->getName(),
4886193326Sed                             "__DATA, __objc_const",
4887193326Sed                             InstanceMethods);
4888198092Srdivacky  Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
4889198398Srdivacky                             + PD->getName(),
4890193326Sed                             "__DATA, __objc_const",
4891193326Sed                             ClassMethods);
4892193326Sed  Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
4893198398Srdivacky                             + PD->getName(),
4894193326Sed                             "__DATA, __objc_const",
4895193326Sed                             OptInstanceMethods);
4896198092Srdivacky  Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
4897198398Srdivacky                             + PD->getName(),
4898193326Sed                             "__DATA, __objc_const",
4899193326Sed                             OptClassMethods);
4900198398Srdivacky  Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
4901193326Sed                               0, PD, ObjCTypes);
4902198092Srdivacky  uint32_t Size =
4903193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
4904193326Sed  Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4905193326Sed  Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
4906193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
4907193326Sed                                                   Values);
4908198092Srdivacky
4909193326Sed  if (Entry) {
4910193326Sed    // Already created, fix the linkage and update the initializer.
4911193326Sed    Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
4912193326Sed    Entry->setInitializer(Init);
4913193326Sed  } else {
4914198092Srdivacky    Entry =
4915198398Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
4916198398Srdivacky                               false, llvm::GlobalValue::WeakAnyLinkage, Init,
4917198398Srdivacky                               "\01l_OBJC_PROTOCOL_$_" + PD->getName());
4918193326Sed    Entry->setAlignment(
4919193326Sed      CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABITy));
4920193326Sed    Entry->setSection("__DATA,__datacoal_nt,coalesced");
4921193326Sed  }
4922193326Sed  Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
4923198092Srdivacky  CGM.AddUsedGlobal(Entry);
4924198092Srdivacky
4925193326Sed  // Use this protocol meta-data to build protocol list table in section
4926193326Sed  // __DATA, __objc_protolist
4927198398Srdivacky  llvm::GlobalVariable *PTGV =
4928198398Srdivacky    new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
4929198398Srdivacky                             false, llvm::GlobalValue::WeakAnyLinkage, Entry,
4930198398Srdivacky                             "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
4931193326Sed  PTGV->setAlignment(
4932193326Sed    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
4933193326Sed  PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
4934193326Sed  PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4935198092Srdivacky  CGM.AddUsedGlobal(PTGV);
4936193326Sed  return Entry;
4937193326Sed}
4938193326Sed
4939193326Sed/// EmitProtocolList - Generate protocol list meta-data:
4940193326Sed/// @code
4941193326Sed/// struct _protocol_list_t {
4942193326Sed///   long protocol_count;   // Note, this is 32/64 bit
4943193326Sed///   struct _protocol_t[protocol_count];
4944193326Sed/// }
4945193326Sed/// @endcode
4946193326Sed///
4947193326Sedllvm::Constant *
4948198398SrdivackyCGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
4949198398Srdivacky                                      ObjCProtocolDecl::protocol_iterator begin,
4950198398Srdivacky                                      ObjCProtocolDecl::protocol_iterator end) {
4951193326Sed  std::vector<llvm::Constant*> ProtocolRefs;
4952198092Srdivacky
4953193326Sed  // Just return null for empty protocol lists
4954198092Srdivacky  if (begin == end)
4955193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
4956198092Srdivacky
4957193326Sed  // FIXME: We shouldn't need to do this lookup here, should we?
4958198398Srdivacky  llvm::SmallString<256> TmpName;
4959198398Srdivacky  Name.toVector(TmpName);
4960198398Srdivacky  llvm::GlobalVariable *GV =
4961198398Srdivacky    CGM.getModule().getGlobalVariable(TmpName.str(), true);
4962193326Sed  if (GV)
4963198398Srdivacky    return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
4964198092Srdivacky
4965193326Sed  for (; begin != end; ++begin)
4966193326Sed    ProtocolRefs.push_back(GetProtocolRef(*begin));  // Implemented???
4967193326Sed
4968193326Sed  // This list is null terminated.
4969193326Sed  ProtocolRefs.push_back(llvm::Constant::getNullValue(
4970198092Srdivacky                           ObjCTypes.ProtocolnfABIPtrTy));
4971198092Srdivacky
4972193326Sed  std::vector<llvm::Constant*> Values(2);
4973198092Srdivacky  Values[0] =
4974198092Srdivacky    llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
4975198092Srdivacky  Values[1] =
4976198092Srdivacky    llvm::ConstantArray::get(
4977198092Srdivacky      llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
4978198092Srdivacky                           ProtocolRefs.size()),
4979198092Srdivacky      ProtocolRefs);
4980198092Srdivacky
4981198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
4982198092Srdivacky  GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
4983193326Sed                                llvm::GlobalValue::InternalLinkage,
4984193326Sed                                Init,
4985198092Srdivacky                                Name);
4986193326Sed  GV->setSection("__DATA, __objc_const");
4987193326Sed  GV->setAlignment(
4988193326Sed    CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
4989198092Srdivacky  CGM.AddUsedGlobal(GV);
4990198092Srdivacky  return llvm::ConstantExpr::getBitCast(GV,
4991193326Sed                                        ObjCTypes.ProtocolListnfABIPtrTy);
4992193326Sed}
4993193326Sed
4994193326Sed/// GetMethodDescriptionConstant - This routine build following meta-data:
4995193326Sed/// struct _objc_method {
4996193326Sed///   SEL _cmd;
4997193326Sed///   char *method_type;
4998193326Sed///   char *_imp;
4999193326Sed/// }
5000193326Sed
5001193326Sedllvm::Constant *
5002193326SedCGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
5003193326Sed  std::vector<llvm::Constant*> Desc(3);
5004198092Srdivacky  Desc[0] =
5005198092Srdivacky    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5006198092Srdivacky                                   ObjCTypes.SelectorPtrTy);
5007193326Sed  Desc[1] = GetMethodVarType(MD);
5008193326Sed  // Protocol methods have no implementation. So, this entry is always NULL.
5009193326Sed  Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5010193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
5011193326Sed}
5012193326Sed
5013193326Sed/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
5014193326Sed/// This code gen. amounts to generating code for:
5015193326Sed/// @code
5016193326Sed/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
5017193326Sed/// @encode
5018198092Srdivacky///
5019193326SedLValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
5020198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5021198092Srdivacky  QualType ObjectTy,
5022198092Srdivacky  llvm::Value *BaseValue,
5023198092Srdivacky  const ObjCIvarDecl *Ivar,
5024198092Srdivacky  unsigned CVRQualifiers) {
5025198092Srdivacky  const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl();
5026193326Sed  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5027193326Sed                                  EmitIvarOffset(CGF, ID, Ivar));
5028193326Sed}
5029193326Sed
5030193326Sedllvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
5031198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5032198092Srdivacky  const ObjCInterfaceDecl *Interface,
5033198092Srdivacky  const ObjCIvarDecl *Ivar) {
5034198092Srdivacky  return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),
5035193326Sed                                false, "ivar");
5036193326Sed}
5037193326Sed
5038193326SedCodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
5039198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5040198092Srdivacky  QualType ResultType,
5041198092Srdivacky  Selector Sel,
5042198092Srdivacky  llvm::Value *Receiver,
5043198092Srdivacky  QualType Arg0Ty,
5044198092Srdivacky  bool IsSuper,
5045198092Srdivacky  const CallArgList &CallArgs) {
5046193326Sed  // FIXME. Even though IsSuper is passes. This function doese not handle calls
5047193326Sed  // to 'super' receivers.
5048193326Sed  CodeGenTypes &Types = CGM.getTypes();
5049193326Sed  llvm::Value *Arg0 = Receiver;
5050193326Sed  if (!IsSuper)
5051193326Sed    Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
5052198092Srdivacky
5053193326Sed  // Find the message function name.
5054193326Sed  // FIXME. This is too much work to get the ABI-specific result type needed to
5055193326Sed  // find the message name.
5056198092Srdivacky  const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType,
5057198092Srdivacky                                                       llvm::SmallVector<QualType, 16>());
5058193326Sed  llvm::Constant *Fn = 0;
5059193326Sed  std::string Name("\01l_");
5060193326Sed  if (CGM.ReturnTypeUsesSret(FnInfo)) {
5061193326Sed#if 0
5062193326Sed    // unlike what is documented. gcc never generates this API!!
5063193326Sed    if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
5064193326Sed      Fn = ObjCTypes.getMessageSendIdStretFixupFn();
5065193326Sed      // FIXME. Is there a better way of getting these names.
5066193326Sed      // They are available in RuntimeFunctions vector pair.
5067193326Sed      Name += "objc_msgSendId_stret_fixup";
5068198092Srdivacky    } else
5069193326Sed#endif
5070198092Srdivacky      if (IsSuper) {
5071193326Sed        Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
5072193326Sed        Name += "objc_msgSendSuper2_stret_fixup";
5073198092Srdivacky      } else {
5074198092Srdivacky        Fn = ObjCTypes.getMessageSendStretFixupFn();
5075198092Srdivacky        Name += "objc_msgSend_stret_fixup";
5076198092Srdivacky      }
5077198092Srdivacky  } else if (!IsSuper && ResultType->isFloatingType()) {
5078195099Sed    if (ResultType->isSpecificBuiltinType(BuiltinType::LongDouble)) {
5079195099Sed      Fn = ObjCTypes.getMessageSendFpretFixupFn();
5080195099Sed      Name += "objc_msgSend_fpret_fixup";
5081198092Srdivacky    } else {
5082195099Sed      Fn = ObjCTypes.getMessageSendFixupFn();
5083195099Sed      Name += "objc_msgSend_fixup";
5084193326Sed    }
5085198092Srdivacky  } else {
5086193326Sed#if 0
5087193326Sed// unlike what is documented. gcc never generates this API!!
5088193326Sed    if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
5089193326Sed      Fn = ObjCTypes.getMessageSendIdFixupFn();
5090193326Sed      Name += "objc_msgSendId_fixup";
5091198092Srdivacky    } else
5092193326Sed#endif
5093198092Srdivacky      if (IsSuper) {
5094193326Sed        Fn = ObjCTypes.getMessageSendSuper2FixupFn();
5095193326Sed        Name += "objc_msgSendSuper2_fixup";
5096198092Srdivacky      } else {
5097198092Srdivacky        Fn = ObjCTypes.getMessageSendFixupFn();
5098198092Srdivacky        Name += "objc_msgSend_fixup";
5099198092Srdivacky      }
5100193326Sed  }
5101193326Sed  assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend");
5102193326Sed  Name += '_';
5103193326Sed  std::string SelName(Sel.getAsString());
5104193326Sed  // Replace all ':' in selector name with '_'  ouch!
5105198092Srdivacky  for (unsigned i = 0; i < SelName.size(); i++)
5106193326Sed    if (SelName[i] == ':')
5107193326Sed      SelName[i] = '_';
5108193326Sed  Name += SelName;
5109193326Sed  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5110193326Sed  if (!GV) {
5111193326Sed    // Build message ref table entry.
5112193326Sed    std::vector<llvm::Constant*> Values(2);
5113193326Sed    Values[0] = Fn;
5114193326Sed    Values[1] = GetMethodVarName(Sel);
5115198092Srdivacky    llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
5116198092Srdivacky    GV =  new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
5117193326Sed                                   llvm::GlobalValue::WeakAnyLinkage,
5118193326Sed                                   Init,
5119198092Srdivacky                                   Name);
5120193326Sed    GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
5121193326Sed    GV->setAlignment(16);
5122193326Sed    GV->setSection("__DATA, __objc_msgrefs, coalesced");
5123193326Sed  }
5124193326Sed  llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy);
5125198092Srdivacky
5126193326Sed  CallArgList ActualArgs;
5127193326Sed  ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
5128198092Srdivacky  ActualArgs.push_back(std::make_pair(RValue::get(Arg1),
5129193326Sed                                      ObjCTypes.MessageRefCPtrTy));
5130193326Sed  ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
5131193326Sed  const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs);
5132193326Sed  llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0);
5133193326Sed  Callee = CGF.Builder.CreateLoad(Callee);
5134193326Sed  const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true);
5135193326Sed  Callee = CGF.Builder.CreateBitCast(Callee,
5136193326Sed                                     llvm::PointerType::getUnqual(FTy));
5137193326Sed  return CGF.EmitCall(FnInfo1, Callee, ActualArgs);
5138193326Sed}
5139193326Sed
5140193326Sed/// Generate code for a message send expression in the nonfragile abi.
5141198092SrdivackyCodeGen::RValue
5142198092SrdivackyCGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
5143198092Srdivacky                                            QualType ResultType,
5144198092Srdivacky                                            Selector Sel,
5145198092Srdivacky                                            llvm::Value *Receiver,
5146198092Srdivacky                                            bool IsClassMessage,
5147198092Srdivacky                                            const CallArgList &CallArgs,
5148198092Srdivacky                                            const ObjCMethodDecl *Method) {
5149193326Sed  return LegacyDispatchedSelector(Sel)
5150198092Srdivacky    ? EmitLegacyMessageSend(CGF, ResultType, EmitSelector(CGF.Builder, Sel),
5151198092Srdivacky                            Receiver, CGF.getContext().getObjCIdType(),
5152198092Srdivacky                            false, CallArgs, Method, ObjCTypes)
5153198092Srdivacky    : EmitMessageSend(CGF, ResultType, Sel,
5154198092Srdivacky                      Receiver, CGF.getContext().getObjCIdType(),
5155198092Srdivacky                      false, CallArgs);
5156193326Sed}
5157193326Sed
5158193326Sedllvm::GlobalVariable *
5159193326SedCGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
5160193326Sed  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5161193326Sed
5162193326Sed  if (!GV) {
5163198092Srdivacky    GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
5164198092Srdivacky                                  false, llvm::GlobalValue::ExternalLinkage,
5165198092Srdivacky                                  0, Name);
5166193326Sed  }
5167193326Sed
5168193326Sed  return GV;
5169193326Sed}
5170193326Sed
5171198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5172198092Srdivacky                                                  const ObjCInterfaceDecl *ID) {
5173193326Sed  llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
5174198092Srdivacky
5175193326Sed  if (!Entry) {
5176193326Sed    std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5177193326Sed    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5178198092Srdivacky    Entry =
5179198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
5180198092Srdivacky                               false, llvm::GlobalValue::InternalLinkage,
5181198092Srdivacky                               ClassGV,
5182198092Srdivacky                               "\01L_OBJC_CLASSLIST_REFERENCES_$_");
5183193326Sed    Entry->setAlignment(
5184198092Srdivacky      CGM.getTargetData().getPrefTypeAlignment(
5185198092Srdivacky        ObjCTypes.ClassnfABIPtrTy));
5186193326Sed    Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
5187198092Srdivacky    CGM.AddUsedGlobal(Entry);
5188193326Sed  }
5189198092Srdivacky
5190193326Sed  return Builder.CreateLoad(Entry, false, "tmp");
5191193326Sed}
5192193326Sed
5193193326Sedllvm::Value *
5194198092SrdivackyCGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
5195193326Sed                                          const ObjCInterfaceDecl *ID) {
5196193326Sed  llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
5197198092Srdivacky
5198193326Sed  if (!Entry) {
5199193326Sed    std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5200193326Sed    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5201198092Srdivacky    Entry =
5202198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
5203198092Srdivacky                               false, llvm::GlobalValue::InternalLinkage,
5204198092Srdivacky                               ClassGV,
5205198092Srdivacky                               "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
5206193326Sed    Entry->setAlignment(
5207198092Srdivacky      CGM.getTargetData().getPrefTypeAlignment(
5208198092Srdivacky        ObjCTypes.ClassnfABIPtrTy));
5209193326Sed    Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
5210198092Srdivacky    CGM.AddUsedGlobal(Entry);
5211193326Sed  }
5212198092Srdivacky
5213193326Sed  return Builder.CreateLoad(Entry, false, "tmp");
5214193326Sed}
5215193326Sed
5216193326Sed/// EmitMetaClassRef - Return a Value * of the address of _class_t
5217193326Sed/// meta-data
5218193326Sed///
5219198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5220198092Srdivacky                                                      const ObjCInterfaceDecl *ID) {
5221193326Sed  llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5222193326Sed  if (Entry)
5223193326Sed    return Builder.CreateLoad(Entry, false, "tmp");
5224198092Srdivacky
5225193326Sed  std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
5226193326Sed  llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
5227198092Srdivacky  Entry =
5228198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
5229193326Sed                             llvm::GlobalValue::InternalLinkage,
5230198092Srdivacky                             MetaClassGV,
5231198092Srdivacky                             "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
5232193326Sed  Entry->setAlignment(
5233198092Srdivacky    CGM.getTargetData().getPrefTypeAlignment(
5234198092Srdivacky      ObjCTypes.ClassnfABIPtrTy));
5235198092Srdivacky
5236193326Sed  Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
5237198092Srdivacky  CGM.AddUsedGlobal(Entry);
5238198092Srdivacky
5239193326Sed  return Builder.CreateLoad(Entry, false, "tmp");
5240193326Sed}
5241193326Sed
5242193326Sed/// GetClass - Return a reference to the class for the given interface
5243193326Sed/// decl.
5244193326Sedllvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
5245193326Sed                                              const ObjCInterfaceDecl *ID) {
5246199482Srdivacky  if (ID->hasAttr<WeakImportAttr>()) {
5247199482Srdivacky    std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5248199482Srdivacky    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5249199482Srdivacky    ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5250199482Srdivacky  }
5251199482Srdivacky
5252193326Sed  return EmitClassRef(Builder, ID);
5253193326Sed}
5254193326Sed
5255193326Sed/// Generates a message send where the super is the receiver.  This is
5256193326Sed/// a message send to self with special delivery semantics indicating
5257193326Sed/// which class's method should be called.
5258193326SedCodeGen::RValue
5259193326SedCGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
5260198092Srdivacky                                                 QualType ResultType,
5261198092Srdivacky                                                 Selector Sel,
5262198092Srdivacky                                                 const ObjCInterfaceDecl *Class,
5263198092Srdivacky                                                 bool isCategoryImpl,
5264198092Srdivacky                                                 llvm::Value *Receiver,
5265198092Srdivacky                                                 bool IsClassMessage,
5266198092Srdivacky                                                 const CodeGen::CallArgList &CallArgs,
5267198092Srdivacky                                                 const ObjCMethodDecl *Method) {
5268193326Sed  // ...
5269193326Sed  // Create and init a super structure; this is a (receiver, class)
5270193326Sed  // pair we will pass to objc_msgSendSuper.
5271193326Sed  llvm::Value *ObjCSuper =
5272193326Sed    CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
5273198092Srdivacky
5274193326Sed  llvm::Value *ReceiverAsObject =
5275193326Sed    CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
5276193326Sed  CGF.Builder.CreateStore(ReceiverAsObject,
5277193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 0));
5278198092Srdivacky
5279193326Sed  // If this is a class message the metaclass is passed as the target.
5280193326Sed  llvm::Value *Target;
5281193326Sed  if (IsClassMessage) {
5282193326Sed    if (isCategoryImpl) {
5283193326Sed      // Message sent to "super' in a class method defined in
5284193326Sed      // a category implementation.
5285193326Sed      Target = EmitClassRef(CGF.Builder, Class);
5286193326Sed      Target = CGF.Builder.CreateStructGEP(Target, 0);
5287193326Sed      Target = CGF.Builder.CreateLoad(Target);
5288198092Srdivacky    } else
5289193326Sed      Target = EmitMetaClassRef(CGF.Builder, Class);
5290198092Srdivacky  } else
5291193326Sed    Target = EmitSuperClassRef(CGF.Builder, Class);
5292198092Srdivacky
5293193326Sed  // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5294193326Sed  // ObjCTypes types.
5295193326Sed  const llvm::Type *ClassTy =
5296193326Sed    CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
5297193326Sed  Target = CGF.Builder.CreateBitCast(Target, ClassTy);
5298193326Sed  CGF.Builder.CreateStore(Target,
5299193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 1));
5300198092Srdivacky
5301193326Sed  return (LegacyDispatchedSelector(Sel))
5302198092Srdivacky    ? EmitLegacyMessageSend(CGF, ResultType,EmitSelector(CGF.Builder, Sel),
5303198092Srdivacky                            ObjCSuper, ObjCTypes.SuperPtrCTy,
5304198092Srdivacky                            true, CallArgs, Method, ObjCTypes)
5305198092Srdivacky    : EmitMessageSend(CGF, ResultType, Sel,
5306198092Srdivacky                      ObjCSuper, ObjCTypes.SuperPtrCTy,
5307198092Srdivacky                      true, CallArgs);
5308193326Sed}
5309193326Sed
5310198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
5311193326Sed                                                  Selector Sel) {
5312193326Sed  llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5313198092Srdivacky
5314193326Sed  if (!Entry) {
5315198092Srdivacky    llvm::Constant *Casted =
5316198092Srdivacky      llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
5317198092Srdivacky                                     ObjCTypes.SelectorPtrTy);
5318198092Srdivacky    Entry =
5319198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
5320198092Srdivacky                               llvm::GlobalValue::InternalLinkage,
5321198092Srdivacky                               Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
5322193326Sed    Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
5323198092Srdivacky    CGM.AddUsedGlobal(Entry);
5324193326Sed  }
5325198092Srdivacky
5326193326Sed  return Builder.CreateLoad(Entry, false, "tmp");
5327193326Sed}
5328193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
5329198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
5330193326Sed///
5331193326Sedvoid CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
5332198092Srdivacky                                                llvm::Value *src,
5333198092Srdivacky                                                llvm::Value *dst,
5334198092Srdivacky                                                llvm::Value *ivarOffset) {
5335193326Sed  const llvm::Type * SrcTy = src->getType();
5336193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5337193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5338193326Sed    assert(Size <= 8 && "does not support size > 8");
5339193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5340193326Sed           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5341193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5342193326Sed  }
5343193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5344193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5345198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5346198092Srdivacky                          src, dst, ivarOffset);
5347193326Sed  return;
5348193326Sed}
5349193326Sed
5350193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5351193326Sed/// objc_assign_strongCast (id src, id *dst)
5352193326Sed///
5353193326Sedvoid CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
5354198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5355198092Srdivacky  llvm::Value *src, llvm::Value *dst) {
5356193326Sed  const llvm::Type * SrcTy = src->getType();
5357193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5358193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5359193326Sed    assert(Size <= 8 && "does not support size > 8");
5360193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5361198092Srdivacky           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5362193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5363193326Sed  }
5364193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5365193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5366193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
5367193326Sed                          src, dst, "weakassign");
5368193326Sed  return;
5369193326Sed}
5370193326Sed
5371198092Srdivackyvoid CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
5372198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5373198092Srdivacky  llvm::Value *DestPtr,
5374198092Srdivacky  llvm::Value *SrcPtr,
5375198092Srdivacky  QualType Ty) {
5376198092Srdivacky  // Get size info for this aggregate.
5377198092Srdivacky  std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty);
5378198092Srdivacky  unsigned long size = TypeInfo.first/8;
5379198092Srdivacky  SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5380198092Srdivacky  DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
5381198092Srdivacky  llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size);
5382198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
5383198092Srdivacky                          DestPtr, SrcPtr, N);
5384198092Srdivacky  return;
5385198092Srdivacky}
5386198092Srdivacky
5387193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak
5388193326Sed/// object: objc_read_weak (id *src)
5389193326Sed///
5390193326Sedllvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
5391198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5392198092Srdivacky  llvm::Value *AddrWeakObj) {
5393193326Sed  const llvm::Type* DestTy =
5394198092Srdivacky    cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5395198092Srdivacky  AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
5396193326Sed  llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
5397193326Sed                                                  AddrWeakObj, "weakread");
5398193326Sed  read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
5399193326Sed  return read_weak;
5400193326Sed}
5401193326Sed
5402193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
5403193326Sed/// objc_assign_weak (id src, id *dst)
5404193326Sed///
5405193326Sedvoid CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
5406198092Srdivacky                                                llvm::Value *src, llvm::Value *dst) {
5407193326Sed  const llvm::Type * SrcTy = src->getType();
5408193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5409193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5410193326Sed    assert(Size <= 8 && "does not support size > 8");
5411193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5412193326Sed           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5413193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5414193326Sed  }
5415193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5416193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5417193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
5418193326Sed                          src, dst, "weakassign");
5419193326Sed  return;
5420193326Sed}
5421193326Sed
5422193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
5423193326Sed/// objc_assign_global (id src, id *dst)
5424193326Sed///
5425193326Sedvoid CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
5426198092Srdivacky                                                  llvm::Value *src, llvm::Value *dst) {
5427193326Sed  const llvm::Type * SrcTy = src->getType();
5428193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5429193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5430193326Sed    assert(Size <= 8 && "does not support size > 8");
5431193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5432193326Sed           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5433193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5434193326Sed  }
5435193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5436193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5437193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
5438193326Sed                          src, dst, "globalassign");
5439193326Sed  return;
5440193326Sed}
5441193326Sed
5442198092Srdivackyvoid
5443193326SedCGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
5444193326Sed                                                  const Stmt &S) {
5445193326Sed  bool isTry = isa<ObjCAtTryStmt>(S);
5446193326Sed  llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
5447193326Sed  llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest();
5448193326Sed  llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
5449193326Sed  llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
5450193326Sed  llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
5451193326Sed  llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
5452193326Sed
5453193326Sed  // For @synchronized, call objc_sync_enter(sync.expr). The
5454193326Sed  // evaluation of the expression must occur before we enter the
5455193326Sed  // @synchronized. We can safely avoid a temp here because jumps into
5456193326Sed  // @synchronized are illegal & this will dominate uses.
5457193326Sed  llvm::Value *SyncArg = 0;
5458193326Sed  if (!isTry) {
5459198092Srdivacky    SyncArg =
5460193326Sed      CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
5461193326Sed    SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
5462193326Sed    CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg);
5463193326Sed  }
5464193326Sed
5465193326Sed  // Push an EH context entry, used for handling rethrows and jumps
5466193326Sed  // through finally.
5467193326Sed  CGF.PushCleanupBlock(FinallyBlock);
5468193326Sed
5469193326Sed  CGF.setInvokeDest(TryHandler);
5470193326Sed
5471193326Sed  CGF.EmitBlock(TryBlock);
5472198092Srdivacky  CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
5473198092Srdivacky               : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
5474193326Sed  CGF.EmitBranchThroughCleanup(FinallyEnd);
5475198092Srdivacky
5476193326Sed  // Emit the exception handler.
5477193326Sed
5478193326Sed  CGF.EmitBlock(TryHandler);
5479193326Sed
5480198092Srdivacky  llvm::Value *llvm_eh_exception =
5481193326Sed    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
5482198092Srdivacky  llvm::Value *llvm_eh_selector =
5483198092Srdivacky    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
5484198092Srdivacky  llvm::Value *llvm_eh_typeid_for =
5485198092Srdivacky    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for);
5486193326Sed  llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
5487193326Sed  llvm::Value *RethrowPtr = CGF.CreateTempAlloca(Exc->getType(), "_rethrow");
5488193326Sed
5489193326Sed  llvm::SmallVector<llvm::Value*, 8> SelectorArgs;
5490193326Sed  SelectorArgs.push_back(Exc);
5491193326Sed  SelectorArgs.push_back(ObjCTypes.getEHPersonalityPtr());
5492193326Sed
5493193326Sed  // Construct the lists of (type, catch body) to handle.
5494193326Sed  llvm::SmallVector<std::pair<const ParmVarDecl*, const Stmt*>, 8> Handlers;
5495193326Sed  bool HasCatchAll = false;
5496193326Sed  if (isTry) {
5497193326Sed    if (const ObjCAtCatchStmt* CatchStmt =
5498193326Sed        cast<ObjCAtTryStmt>(S).getCatchStmts())  {
5499193326Sed      for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
5500193326Sed        const ParmVarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
5501193326Sed        Handlers.push_back(std::make_pair(CatchDecl, CatchStmt->getCatchBody()));
5502193326Sed
5503193326Sed        // catch(...) always matches.
5504193326Sed        if (!CatchDecl) {
5505193326Sed          // Use i8* null here to signal this is a catch all, not a cleanup.
5506193326Sed          llvm::Value *Null = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5507193326Sed          SelectorArgs.push_back(Null);
5508193326Sed          HasCatchAll = true;
5509193326Sed          break;
5510193326Sed        }
5511193326Sed
5512198092Srdivacky        if (CatchDecl->getType()->isObjCIdType() ||
5513193326Sed            CatchDecl->getType()->isObjCQualifiedIdType()) {
5514198092Srdivacky          llvm::Value *IDEHType =
5515193326Sed            CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
5516193326Sed          if (!IDEHType)
5517198092Srdivacky            IDEHType =
5518198092Srdivacky              new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
5519198092Srdivacky                                       false,
5520193326Sed                                       llvm::GlobalValue::ExternalLinkage,
5521198092Srdivacky                                       0, "OBJC_EHTYPE_id");
5522193326Sed          SelectorArgs.push_back(IDEHType);
5523198092Srdivacky        } else {
5524198092Srdivacky          // All other types should be Objective-C interface pointer types.
5525198092Srdivacky          const ObjCObjectPointerType *PT =
5526198092Srdivacky            CatchDecl->getType()->getAs<ObjCObjectPointerType>();
5527198092Srdivacky          assert(PT && "Invalid @catch type.");
5528198092Srdivacky          const ObjCInterfaceType *IT = PT->getInterfaceType();
5529198092Srdivacky          assert(IT && "Invalid @catch type.");
5530198092Srdivacky          llvm::Value *EHType = GetInterfaceEHType(IT->getDecl(), false);
5531198092Srdivacky          SelectorArgs.push_back(EHType);
5532198092Srdivacky        }
5533193326Sed      }
5534193326Sed    }
5535193326Sed  }
5536193326Sed
5537193326Sed  // We use a cleanup unless there was already a catch all.
5538193326Sed  if (!HasCatchAll) {
5539198092Srdivacky    // Even though this is a cleanup, treat it as a catch all to avoid the C++
5540198092Srdivacky    // personality behavior of terminating the process if only cleanups are
5541198092Srdivacky    // found in the exception handling stack.
5542198092Srdivacky    SelectorArgs.push_back(llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy));
5543193326Sed    Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0));
5544193326Sed  }
5545198092Srdivacky
5546198092Srdivacky  llvm::Value *Selector =
5547198092Srdivacky    CGF.Builder.CreateCall(llvm_eh_selector,
5548193326Sed                           SelectorArgs.begin(), SelectorArgs.end(),
5549193326Sed                           "selector");
5550193326Sed  for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
5551193326Sed    const ParmVarDecl *CatchParam = Handlers[i].first;
5552193326Sed    const Stmt *CatchBody = Handlers[i].second;
5553193326Sed
5554193326Sed    llvm::BasicBlock *Next = 0;
5555193326Sed
5556193326Sed    // The last handler always matches.
5557193326Sed    if (i + 1 != e) {
5558193326Sed      assert(CatchParam && "Only last handler can be a catch all.");
5559193326Sed
5560193326Sed      llvm::BasicBlock *Match = CGF.createBasicBlock("match");
5561193326Sed      Next = CGF.createBasicBlock("catch.next");
5562198092Srdivacky      llvm::Value *Id =
5563198092Srdivacky        CGF.Builder.CreateCall(llvm_eh_typeid_for,
5564193326Sed                               CGF.Builder.CreateBitCast(SelectorArgs[i+2],
5565193326Sed                                                         ObjCTypes.Int8PtrTy));
5566193326Sed      CGF.Builder.CreateCondBr(CGF.Builder.CreateICmpEQ(Selector, Id),
5567193326Sed                               Match, Next);
5568193326Sed
5569193326Sed      CGF.EmitBlock(Match);
5570193326Sed    }
5571198092Srdivacky
5572193326Sed    if (CatchBody) {
5573193326Sed      llvm::BasicBlock *MatchEnd = CGF.createBasicBlock("match.end");
5574193326Sed      llvm::BasicBlock *MatchHandler = CGF.createBasicBlock("match.handler");
5575193326Sed
5576193326Sed      // Cleanups must call objc_end_catch.
5577198092Srdivacky      //
5578193326Sed      // FIXME: It seems incorrect for objc_begin_catch to be inside this
5579193326Sed      // context, but this matches gcc.
5580193326Sed      CGF.PushCleanupBlock(MatchEnd);
5581193326Sed      CGF.setInvokeDest(MatchHandler);
5582198092Srdivacky
5583198092Srdivacky      llvm::Value *ExcObject =
5584193326Sed        CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), Exc);
5585193326Sed
5586193326Sed      // Bind the catch parameter if it exists.
5587193326Sed      if (CatchParam) {
5588198092Srdivacky        ExcObject =
5589198092Srdivacky          CGF.Builder.CreateBitCast(ExcObject,
5590193326Sed                                    CGF.ConvertType(CatchParam->getType()));
5591193326Sed        // CatchParam is a ParmVarDecl because of the grammar
5592193326Sed        // construction used to handle this, but for codegen purposes
5593193326Sed        // we treat this as a local decl.
5594193326Sed        CGF.EmitLocalBlockVarDecl(*CatchParam);
5595193326Sed        CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(CatchParam));
5596193326Sed      }
5597193326Sed
5598193326Sed      CGF.ObjCEHValueStack.push_back(ExcObject);
5599193326Sed      CGF.EmitStmt(CatchBody);
5600193326Sed      CGF.ObjCEHValueStack.pop_back();
5601193326Sed
5602193326Sed      CGF.EmitBranchThroughCleanup(FinallyEnd);
5603193326Sed
5604193326Sed      CGF.EmitBlock(MatchHandler);
5605193326Sed
5606193326Sed      llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
5607193326Sed      // We are required to emit this call to satisfy LLVM, even
5608193326Sed      // though we don't use the result.
5609193326Sed      llvm::SmallVector<llvm::Value*, 8> Args;
5610193326Sed      Args.push_back(Exc);
5611193326Sed      Args.push_back(ObjCTypes.getEHPersonalityPtr());
5612198092Srdivacky      Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
5613193326Sed                                            0));
5614198092Srdivacky      CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
5615193326Sed      CGF.Builder.CreateStore(Exc, RethrowPtr);
5616193326Sed      CGF.EmitBranchThroughCleanup(FinallyRethrow);
5617193326Sed
5618193326Sed      CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
5619198092Srdivacky
5620193326Sed      CGF.EmitBlock(MatchEnd);
5621193326Sed
5622193326Sed      // Unfortunately, we also have to generate another EH frame here
5623193326Sed      // in case this throws.
5624198092Srdivacky      llvm::BasicBlock *MatchEndHandler =
5625193326Sed        CGF.createBasicBlock("match.end.handler");
5626193326Sed      llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
5627198092Srdivacky      CGF.Builder.CreateInvoke(ObjCTypes.getObjCEndCatchFn(),
5628193326Sed                               Cont, MatchEndHandler,
5629193326Sed                               Args.begin(), Args.begin());
5630193326Sed
5631193326Sed      CGF.EmitBlock(Cont);
5632193326Sed      if (Info.SwitchBlock)
5633193326Sed        CGF.EmitBlock(Info.SwitchBlock);
5634193326Sed      if (Info.EndBlock)
5635193326Sed        CGF.EmitBlock(Info.EndBlock);
5636193326Sed
5637193326Sed      CGF.EmitBlock(MatchEndHandler);
5638193326Sed      Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
5639193326Sed      // We are required to emit this call to satisfy LLVM, even
5640193326Sed      // though we don't use the result.
5641193326Sed      Args.clear();
5642193326Sed      Args.push_back(Exc);
5643193326Sed      Args.push_back(ObjCTypes.getEHPersonalityPtr());
5644198092Srdivacky      Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
5645193326Sed                                            0));
5646198092Srdivacky      CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
5647193326Sed      CGF.Builder.CreateStore(Exc, RethrowPtr);
5648193326Sed      CGF.EmitBranchThroughCleanup(FinallyRethrow);
5649193326Sed
5650193326Sed      if (Next)
5651193326Sed        CGF.EmitBlock(Next);
5652193326Sed    } else {
5653193326Sed      assert(!Next && "catchup should be last handler.");
5654193326Sed
5655193326Sed      CGF.Builder.CreateStore(Exc, RethrowPtr);
5656193326Sed      CGF.EmitBranchThroughCleanup(FinallyRethrow);
5657193326Sed    }
5658193326Sed  }
5659193326Sed
5660193326Sed  // Pop the cleanup entry, the @finally is outside this cleanup
5661193326Sed  // scope.
5662193326Sed  CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
5663193326Sed  CGF.setInvokeDest(PrevLandingPad);
5664193326Sed
5665193326Sed  CGF.EmitBlock(FinallyBlock);
5666193326Sed
5667193326Sed  if (isTry) {
5668198092Srdivacky    if (const ObjCAtFinallyStmt* FinallyStmt =
5669193326Sed        cast<ObjCAtTryStmt>(S).getFinallyStmt())
5670193326Sed      CGF.EmitStmt(FinallyStmt->getFinallyBody());
5671193326Sed  } else {
5672193326Sed    // Emit 'objc_sync_exit(expr)' as finally's sole statement for
5673193326Sed    // @synchronized.
5674193326Sed    CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg);
5675193326Sed  }
5676193326Sed
5677193326Sed  if (Info.SwitchBlock)
5678193326Sed    CGF.EmitBlock(Info.SwitchBlock);
5679193326Sed  if (Info.EndBlock)
5680193326Sed    CGF.EmitBlock(Info.EndBlock);
5681193326Sed
5682193326Sed  // Branch around the rethrow code.
5683193326Sed  CGF.EmitBranch(FinallyEnd);
5684193326Sed
5685193326Sed  CGF.EmitBlock(FinallyRethrow);
5686198092Srdivacky  CGF.Builder.CreateCall(ObjCTypes.getUnwindResumeOrRethrowFn(),
5687193326Sed                         CGF.Builder.CreateLoad(RethrowPtr));
5688193326Sed  CGF.Builder.CreateUnreachable();
5689198092Srdivacky
5690193326Sed  CGF.EmitBlock(FinallyEnd);
5691193326Sed}
5692193326Sed
5693193326Sed/// EmitThrowStmt - Generate code for a throw statement.
5694193326Sedvoid CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
5695193326Sed                                           const ObjCAtThrowStmt &S) {
5696198092Srdivacky  llvm::Value *Exception;
5697193326Sed  if (const Expr *ThrowExpr = S.getThrowExpr()) {
5698193326Sed    Exception = CGF.EmitScalarExpr(ThrowExpr);
5699193326Sed  } else {
5700198092Srdivacky    assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
5701193326Sed           "Unexpected rethrow outside @catch block.");
5702193326Sed    Exception = CGF.ObjCEHValueStack.back();
5703193326Sed  }
5704193326Sed
5705198092Srdivacky  llvm::Value *ExceptionAsObject =
5706193326Sed    CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
5707193326Sed  llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
5708193326Sed  if (InvokeDest) {
5709193326Sed    llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
5710193326Sed    CGF.Builder.CreateInvoke(ObjCTypes.getExceptionThrowFn(),
5711193326Sed                             Cont, InvokeDest,
5712193326Sed                             &ExceptionAsObject, &ExceptionAsObject + 1);
5713193326Sed    CGF.EmitBlock(Cont);
5714193326Sed  } else
5715198092Srdivacky    CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject);
5716193326Sed  CGF.Builder.CreateUnreachable();
5717193326Sed
5718193326Sed  // Clear the insertion point to indicate we are in unreachable code.
5719193326Sed  CGF.Builder.ClearInsertionPoint();
5720193326Sed}
5721193326Sed
5722193326Sedllvm::Value *
5723198092SrdivackyCGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
5724193326Sed                                           bool ForDefinition) {
5725193326Sed  llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
5726193326Sed
5727193326Sed  // If we don't need a definition, return the entry if found or check
5728193326Sed  // if we use an external reference.
5729193326Sed  if (!ForDefinition) {
5730193326Sed    if (Entry)
5731193326Sed      return Entry;
5732193326Sed
5733193326Sed    // If this type (or a super class) has the __objc_exception__
5734193326Sed    // attribute, emit an external reference.
5735194613Sed    if (hasObjCExceptionAttribute(CGM.getContext(), ID))
5736198092Srdivacky      return Entry =
5737198092Srdivacky        new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
5738193326Sed                                 llvm::GlobalValue::ExternalLinkage,
5739198092Srdivacky                                 0,
5740198398Srdivacky                                 ("OBJC_EHTYPE_$_" +
5741198092Srdivacky                                  ID->getIdentifier()->getName()));
5742193326Sed  }
5743198092Srdivacky
5744193326Sed  // Otherwise we need to either make a new entry or fill in the
5745193326Sed  // initializer.
5746193326Sed  assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
5747193326Sed  std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5748193326Sed  std::string VTableName = "objc_ehtype_vtable";
5749198092Srdivacky  llvm::GlobalVariable *VTableGV =
5750193326Sed    CGM.getModule().getGlobalVariable(VTableName);
5751193326Sed  if (!VTableGV)
5752198092Srdivacky    VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
5753198092Srdivacky                                        false,
5754193326Sed                                        llvm::GlobalValue::ExternalLinkage,
5755198092Srdivacky                                        0, VTableName);
5756193326Sed
5757198092Srdivacky  llvm::Value *VTableIdx = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
5758193326Sed
5759193326Sed  std::vector<llvm::Constant*> Values(3);
5760193326Sed  Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
5761193326Sed  Values[1] = GetClassName(ID->getIdentifier());
5762193326Sed  Values[2] = GetClassGlobal(ClassName);
5763198092Srdivacky  llvm::Constant *Init =
5764198092Srdivacky    llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
5765193326Sed
5766193326Sed  if (Entry) {
5767193326Sed    Entry->setInitializer(Init);
5768193326Sed  } else {
5769198092Srdivacky    Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
5770193326Sed                                     llvm::GlobalValue::WeakAnyLinkage,
5771198092Srdivacky                                     Init,
5772198398Srdivacky                                     ("OBJC_EHTYPE_$_" +
5773198092Srdivacky                                      ID->getIdentifier()->getName()));
5774193326Sed  }
5775193326Sed
5776193326Sed  if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden)
5777193326Sed    Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
5778193326Sed  Entry->setAlignment(8);
5779193326Sed
5780193326Sed  if (ForDefinition) {
5781193326Sed    Entry->setSection("__DATA,__objc_const");
5782193326Sed    Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
5783193326Sed  } else {
5784193326Sed    Entry->setSection("__DATA,__datacoal_nt,coalesced");
5785193326Sed  }
5786193326Sed
5787193326Sed  return Entry;
5788193326Sed}
5789198092Srdivacky
5790193326Sed/* *** */
5791193326Sed
5792193326SedCodeGen::CGObjCRuntime *
5793193326SedCodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
5794193326Sed  return new CGObjCMac(CGM);
5795193326Sed}
5796193326Sed
5797193326SedCodeGen::CGObjCRuntime *
5798193326SedCodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) {
5799193326Sed  return new CGObjCNonFragileABIMac(CGM);
5800193326Sed}
5801