CGObjCMac.cpp revision 218893
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
16206084Srdivacky#include "CGRecordLayout.h"
17193326Sed#include "CodeGenModule.h"
18193326Sed#include "CodeGenFunction.h"
19218893Sdim#include "CGBlocks.h"
20218893Sdim#include "CGCleanup.h"
21193326Sed#include "clang/AST/ASTContext.h"
22193326Sed#include "clang/AST/Decl.h"
23193326Sed#include "clang/AST/DeclObjC.h"
24193326Sed#include "clang/AST/RecordLayout.h"
25193326Sed#include "clang/AST/StmtObjC.h"
26193326Sed#include "clang/Basic/LangOptions.h"
27210299Sed#include "clang/Frontend/CodeGenOptions.h"
28193326Sed
29212904Sdim#include "llvm/InlineAsm.h"
30212904Sdim#include "llvm/IntrinsicInst.h"
31198092Srdivacky#include "llvm/LLVMContext.h"
32193326Sed#include "llvm/Module.h"
33193326Sed#include "llvm/ADT/DenseSet.h"
34198092Srdivacky#include "llvm/ADT/SetVector.h"
35198092Srdivacky#include "llvm/ADT/SmallString.h"
36200583Srdivacky#include "llvm/ADT/SmallPtrSet.h"
37210299Sed#include "llvm/Support/CallSite.h"
38198092Srdivacky#include "llvm/Support/raw_ostream.h"
39193326Sed#include "llvm/Target/TargetData.h"
40198092Srdivacky#include <cstdio>
41193326Sed
42193326Sedusing namespace clang;
43193326Sedusing namespace CodeGen;
44193326Sed
45193326Sed// Common CGObjCRuntime functions, these don't belong here, but they
46193326Sed// don't belong in CGObjCRuntime either so we will live with it for
47193326Sed// now.
48193326Sed
49193326Sedstatic uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
50193326Sed                                     const ObjCInterfaceDecl *OID,
51193326Sed                                     const ObjCImplementationDecl *ID,
52193326Sed                                     const ObjCIvarDecl *Ivar) {
53206125Srdivacky  const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
54193326Sed
55206125Srdivacky  // FIXME: We should eliminate the need to have ObjCImplementationDecl passed
56206125Srdivacky  // in here; it should never be necessary because that should be the lexical
57206125Srdivacky  // decl context for the ivar.
58206125Srdivacky
59193326Sed  // If we know have an implementation (and the ivar is in it) then
60193326Sed  // look up in the implementation layout.
61198092Srdivacky  const ASTRecordLayout *RL;
62193326Sed  if (ID && ID->getClassInterface() == Container)
63193326Sed    RL = &CGM.getContext().getASTObjCImplementationLayout(ID);
64193326Sed  else
65193326Sed    RL = &CGM.getContext().getASTObjCInterfaceLayout(Container);
66206125Srdivacky
67206125Srdivacky  // Compute field index.
68206125Srdivacky  //
69206125Srdivacky  // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is
70206125Srdivacky  // implemented. This should be fixed to get the information from the layout
71206125Srdivacky  // directly.
72206125Srdivacky  unsigned Index = 0;
73206125Srdivacky  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
74206125Srdivacky  CGM.getContext().ShallowCollectObjCIvars(Container, Ivars);
75206125Srdivacky  for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
76206125Srdivacky    if (Ivar == Ivars[k])
77206125Srdivacky      break;
78206125Srdivacky    ++Index;
79206125Srdivacky  }
80206125Srdivacky  assert(Index != Ivars.size() && "Ivar is not inside container!");
81218893Sdim  assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!");
82206125Srdivacky
83193326Sed  return RL->getFieldOffset(Index);
84193326Sed}
85193326Sed
86193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
87193326Sed                                              const ObjCInterfaceDecl *OID,
88193326Sed                                              const ObjCIvarDecl *Ivar) {
89193326Sed  return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 8;
90193326Sed}
91193326Sed
92193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
93193326Sed                                              const ObjCImplementationDecl *OID,
94193326Sed                                              const ObjCIvarDecl *Ivar) {
95193326Sed  return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 8;
96193326Sed}
97193326Sed
98193326SedLValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
99193326Sed                                               const ObjCInterfaceDecl *OID,
100193326Sed                                               llvm::Value *BaseValue,
101193326Sed                                               const ObjCIvarDecl *Ivar,
102193326Sed                                               unsigned CVRQualifiers,
103193326Sed                                               llvm::Value *Offset) {
104193326Sed  // Compute (type*) ( (char *) BaseValue + Offset)
105198092Srdivacky  const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
106193326Sed  QualType IvarTy = Ivar->getType();
107193326Sed  const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
108193326Sed  llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr);
109193326Sed  V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
110193326Sed  V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
111198092Srdivacky
112212904Sdim  if (!Ivar->isBitField()) {
113212904Sdim    LValue LV = CGF.MakeAddrLValue(V, IvarTy);
114212904Sdim    LV.getQuals().addCVRQualifiers(CVRQualifiers);
115212904Sdim    return LV;
116212904Sdim  }
117198092Srdivacky
118212904Sdim  // We need to compute an access strategy for this bit-field. We are given the
119212904Sdim  // offset to the first byte in the bit-field, the sub-byte offset is taken
120212904Sdim  // from the original layout. We reuse the normal bit-field access strategy by
121212904Sdim  // treating this as an access to a struct where the bit-field is in byte 0,
122212904Sdim  // and adjust the containing type size as appropriate.
123212904Sdim  //
124212904Sdim  // FIXME: Note that currently we make a very conservative estimate of the
125212904Sdim  // alignment of the bit-field, because (a) it is not clear what guarantees the
126212904Sdim  // runtime makes us, and (b) we don't have a way to specify that the struct is
127212904Sdim  // at an alignment plus offset.
128212904Sdim  //
129212904Sdim  // Note, there is a subtle invariant here: we can only call this routine on
130212904Sdim  // non-synthesized ivars but we may be called for synthesized ivars.  However,
131212904Sdim  // a synthesized ivar can never be a bit-field, so this is safe.
132212904Sdim  const ASTRecordLayout &RL =
133212904Sdim    CGF.CGM.getContext().getASTObjCInterfaceLayout(OID);
134218893Sdim  uint64_t TypeSizeInBits = CGF.CGM.getContext().toBits(RL.getSize());
135212904Sdim  uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar);
136212904Sdim  uint64_t BitOffset = FieldBitOffset % 8;
137212904Sdim  uint64_t ContainingTypeAlign = 8;
138212904Sdim  uint64_t ContainingTypeSize = TypeSizeInBits - (FieldBitOffset - BitOffset);
139206275Srdivacky  uint64_t BitFieldSize =
140206275Srdivacky    Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue();
141193326Sed
142206275Srdivacky  // Allocate a new CGBitFieldInfo object to describe this access.
143206275Srdivacky  //
144206275Srdivacky  // FIXME: This is incredibly wasteful, these should be uniqued or part of some
145206275Srdivacky  // layout object. However, this is blocked on other cleanups to the
146206275Srdivacky  // Objective-C code, so for now we just live with allocating a bunch of these
147206275Srdivacky  // objects.
148212904Sdim  CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo(
149212904Sdim    CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize,
150212904Sdim                             ContainingTypeSize, ContainingTypeAlign));
151207619Srdivacky
152212904Sdim  return LValue::MakeBitfield(V, *Info,
153212904Sdim                              IvarTy.getCVRQualifiers() | CVRQualifiers);
154193326Sed}
155193326Sed
156193326Sed///
157193326Sed
158193326Sednamespace {
159193326Sed
160198092Srdivackytypedef std::vector<llvm::Constant*> ConstantVector;
161193326Sed
162198092Srdivacky// FIXME: We should find a nicer way to make the labels for metadata, string
163198092Srdivacky// concatenation is lame.
164193326Sed
165193326Sedclass ObjCCommonTypesHelper {
166198092Srdivackyprotected:
167198092Srdivacky  llvm::LLVMContext &VMContext;
168198092Srdivacky
169193326Sedprivate:
170193326Sed  llvm::Constant *getMessageSendFn() const {
171193326Sed    // id objc_msgSend (id, SEL, ...)
172193326Sed    std::vector<const llvm::Type*> Params;
173193326Sed    Params.push_back(ObjectPtrTy);
174193326Sed    Params.push_back(SelectorPtrTy);
175193326Sed    return
176198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
177198092Srdivacky                                                        Params, true),
178198092Srdivacky                                "objc_msgSend");
179193326Sed  }
180198092Srdivacky
181193326Sed  llvm::Constant *getMessageSendStretFn() const {
182193326Sed    // id objc_msgSend_stret (id, SEL, ...)
183193326Sed    std::vector<const llvm::Type*> Params;
184193326Sed    Params.push_back(ObjectPtrTy);
185193326Sed    Params.push_back(SelectorPtrTy);
186193326Sed    return
187198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
188198092Srdivacky                                                        Params, true),
189198092Srdivacky                                "objc_msgSend_stret");
190198092Srdivacky
191193326Sed  }
192198092Srdivacky
193193326Sed  llvm::Constant *getMessageSendFpretFn() const {
194193326Sed    // FIXME: This should be long double on x86_64?
195193326Sed    // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
196193326Sed    std::vector<const llvm::Type*> Params;
197193326Sed    Params.push_back(ObjectPtrTy);
198193326Sed    Params.push_back(SelectorPtrTy);
199193326Sed    return
200198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(
201198092Srdivacky                                             llvm::Type::getDoubleTy(VMContext),
202198092Srdivacky                                                        Params,
203198092Srdivacky                                                        true),
204198092Srdivacky                                "objc_msgSend_fpret");
205198092Srdivacky
206193326Sed  }
207198092Srdivacky
208193326Sed  llvm::Constant *getMessageSendSuperFn() const {
209193326Sed    // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
210193326Sed    const char *SuperName = "objc_msgSendSuper";
211193326Sed    std::vector<const llvm::Type*> Params;
212193326Sed    Params.push_back(SuperPtrTy);
213193326Sed    Params.push_back(SelectorPtrTy);
214193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
215193326Sed                                                             Params, true),
216193326Sed                                     SuperName);
217193326Sed  }
218198092Srdivacky
219193326Sed  llvm::Constant *getMessageSendSuperFn2() const {
220193326Sed    // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
221193326Sed    const char *SuperName = "objc_msgSendSuper2";
222193326Sed    std::vector<const llvm::Type*> Params;
223193326Sed    Params.push_back(SuperPtrTy);
224193326Sed    Params.push_back(SelectorPtrTy);
225193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
226193326Sed                                                             Params, true),
227193326Sed                                     SuperName);
228193326Sed  }
229198092Srdivacky
230193326Sed  llvm::Constant *getMessageSendSuperStretFn() const {
231193326Sed    // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
232193326Sed    //                              SEL op, ...)
233193326Sed    std::vector<const llvm::Type*> Params;
234193326Sed    Params.push_back(Int8PtrTy);
235193326Sed    Params.push_back(SuperPtrTy);
236193326Sed    Params.push_back(SelectorPtrTy);
237198092Srdivacky    return CGM.CreateRuntimeFunction(
238198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
239198092Srdivacky                              Params, true),
240198092Srdivacky      "objc_msgSendSuper_stret");
241193326Sed  }
242198092Srdivacky
243193326Sed  llvm::Constant *getMessageSendSuperStretFn2() const {
244193326Sed    // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
245193326Sed    //                               SEL op, ...)
246193326Sed    std::vector<const llvm::Type*> Params;
247193326Sed    Params.push_back(Int8PtrTy);
248193326Sed    Params.push_back(SuperPtrTy);
249193326Sed    Params.push_back(SelectorPtrTy);
250198092Srdivacky    return CGM.CreateRuntimeFunction(
251198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
252198092Srdivacky                              Params, true),
253198092Srdivacky      "objc_msgSendSuper2_stret");
254193326Sed  }
255198092Srdivacky
256193326Sed  llvm::Constant *getMessageSendSuperFpretFn() const {
257193326Sed    // There is no objc_msgSendSuper_fpret? How can that work?
258193326Sed    return getMessageSendSuperFn();
259193326Sed  }
260198092Srdivacky
261193326Sed  llvm::Constant *getMessageSendSuperFpretFn2() const {
262193326Sed    // There is no objc_msgSendSuper_fpret? How can that work?
263193326Sed    return getMessageSendSuperFn2();
264193326Sed  }
265198092Srdivacky
266193326Sedprotected:
267193326Sed  CodeGen::CodeGenModule &CGM;
268198092Srdivacky
269193326Sedpublic:
270193326Sed  const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
271193326Sed  const llvm::Type *Int8PtrTy;
272198092Srdivacky
273193326Sed  /// ObjectPtrTy - LLVM type for object handles (typeof(id))
274193326Sed  const llvm::Type *ObjectPtrTy;
275198092Srdivacky
276193326Sed  /// PtrObjectPtrTy - LLVM type for id *
277193326Sed  const llvm::Type *PtrObjectPtrTy;
278198092Srdivacky
279193326Sed  /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
280193326Sed  const llvm::Type *SelectorPtrTy;
281193326Sed  /// ProtocolPtrTy - LLVM type for external protocol handles
282193326Sed  /// (typeof(Protocol))
283193326Sed  const llvm::Type *ExternalProtocolPtrTy;
284198092Srdivacky
285193326Sed  // SuperCTy - clang type for struct objc_super.
286193326Sed  QualType SuperCTy;
287193326Sed  // SuperPtrCTy - clang type for struct objc_super *.
288193326Sed  QualType SuperPtrCTy;
289198092Srdivacky
290193326Sed  /// SuperTy - LLVM type for struct objc_super.
291193326Sed  const llvm::StructType *SuperTy;
292193326Sed  /// SuperPtrTy - LLVM type for struct objc_super *.
293193326Sed  const llvm::Type *SuperPtrTy;
294198092Srdivacky
295193326Sed  /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
296193326Sed  /// in GCC parlance).
297193326Sed  const llvm::StructType *PropertyTy;
298198092Srdivacky
299193326Sed  /// PropertyListTy - LLVM type for struct objc_property_list
300193326Sed  /// (_prop_list_t in GCC parlance).
301193326Sed  const llvm::StructType *PropertyListTy;
302193326Sed  /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
303193326Sed  const llvm::Type *PropertyListPtrTy;
304198092Srdivacky
305193326Sed  // MethodTy - LLVM type for struct objc_method.
306193326Sed  const llvm::StructType *MethodTy;
307198092Srdivacky
308193326Sed  /// CacheTy - LLVM type for struct objc_cache.
309193326Sed  const llvm::Type *CacheTy;
310193326Sed  /// CachePtrTy - LLVM type for struct objc_cache *.
311193326Sed  const llvm::Type *CachePtrTy;
312198092Srdivacky
313193326Sed  llvm::Constant *getGetPropertyFn() {
314193326Sed    CodeGen::CodeGenTypes &Types = CGM.getTypes();
315193326Sed    ASTContext &Ctx = CGM.getContext();
316193326Sed    // id objc_getProperty (id, SEL, ptrdiff_t, bool)
317204643Srdivacky    llvm::SmallVector<CanQualType,4> Params;
318204643Srdivacky    CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
319204643Srdivacky    CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
320193326Sed    Params.push_back(IdType);
321193326Sed    Params.push_back(SelType);
322193326Sed    Params.push_back(Ctx.LongTy);
323193326Sed    Params.push_back(Ctx.BoolTy);
324193326Sed    const llvm::FunctionType *FTy =
325203955Srdivacky      Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
326206084Srdivacky                                                  FunctionType::ExtInfo()),
327206084Srdivacky                            false);
328193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
329193326Sed  }
330198092Srdivacky
331193326Sed  llvm::Constant *getSetPropertyFn() {
332193326Sed    CodeGen::CodeGenTypes &Types = CGM.getTypes();
333193326Sed    ASTContext &Ctx = CGM.getContext();
334193326Sed    // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
335204643Srdivacky    llvm::SmallVector<CanQualType,6> Params;
336204643Srdivacky    CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
337204643Srdivacky    CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
338193326Sed    Params.push_back(IdType);
339193326Sed    Params.push_back(SelType);
340193326Sed    Params.push_back(Ctx.LongTy);
341193326Sed    Params.push_back(IdType);
342193326Sed    Params.push_back(Ctx.BoolTy);
343193326Sed    Params.push_back(Ctx.BoolTy);
344193326Sed    const llvm::FunctionType *FTy =
345203955Srdivacky      Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
346206084Srdivacky                                                  FunctionType::ExtInfo()),
347206084Srdivacky                            false);
348193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
349193326Sed  }
350198092Srdivacky
351207619Srdivacky
352207619Srdivacky  llvm::Constant *getCopyStructFn() {
353207619Srdivacky    CodeGen::CodeGenTypes &Types = CGM.getTypes();
354207619Srdivacky    ASTContext &Ctx = CGM.getContext();
355207619Srdivacky    // void objc_copyStruct (void *, const void *, size_t, bool, bool)
356207619Srdivacky    llvm::SmallVector<CanQualType,5> Params;
357207619Srdivacky    Params.push_back(Ctx.VoidPtrTy);
358207619Srdivacky    Params.push_back(Ctx.VoidPtrTy);
359207619Srdivacky    Params.push_back(Ctx.LongTy);
360207619Srdivacky    Params.push_back(Ctx.BoolTy);
361207619Srdivacky    Params.push_back(Ctx.BoolTy);
362207619Srdivacky    const llvm::FunctionType *FTy =
363207619Srdivacky      Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
364207619Srdivacky                                                  FunctionType::ExtInfo()),
365207619Srdivacky                            false);
366207619Srdivacky    return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
367207619Srdivacky  }
368207619Srdivacky
369193326Sed  llvm::Constant *getEnumerationMutationFn() {
370198092Srdivacky    CodeGen::CodeGenTypes &Types = CGM.getTypes();
371198092Srdivacky    ASTContext &Ctx = CGM.getContext();
372193326Sed    // void objc_enumerationMutation (id)
373204643Srdivacky    llvm::SmallVector<CanQualType,1> Params;
374204643Srdivacky    Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
375198092Srdivacky    const llvm::FunctionType *FTy =
376203955Srdivacky      Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
377206084Srdivacky                                                  FunctionType::ExtInfo()),
378206084Srdivacky                            false);
379193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
380193326Sed  }
381198092Srdivacky
382193326Sed  /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
383193326Sed  llvm::Constant *getGcReadWeakFn() {
384193326Sed    // id objc_read_weak (id *)
385193326Sed    std::vector<const llvm::Type*> Args;
386193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
387198092Srdivacky    llvm::FunctionType *FTy =
388198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
389193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
390198092Srdivacky  }
391198092Srdivacky
392193326Sed  /// GcAssignWeakFn -- LLVM objc_assign_weak function.
393193326Sed  llvm::Constant *getGcAssignWeakFn() {
394193326Sed    // id objc_assign_weak (id, id *)
395193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
396193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
397193326Sed    llvm::FunctionType *FTy =
398193326Sed      llvm::FunctionType::get(ObjectPtrTy, Args, false);
399193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
400193326Sed  }
401198092Srdivacky
402193326Sed  /// GcAssignGlobalFn -- LLVM objc_assign_global function.
403193326Sed  llvm::Constant *getGcAssignGlobalFn() {
404193326Sed    // id objc_assign_global(id, id *)
405193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
406193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
407198092Srdivacky    llvm::FunctionType *FTy =
408198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
409193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
410193326Sed  }
411198092Srdivacky
412212904Sdim  /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
413212904Sdim  llvm::Constant *getGcAssignThreadLocalFn() {
414212904Sdim    // id objc_assign_threadlocal(id src, id * dest)
415212904Sdim    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
416212904Sdim    Args.push_back(ObjectPtrTy->getPointerTo());
417212904Sdim    llvm::FunctionType *FTy =
418212904Sdim    llvm::FunctionType::get(ObjectPtrTy, Args, false);
419212904Sdim    return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
420212904Sdim  }
421212904Sdim
422193326Sed  /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
423193326Sed  llvm::Constant *getGcAssignIvarFn() {
424198092Srdivacky    // id objc_assign_ivar(id, id *, ptrdiff_t)
425193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
426193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
427198092Srdivacky    Args.push_back(LongTy);
428198092Srdivacky    llvm::FunctionType *FTy =
429198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
430193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
431193326Sed  }
432198092Srdivacky
433198092Srdivacky  /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
434198092Srdivacky  llvm::Constant *GcMemmoveCollectableFn() {
435198092Srdivacky    // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
436198092Srdivacky    std::vector<const llvm::Type*> Args(1, Int8PtrTy);
437198092Srdivacky    Args.push_back(Int8PtrTy);
438198092Srdivacky    Args.push_back(LongTy);
439198092Srdivacky    llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
440198092Srdivacky    return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
441198092Srdivacky  }
442198092Srdivacky
443193326Sed  /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
444193326Sed  llvm::Constant *getGcAssignStrongCastFn() {
445212904Sdim    // id objc_assign_strongCast(id, id *)
446193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
447193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
448198092Srdivacky    llvm::FunctionType *FTy =
449198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
450193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
451193326Sed  }
452193326Sed
453193326Sed  /// ExceptionThrowFn - LLVM objc_exception_throw function.
454193326Sed  llvm::Constant *getExceptionThrowFn() {
455193326Sed    // void objc_exception_throw(id)
456193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
457193326Sed    llvm::FunctionType *FTy =
458198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
459193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
460193326Sed  }
461198092Srdivacky
462210299Sed  /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
463210299Sed  llvm::Constant *getExceptionRethrowFn() {
464210299Sed    // void objc_exception_rethrow(void)
465210299Sed    std::vector<const llvm::Type*> Args;
466210299Sed    llvm::FunctionType *FTy =
467218893Sdim      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
468210299Sed    return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
469210299Sed  }
470210299Sed
471193326Sed  /// SyncEnterFn - LLVM object_sync_enter function.
472193326Sed  llvm::Constant *getSyncEnterFn() {
473193326Sed    // void objc_sync_enter (id)
474193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
475193326Sed    llvm::FunctionType *FTy =
476198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
477193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
478193326Sed  }
479198092Srdivacky
480193326Sed  /// SyncExitFn - LLVM object_sync_exit function.
481193326Sed  llvm::Constant *getSyncExitFn() {
482193326Sed    // void objc_sync_exit (id)
483193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
484193326Sed    llvm::FunctionType *FTy =
485198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
486193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
487193326Sed  }
488198092Srdivacky
489193326Sed  llvm::Constant *getSendFn(bool IsSuper) const {
490193326Sed    return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
491193326Sed  }
492198092Srdivacky
493193326Sed  llvm::Constant *getSendFn2(bool IsSuper) const {
494193326Sed    return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
495193326Sed  }
496198092Srdivacky
497193326Sed  llvm::Constant *getSendStretFn(bool IsSuper) const {
498193326Sed    return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
499193326Sed  }
500198092Srdivacky
501193326Sed  llvm::Constant *getSendStretFn2(bool IsSuper) const {
502193326Sed    return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
503193326Sed  }
504198092Srdivacky
505193326Sed  llvm::Constant *getSendFpretFn(bool IsSuper) const {
506193326Sed    return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
507193326Sed  }
508198092Srdivacky
509193326Sed  llvm::Constant *getSendFpretFn2(bool IsSuper) const {
510193326Sed    return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
511193326Sed  }
512198092Srdivacky
513193326Sed  ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
514193326Sed  ~ObjCCommonTypesHelper(){}
515193326Sed};
516193326Sed
517193326Sed/// ObjCTypesHelper - Helper class that encapsulates lazy
518193326Sed/// construction of varies types used during ObjC generation.
519193326Sedclass ObjCTypesHelper : public ObjCCommonTypesHelper {
520193326Sedpublic:
521193326Sed  /// SymtabTy - LLVM type for struct objc_symtab.
522193326Sed  const llvm::StructType *SymtabTy;
523193326Sed  /// SymtabPtrTy - LLVM type for struct objc_symtab *.
524193326Sed  const llvm::Type *SymtabPtrTy;
525193326Sed  /// ModuleTy - LLVM type for struct objc_module.
526193326Sed  const llvm::StructType *ModuleTy;
527193326Sed
528193326Sed  /// ProtocolTy - LLVM type for struct objc_protocol.
529193326Sed  const llvm::StructType *ProtocolTy;
530193326Sed  /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
531193326Sed  const llvm::Type *ProtocolPtrTy;
532193326Sed  /// ProtocolExtensionTy - LLVM type for struct
533193326Sed  /// objc_protocol_extension.
534193326Sed  const llvm::StructType *ProtocolExtensionTy;
535193326Sed  /// ProtocolExtensionTy - LLVM type for struct
536193326Sed  /// objc_protocol_extension *.
537193326Sed  const llvm::Type *ProtocolExtensionPtrTy;
538193326Sed  /// MethodDescriptionTy - LLVM type for struct
539193326Sed  /// objc_method_description.
540193326Sed  const llvm::StructType *MethodDescriptionTy;
541193326Sed  /// MethodDescriptionListTy - LLVM type for struct
542193326Sed  /// objc_method_description_list.
543193326Sed  const llvm::StructType *MethodDescriptionListTy;
544193326Sed  /// MethodDescriptionListPtrTy - LLVM type for struct
545193326Sed  /// objc_method_description_list *.
546193326Sed  const llvm::Type *MethodDescriptionListPtrTy;
547193326Sed  /// ProtocolListTy - LLVM type for struct objc_property_list.
548193326Sed  const llvm::Type *ProtocolListTy;
549193326Sed  /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
550193326Sed  const llvm::Type *ProtocolListPtrTy;
551193326Sed  /// CategoryTy - LLVM type for struct objc_category.
552193326Sed  const llvm::StructType *CategoryTy;
553193326Sed  /// ClassTy - LLVM type for struct objc_class.
554193326Sed  const llvm::StructType *ClassTy;
555193326Sed  /// ClassPtrTy - LLVM type for struct objc_class *.
556193326Sed  const llvm::Type *ClassPtrTy;
557193326Sed  /// ClassExtensionTy - LLVM type for struct objc_class_ext.
558193326Sed  const llvm::StructType *ClassExtensionTy;
559193326Sed  /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
560193326Sed  const llvm::Type *ClassExtensionPtrTy;
561193326Sed  // IvarTy - LLVM type for struct objc_ivar.
562193326Sed  const llvm::StructType *IvarTy;
563193326Sed  /// IvarListTy - LLVM type for struct objc_ivar_list.
564193326Sed  const llvm::Type *IvarListTy;
565193326Sed  /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
566193326Sed  const llvm::Type *IvarListPtrTy;
567193326Sed  /// MethodListTy - LLVM type for struct objc_method_list.
568193326Sed  const llvm::Type *MethodListTy;
569193326Sed  /// MethodListPtrTy - LLVM type for struct objc_method_list *.
570193326Sed  const llvm::Type *MethodListPtrTy;
571198092Srdivacky
572193326Sed  /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
573193326Sed  const llvm::Type *ExceptionDataTy;
574198092Srdivacky
575193326Sed  /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
576193326Sed  llvm::Constant *getExceptionTryEnterFn() {
577193326Sed    std::vector<const llvm::Type*> Params;
578193326Sed    Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
579198092Srdivacky    return CGM.CreateRuntimeFunction(
580198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
581198092Srdivacky                              Params, false),
582198092Srdivacky      "objc_exception_try_enter");
583193326Sed  }
584193326Sed
585193326Sed  /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
586193326Sed  llvm::Constant *getExceptionTryExitFn() {
587193326Sed    std::vector<const llvm::Type*> Params;
588193326Sed    Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
589198092Srdivacky    return CGM.CreateRuntimeFunction(
590198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
591198092Srdivacky                              Params, false),
592198092Srdivacky      "objc_exception_try_exit");
593193326Sed  }
594193326Sed
595193326Sed  /// ExceptionExtractFn - LLVM objc_exception_extract function.
596193326Sed  llvm::Constant *getExceptionExtractFn() {
597193326Sed    std::vector<const llvm::Type*> Params;
598193326Sed    Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
599193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
600193326Sed                                                             Params, false),
601193326Sed                                     "objc_exception_extract");
602198092Srdivacky
603193326Sed  }
604198092Srdivacky
605193326Sed  /// ExceptionMatchFn - LLVM objc_exception_match function.
606193326Sed  llvm::Constant *getExceptionMatchFn() {
607193326Sed    std::vector<const llvm::Type*> Params;
608193326Sed    Params.push_back(ClassPtrTy);
609193326Sed    Params.push_back(ObjectPtrTy);
610198092Srdivacky    return CGM.CreateRuntimeFunction(
611198092Srdivacky      llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
612198092Srdivacky                              Params, false),
613198092Srdivacky      "objc_exception_match");
614198092Srdivacky
615193326Sed  }
616198092Srdivacky
617193326Sed  /// SetJmpFn - LLVM _setjmp function.
618193326Sed  llvm::Constant *getSetJmpFn() {
619193326Sed    std::vector<const llvm::Type*> Params;
620198092Srdivacky    Params.push_back(llvm::Type::getInt32PtrTy(VMContext));
621193326Sed    return
622198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
623193326Sed                                                        Params, false),
624193326Sed                                "_setjmp");
625198092Srdivacky
626193326Sed  }
627198092Srdivacky
628193326Sedpublic:
629193326Sed  ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
630193326Sed  ~ObjCTypesHelper() {}
631193326Sed};
632193326Sed
633193326Sed/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
634193326Sed/// modern abi
635193326Sedclass ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
636193326Sedpublic:
637198092Srdivacky
638193326Sed  // MethodListnfABITy - LLVM for struct _method_list_t
639193326Sed  const llvm::StructType *MethodListnfABITy;
640198092Srdivacky
641193326Sed  // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
642193326Sed  const llvm::Type *MethodListnfABIPtrTy;
643198092Srdivacky
644193326Sed  // ProtocolnfABITy = LLVM for struct _protocol_t
645193326Sed  const llvm::StructType *ProtocolnfABITy;
646198092Srdivacky
647193326Sed  // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
648193326Sed  const llvm::Type *ProtocolnfABIPtrTy;
649193326Sed
650193326Sed  // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
651193326Sed  const llvm::StructType *ProtocolListnfABITy;
652198092Srdivacky
653193326Sed  // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
654193326Sed  const llvm::Type *ProtocolListnfABIPtrTy;
655198092Srdivacky
656193326Sed  // ClassnfABITy - LLVM for struct _class_t
657193326Sed  const llvm::StructType *ClassnfABITy;
658198092Srdivacky
659193326Sed  // ClassnfABIPtrTy - LLVM for struct _class_t*
660193326Sed  const llvm::Type *ClassnfABIPtrTy;
661198092Srdivacky
662193326Sed  // IvarnfABITy - LLVM for struct _ivar_t
663193326Sed  const llvm::StructType *IvarnfABITy;
664198092Srdivacky
665193326Sed  // IvarListnfABITy - LLVM for struct _ivar_list_t
666193326Sed  const llvm::StructType *IvarListnfABITy;
667198092Srdivacky
668193326Sed  // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
669193326Sed  const llvm::Type *IvarListnfABIPtrTy;
670198092Srdivacky
671193326Sed  // ClassRonfABITy - LLVM for struct _class_ro_t
672193326Sed  const llvm::StructType *ClassRonfABITy;
673198092Srdivacky
674193326Sed  // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
675193326Sed  const llvm::Type *ImpnfABITy;
676198092Srdivacky
677193326Sed  // CategorynfABITy - LLVM for struct _category_t
678193326Sed  const llvm::StructType *CategorynfABITy;
679198092Srdivacky
680193326Sed  // New types for nonfragile abi messaging.
681198092Srdivacky
682193326Sed  // MessageRefTy - LLVM for:
683193326Sed  // struct _message_ref_t {
684193326Sed  //   IMP messenger;
685193326Sed  //   SEL name;
686193326Sed  // };
687193326Sed  const llvm::StructType *MessageRefTy;
688193326Sed  // MessageRefCTy - clang type for struct _message_ref_t
689193326Sed  QualType MessageRefCTy;
690198092Srdivacky
691193326Sed  // MessageRefPtrTy - LLVM for struct _message_ref_t*
692193326Sed  const llvm::Type *MessageRefPtrTy;
693193326Sed  // MessageRefCPtrTy - clang type for struct _message_ref_t*
694193326Sed  QualType MessageRefCPtrTy;
695198092Srdivacky
696193326Sed  // MessengerTy - Type of the messenger (shown as IMP above)
697193326Sed  const llvm::FunctionType *MessengerTy;
698198092Srdivacky
699193326Sed  // SuperMessageRefTy - LLVM for:
700193326Sed  // struct _super_message_ref_t {
701193326Sed  //   SUPER_IMP messenger;
702193326Sed  //   SEL name;
703193326Sed  // };
704193326Sed  const llvm::StructType *SuperMessageRefTy;
705198092Srdivacky
706193326Sed  // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
707193326Sed  const llvm::Type *SuperMessageRefPtrTy;
708193326Sed
709193326Sed  llvm::Constant *getMessageSendFixupFn() {
710193326Sed    // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
711193326Sed    std::vector<const llvm::Type*> Params;
712193326Sed    Params.push_back(ObjectPtrTy);
713193326Sed    Params.push_back(MessageRefPtrTy);
714193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
715193326Sed                                                             Params, true),
716193326Sed                                     "objc_msgSend_fixup");
717193326Sed  }
718198092Srdivacky
719193326Sed  llvm::Constant *getMessageSendFpretFixupFn() {
720193326Sed    // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
721193326Sed    std::vector<const llvm::Type*> Params;
722193326Sed    Params.push_back(ObjectPtrTy);
723193326Sed    Params.push_back(MessageRefPtrTy);
724193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
725193326Sed                                                             Params, true),
726193326Sed                                     "objc_msgSend_fpret_fixup");
727193326Sed  }
728198092Srdivacky
729193326Sed  llvm::Constant *getMessageSendStretFixupFn() {
730193326Sed    // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
731193326Sed    std::vector<const llvm::Type*> Params;
732193326Sed    Params.push_back(ObjectPtrTy);
733193326Sed    Params.push_back(MessageRefPtrTy);
734193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
735193326Sed                                                             Params, true),
736193326Sed                                     "objc_msgSend_stret_fixup");
737193326Sed  }
738198092Srdivacky
739193326Sed  llvm::Constant *getMessageSendSuper2FixupFn() {
740198092Srdivacky    // id objc_msgSendSuper2_fixup (struct objc_super *,
741193326Sed    //                              struct _super_message_ref_t*, ...)
742193326Sed    std::vector<const llvm::Type*> Params;
743193326Sed    Params.push_back(SuperPtrTy);
744193326Sed    Params.push_back(SuperMessageRefPtrTy);
745193326Sed    return  CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
746193326Sed                                                              Params, true),
747193326Sed                                      "objc_msgSendSuper2_fixup");
748193326Sed  }
749198092Srdivacky
750193326Sed  llvm::Constant *getMessageSendSuper2StretFixupFn() {
751198092Srdivacky    // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
752193326Sed    //                                   struct _super_message_ref_t*, ...)
753193326Sed    std::vector<const llvm::Type*> Params;
754193326Sed    Params.push_back(SuperPtrTy);
755193326Sed    Params.push_back(SuperMessageRefPtrTy);
756193326Sed    return  CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
757193326Sed                                                              Params, true),
758193326Sed                                      "objc_msgSendSuper2_stret_fixup");
759193326Sed  }
760198092Srdivacky
761193326Sed  llvm::Constant *getObjCEndCatchFn() {
762198092Srdivacky    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
763195341Sed                                                             false),
764193326Sed                                     "objc_end_catch");
765198092Srdivacky
766193326Sed  }
767198092Srdivacky
768193326Sed  llvm::Constant *getObjCBeginCatchFn() {
769193326Sed    std::vector<const llvm::Type*> Params;
770193326Sed    Params.push_back(Int8PtrTy);
771193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
772193326Sed                                                             Params, false),
773193326Sed                                     "objc_begin_catch");
774193326Sed  }
775193326Sed
776193326Sed  const llvm::StructType *EHTypeTy;
777193326Sed  const llvm::Type *EHTypePtrTy;
778193326Sed
779193326Sed  ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
780193326Sed  ~ObjCNonFragileABITypesHelper(){}
781193326Sed};
782198092Srdivacky
783193326Sedclass CGObjCCommonMac : public CodeGen::CGObjCRuntime {
784193326Sedpublic:
785193326Sed  // FIXME - accessibility
786193326Sed  class GC_IVAR {
787193326Sed  public:
788193326Sed    unsigned ivar_bytepos;
789193326Sed    unsigned ivar_size;
790193326Sed    GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
791198092Srdivacky      : ivar_bytepos(bytepos), ivar_size(size) {}
792193326Sed
793193326Sed    // Allow sorting based on byte pos.
794193326Sed    bool operator<(const GC_IVAR &b) const {
795193326Sed      return ivar_bytepos < b.ivar_bytepos;
796193326Sed    }
797193326Sed  };
798198092Srdivacky
799193326Sed  class SKIP_SCAN {
800193326Sed  public:
801193326Sed    unsigned skip;
802193326Sed    unsigned scan;
803198092Srdivacky    SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
804193326Sed      : skip(_skip), scan(_scan) {}
805193326Sed  };
806198092Srdivacky
807193326Sedprotected:
808193326Sed  CodeGen::CodeGenModule &CGM;
809198092Srdivacky  llvm::LLVMContext &VMContext;
810193326Sed  // FIXME! May not be needing this after all.
811193326Sed  unsigned ObjCABI;
812198092Srdivacky
813193326Sed  // gc ivar layout bitmap calculation helper caches.
814193326Sed  llvm::SmallVector<GC_IVAR, 16> SkipIvars;
815193326Sed  llvm::SmallVector<GC_IVAR, 16> IvarsInfo;
816198092Srdivacky
817193326Sed  /// LazySymbols - Symbols to generate a lazy reference for. See
818193326Sed  /// DefinedSymbols and FinishModule().
819198092Srdivacky  llvm::SetVector<IdentifierInfo*> LazySymbols;
820198092Srdivacky
821193326Sed  /// DefinedSymbols - External symbols which are defined by this
822193326Sed  /// module. The symbols in this list and LazySymbols are used to add
823193326Sed  /// special linker symbols which ensure that Objective-C modules are
824193326Sed  /// linked properly.
825198092Srdivacky  llvm::SetVector<IdentifierInfo*> DefinedSymbols;
826198092Srdivacky
827193326Sed  /// ClassNames - uniqued class names.
828193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
829198092Srdivacky
830193326Sed  /// MethodVarNames - uniqued method variable names.
831193326Sed  llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
832198092Srdivacky
833210299Sed  /// DefinedCategoryNames - list of category names in form Class_Category.
834210299Sed  llvm::SetVector<std::string> DefinedCategoryNames;
835210299Sed
836193326Sed  /// MethodVarTypes - uniqued method type signatures. We have to use
837193326Sed  /// a StringMap here because have no other unique reference.
838193326Sed  llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
839198092Srdivacky
840193326Sed  /// MethodDefinitions - map of methods which have been defined in
841193326Sed  /// this translation unit.
842193326Sed  llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
843198092Srdivacky
844193326Sed  /// PropertyNames - uniqued method variable names.
845193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
846198092Srdivacky
847193326Sed  /// ClassReferences - uniqued class references.
848193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
849198092Srdivacky
850193326Sed  /// SelectorReferences - uniqued selector references.
851193326Sed  llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
852198092Srdivacky
853193326Sed  /// Protocols - Protocols for which an objc_protocol structure has
854193326Sed  /// been emitted. Forward declarations are handled by creating an
855193326Sed  /// empty structure whose initializer is filled in when/if defined.
856193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
857198092Srdivacky
858193326Sed  /// DefinedProtocols - Protocols which have actually been
859193326Sed  /// defined. We should not need this, see FIXME in GenerateProtocol.
860193326Sed  llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
861198092Srdivacky
862193326Sed  /// DefinedClasses - List of defined classes.
863193326Sed  std::vector<llvm::GlobalValue*> DefinedClasses;
864193326Sed
865193326Sed  /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
866193326Sed  std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
867198092Srdivacky
868193326Sed  /// DefinedCategories - List of defined categories.
869193326Sed  std::vector<llvm::GlobalValue*> DefinedCategories;
870198092Srdivacky
871193326Sed  /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
872193326Sed  std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
873193326Sed
874193326Sed  /// GetNameForMethod - Return a name for the given method.
875193326Sed  /// \param[out] NameOut - The return value.
876193326Sed  void GetNameForMethod(const ObjCMethodDecl *OMD,
877193326Sed                        const ObjCContainerDecl *CD,
878198398Srdivacky                        llvm::SmallVectorImpl<char> &NameOut);
879198092Srdivacky
880193326Sed  /// GetMethodVarName - Return a unique constant for the given
881193326Sed  /// selector's name. The return value has type char *.
882193326Sed  llvm::Constant *GetMethodVarName(Selector Sel);
883193326Sed  llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
884198092Srdivacky
885193326Sed  /// GetMethodVarType - Return a unique constant for the given
886193326Sed  /// selector's name. The return value has type char *.
887198092Srdivacky
888193326Sed  // FIXME: This is a horrible name.
889193326Sed  llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
890193326Sed  llvm::Constant *GetMethodVarType(const FieldDecl *D);
891198092Srdivacky
892193326Sed  /// GetPropertyName - Return a unique constant for the given
893193326Sed  /// name. The return value has type char *.
894193326Sed  llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
895198092Srdivacky
896193326Sed  // FIXME: This can be dropped once string functions are unified.
897193326Sed  llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
898193326Sed                                        const Decl *Container);
899198092Srdivacky
900193326Sed  /// GetClassName - Return a unique constant for the given selector's
901193326Sed  /// name. The return value has type char *.
902193326Sed  llvm::Constant *GetClassName(IdentifierInfo *Ident);
903198092Srdivacky
904212904Sdim  llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
905212904Sdim
906193326Sed  /// BuildIvarLayout - Builds ivar layout bitmap for the class
907193326Sed  /// implementation for the __strong or __weak case.
908193326Sed  ///
909193326Sed  llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
910193326Sed                                  bool ForStrongLayout);
911212904Sdim
912212904Sdim  llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
913198092Srdivacky
914193326Sed  void BuildAggrIvarRecordLayout(const RecordType *RT,
915198092Srdivacky                                 unsigned int BytePos, bool ForStrongLayout,
916198092Srdivacky                                 bool &HasUnion);
917193326Sed  void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
918193326Sed                           const llvm::StructLayout *Layout,
919193326Sed                           const RecordDecl *RD,
920193326Sed                           const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
921193326Sed                           unsigned int BytePos, bool ForStrongLayout,
922193326Sed                           bool &HasUnion);
923193326Sed
924193326Sed  /// GetIvarLayoutName - Returns a unique constant for the given
925193326Sed  /// ivar layout bitmap.
926193326Sed  llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
927193326Sed                                    const ObjCCommonTypesHelper &ObjCTypes);
928198092Srdivacky
929193326Sed  /// EmitPropertyList - Emit the given property list. The return
930193326Sed  /// value has type PropertyListPtrTy.
931198398Srdivacky  llvm::Constant *EmitPropertyList(llvm::Twine Name,
932198092Srdivacky                                   const Decl *Container,
933193326Sed                                   const ObjCContainerDecl *OCD,
934193326Sed                                   const ObjCCommonTypesHelper &ObjCTypes);
935198092Srdivacky
936200583Srdivacky  /// PushProtocolProperties - Push protocol's property on the input stack.
937200583Srdivacky  void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
938200583Srdivacky                              std::vector<llvm::Constant*> &Properties,
939200583Srdivacky                                   const Decl *Container,
940200583Srdivacky                                   const ObjCProtocolDecl *PROTO,
941200583Srdivacky                                   const ObjCCommonTypesHelper &ObjCTypes);
942200583Srdivacky
943193326Sed  /// GetProtocolRef - Return a reference to the internal protocol
944193326Sed  /// description, creating an empty one if it has not been
945193326Sed  /// defined. The return value has type ProtocolPtrTy.
946193326Sed  llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
947193326Sed
948193326Sed  /// CreateMetadataVar - Create a global variable with internal
949193326Sed  /// linkage for use by the Objective-C runtime.
950193326Sed  ///
951193326Sed  /// This is a convenience wrapper which not only creates the
952193326Sed  /// variable, but also sets the section and alignment and adds the
953198092Srdivacky  /// global to the "llvm.used" list.
954193326Sed  ///
955193326Sed  /// \param Name - The variable name.
956193326Sed  /// \param Init - The variable initializer; this is also used to
957193326Sed  /// define the type of the variable.
958193326Sed  /// \param Section - The section the variable should go into, or 0.
959193326Sed  /// \param Align - The alignment for the variable, or 0.
960193326Sed  /// \param AddToUsed - Whether the variable should be added to
961193326Sed  /// "llvm.used".
962198398Srdivacky  llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
963193326Sed                                          llvm::Constant *Init,
964193326Sed                                          const char *Section,
965193326Sed                                          unsigned Align,
966193326Sed                                          bool AddToUsed);
967193326Sed
968193326Sed  CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
969208600Srdivacky                                        ReturnValueSlot Return,
970193326Sed                                        QualType ResultType,
971193326Sed                                        llvm::Value *Sel,
972193326Sed                                        llvm::Value *Arg0,
973193326Sed                                        QualType Arg0Ty,
974193326Sed                                        bool IsSuper,
975193326Sed                                        const CallArgList &CallArgs,
976198092Srdivacky                                        const ObjCMethodDecl *OMD,
977193326Sed                                        const ObjCCommonTypesHelper &ObjCTypes);
978193326Sed
979207619Srdivacky  /// EmitImageInfo - Emit the image info marker used to encode some module
980207619Srdivacky  /// level information.
981207619Srdivacky  void EmitImageInfo();
982207619Srdivacky
983198092Srdivackypublic:
984198092Srdivacky  CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
985198092Srdivacky    CGM(cgm), VMContext(cgm.getLLVMContext()) { }
986195099Sed
987202879Srdivacky  virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
988198092Srdivacky
989193326Sed  virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
990193326Sed                                         const ObjCContainerDecl *CD=0);
991198092Srdivacky
992193326Sed  virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
993198092Srdivacky
994193326Sed  /// GetOrEmitProtocol - Get the protocol object for the given
995193326Sed  /// declaration, emitting it if necessary. The return value has type
996193326Sed  /// ProtocolPtrTy.
997193326Sed  virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
998198092Srdivacky
999193326Sed  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1000193326Sed  /// object for the given declaration, emitting it if needed. These
1001193326Sed  /// forward references will be filled in with empty bodies if no
1002193326Sed  /// definition is seen. The return value has type ProtocolPtrTy.
1003193326Sed  virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
1004218893Sdim  virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1005218893Sdim                                             const CGBlockInfo &blockInfo);
1006212904Sdim
1007193326Sed};
1008198092Srdivacky
1009193326Sedclass CGObjCMac : public CGObjCCommonMac {
1010193326Sedprivate:
1011193326Sed  ObjCTypesHelper ObjCTypes;
1012193326Sed
1013193326Sed  /// EmitModuleInfo - Another marker encoding module level
1014198092Srdivacky  /// information.
1015193326Sed  void EmitModuleInfo();
1016193326Sed
1017193326Sed  /// EmitModuleSymols - Emit module symbols, the list of defined
1018193326Sed  /// classes and categories. The result has type SymtabPtrTy.
1019193326Sed  llvm::Constant *EmitModuleSymbols();
1020193326Sed
1021193326Sed  /// FinishModule - Write out global data structures at the end of
1022193326Sed  /// processing a translation unit.
1023193326Sed  void FinishModule();
1024193326Sed
1025193326Sed  /// EmitClassExtension - Generate the class extension structure used
1026193326Sed  /// to store the weak ivar layout and properties. The return value
1027193326Sed  /// has type ClassExtensionPtrTy.
1028193326Sed  llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
1029193326Sed
1030193326Sed  /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1031193326Sed  /// for the given class.
1032198092Srdivacky  llvm::Value *EmitClassRef(CGBuilderTy &Builder,
1033193326Sed                            const ObjCInterfaceDecl *ID);
1034199482Srdivacky
1035199482Srdivacky  /// EmitSuperClassRef - Emits reference to class's main metadata class.
1036199482Srdivacky  llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
1037193326Sed
1038193326Sed  /// EmitIvarList - Emit the ivar list for the given
1039193326Sed  /// implementation. If ForClass is true the list of class ivars
1040193326Sed  /// (i.e. metaclass ivars) is emitted, otherwise the list of
1041193326Sed  /// interface ivars will be emitted. The return value has type
1042193326Sed  /// IvarListPtrTy.
1043193326Sed  llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
1044193326Sed                               bool ForClass);
1045198092Srdivacky
1046193326Sed  /// EmitMetaClass - Emit a forward reference to the class structure
1047193326Sed  /// for the metaclass of the given interface. The return value has
1048193326Sed  /// type ClassPtrTy.
1049193326Sed  llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1050193326Sed
1051193326Sed  /// EmitMetaClass - Emit a class structure for the metaclass of the
1052193326Sed  /// given implementation. The return value has type ClassPtrTy.
1053193326Sed  llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1054193326Sed                                llvm::Constant *Protocols,
1055193326Sed                                const ConstantVector &Methods);
1056198092Srdivacky
1057193326Sed  llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
1058198092Srdivacky
1059193326Sed  llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
1060193326Sed
1061193326Sed  /// EmitMethodList - Emit the method list for the given
1062193326Sed  /// implementation. The return value has type MethodListPtrTy.
1063198398Srdivacky  llvm::Constant *EmitMethodList(llvm::Twine Name,
1064193326Sed                                 const char *Section,
1065193326Sed                                 const ConstantVector &Methods);
1066193326Sed
1067193326Sed  /// EmitMethodDescList - Emit a method description list for a list of
1068198092Srdivacky  /// method declarations.
1069193326Sed  ///  - TypeName: The name for the type containing the methods.
1070193326Sed  ///  - IsProtocol: True iff these methods are for a protocol.
1071193326Sed  ///  - ClassMethds: True iff these are class methods.
1072193326Sed  ///  - Required: When true, only "required" methods are
1073193326Sed  ///    listed. Similarly, when false only "optional" methods are
1074193326Sed  ///    listed. For classes this should always be true.
1075193326Sed  ///  - begin, end: The method list to output.
1076193326Sed  ///
1077193326Sed  /// The return value has type MethodDescriptionListPtrTy.
1078198398Srdivacky  llvm::Constant *EmitMethodDescList(llvm::Twine Name,
1079193326Sed                                     const char *Section,
1080193326Sed                                     const ConstantVector &Methods);
1081193326Sed
1082193326Sed  /// GetOrEmitProtocol - Get the protocol object for the given
1083193326Sed  /// declaration, emitting it if necessary. The return value has type
1084193326Sed  /// ProtocolPtrTy.
1085193326Sed  virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
1086193326Sed
1087193326Sed  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1088193326Sed  /// object for the given declaration, emitting it if needed. These
1089193326Sed  /// forward references will be filled in with empty bodies if no
1090193326Sed  /// definition is seen. The return value has type ProtocolPtrTy.
1091193326Sed  virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
1092193326Sed
1093193326Sed  /// EmitProtocolExtension - Generate the protocol extension
1094193326Sed  /// structure used to store optional instance and class methods, and
1095193326Sed  /// protocol properties. The return value has type
1096193326Sed  /// ProtocolExtensionPtrTy.
1097193326Sed  llvm::Constant *
1098193326Sed  EmitProtocolExtension(const ObjCProtocolDecl *PD,
1099193326Sed                        const ConstantVector &OptInstanceMethods,
1100193326Sed                        const ConstantVector &OptClassMethods);
1101193326Sed
1102193326Sed  /// EmitProtocolList - Generate the list of referenced
1103193326Sed  /// protocols. The return value has type ProtocolListPtrTy.
1104198398Srdivacky  llvm::Constant *EmitProtocolList(llvm::Twine Name,
1105193326Sed                                   ObjCProtocolDecl::protocol_iterator begin,
1106193326Sed                                   ObjCProtocolDecl::protocol_iterator end);
1107193326Sed
1108193326Sed  /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1109193326Sed  /// for the given selector.
1110210299Sed  llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1111210299Sed                            bool lval=false);
1112198092Srdivacky
1113198092Srdivackypublic:
1114193326Sed  CGObjCMac(CodeGen::CodeGenModule &cgm);
1115193326Sed
1116193326Sed  virtual llvm::Function *ModuleInitFunction();
1117198092Srdivacky
1118193326Sed  virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1119208600Srdivacky                                              ReturnValueSlot Return,
1120193326Sed                                              QualType ResultType,
1121193326Sed                                              Selector Sel,
1122193326Sed                                              llvm::Value *Receiver,
1123193326Sed                                              const CallArgList &CallArgs,
1124207619Srdivacky                                              const ObjCInterfaceDecl *Class,
1125193326Sed                                              const ObjCMethodDecl *Method);
1126193326Sed
1127198092Srdivacky  virtual CodeGen::RValue
1128193326Sed  GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1129208600Srdivacky                           ReturnValueSlot Return,
1130193326Sed                           QualType ResultType,
1131193326Sed                           Selector Sel,
1132193326Sed                           const ObjCInterfaceDecl *Class,
1133193326Sed                           bool isCategoryImpl,
1134193326Sed                           llvm::Value *Receiver,
1135193326Sed                           bool IsClassMessage,
1136198092Srdivacky                           const CallArgList &CallArgs,
1137198092Srdivacky                           const ObjCMethodDecl *Method);
1138198092Srdivacky
1139193326Sed  virtual llvm::Value *GetClass(CGBuilderTy &Builder,
1140193326Sed                                const ObjCInterfaceDecl *ID);
1141193326Sed
1142210299Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1143210299Sed                                   bool lval = false);
1144193326Sed
1145193326Sed  /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1146193326Sed  /// untyped one.
1147193326Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1148193326Sed                                   const ObjCMethodDecl *Method);
1149193326Sed
1150212904Sdim  virtual llvm::Constant *GetEHType(QualType T);
1151212904Sdim
1152193326Sed  virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
1153193326Sed
1154193326Sed  virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
1155193326Sed
1156193326Sed  virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
1157193326Sed                                           const ObjCProtocolDecl *PD);
1158198092Srdivacky
1159193326Sed  virtual llvm::Constant *GetPropertyGetFunction();
1160193326Sed  virtual llvm::Constant *GetPropertySetFunction();
1161218893Sdim  virtual llvm::Constant *GetGetStructFunction();
1162218893Sdim  virtual llvm::Constant *GetSetStructFunction();
1163193326Sed  virtual llvm::Constant *EnumerationMutationFunction();
1164198092Srdivacky
1165210299Sed  virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1166210299Sed                           const ObjCAtTryStmt &S);
1167210299Sed  virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1168210299Sed                                    const ObjCAtSynchronizedStmt &S);
1169210299Sed  void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
1170193326Sed  virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1171193326Sed                             const ObjCAtThrowStmt &S);
1172193326Sed  virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1173198092Srdivacky                                         llvm::Value *AddrWeakObj);
1174193326Sed  virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1175198092Srdivacky                                  llvm::Value *src, llvm::Value *dst);
1176193326Sed  virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1177212904Sdim                                    llvm::Value *src, llvm::Value *dest,
1178212904Sdim                                    bool threadlocal = false);
1179193326Sed  virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1180198092Srdivacky                                  llvm::Value *src, llvm::Value *dest,
1181198092Srdivacky                                  llvm::Value *ivarOffset);
1182193326Sed  virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1183193326Sed                                        llvm::Value *src, llvm::Value *dest);
1184198092Srdivacky  virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1185198092Srdivacky                                        llvm::Value *dest, llvm::Value *src,
1186210299Sed                                        llvm::Value *size);
1187198092Srdivacky
1188193326Sed  virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1189193326Sed                                      QualType ObjectTy,
1190193326Sed                                      llvm::Value *BaseValue,
1191193326Sed                                      const ObjCIvarDecl *Ivar,
1192193326Sed                                      unsigned CVRQualifiers);
1193193326Sed  virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1194193326Sed                                      const ObjCInterfaceDecl *Interface,
1195193326Sed                                      const ObjCIvarDecl *Ivar);
1196193326Sed};
1197198092Srdivacky
1198193326Sedclass CGObjCNonFragileABIMac : public CGObjCCommonMac {
1199193326Sedprivate:
1200193326Sed  ObjCNonFragileABITypesHelper ObjCTypes;
1201193326Sed  llvm::GlobalVariable* ObjCEmptyCacheVar;
1202193326Sed  llvm::GlobalVariable* ObjCEmptyVtableVar;
1203198092Srdivacky
1204193326Sed  /// SuperClassReferences - uniqued super class references.
1205193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
1206198092Srdivacky
1207193326Sed  /// MetaClassReferences - uniqued meta class references.
1208193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
1209193326Sed
1210193326Sed  /// EHTypeReferences - uniqued class ehtype references.
1211193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
1212198092Srdivacky
1213193326Sed  /// NonLegacyDispatchMethods - List of methods for which we do *not* generate
1214193326Sed  /// legacy messaging dispatch.
1215193326Sed  llvm::DenseSet<Selector> NonLegacyDispatchMethods;
1216198092Srdivacky
1217199482Srdivacky  /// DefinedMetaClasses - List of defined meta-classes.
1218199482Srdivacky  std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1219199482Srdivacky
1220193326Sed  /// LegacyDispatchedSelector - Returns true if SEL is not in the list of
1221193326Sed  /// NonLegacyDispatchMethods; false otherwise.
1222193326Sed  bool LegacyDispatchedSelector(Selector Sel);
1223198092Srdivacky
1224193326Sed  /// FinishNonFragileABIModule - Write out global data structures at the end of
1225193326Sed  /// processing a translation unit.
1226193326Sed  void FinishNonFragileABIModule();
1227193326Sed
1228193326Sed  /// AddModuleClassList - Add the given list of class pointers to the
1229193326Sed  /// module with the provided symbol and section names.
1230193326Sed  void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container,
1231193326Sed                          const char *SymbolName,
1232193326Sed                          const char *SectionName);
1233193326Sed
1234198092Srdivacky  llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1235198092Srdivacky                                              unsigned InstanceStart,
1236198092Srdivacky                                              unsigned InstanceSize,
1237198092Srdivacky                                              const ObjCImplementationDecl *ID);
1238193326Sed  llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
1239198092Srdivacky                                            llvm::Constant *IsAGV,
1240193326Sed                                            llvm::Constant *SuperClassGV,
1241193326Sed                                            llvm::Constant *ClassRoGV,
1242193326Sed                                            bool HiddenVisibility);
1243198092Srdivacky
1244193326Sed  llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
1245198092Srdivacky
1246193326Sed  llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
1247198092Srdivacky
1248193326Sed  /// EmitMethodList - Emit the method list for the given
1249193326Sed  /// implementation. The return value has type MethodListnfABITy.
1250198398Srdivacky  llvm::Constant *EmitMethodList(llvm::Twine Name,
1251193326Sed                                 const char *Section,
1252193326Sed                                 const ConstantVector &Methods);
1253193326Sed  /// EmitIvarList - Emit the ivar list for the given
1254193326Sed  /// implementation. If ForClass is true the list of class ivars
1255193326Sed  /// (i.e. metaclass ivars) is emitted, otherwise the list of
1256193326Sed  /// interface ivars will be emitted. The return value has type
1257193326Sed  /// IvarListnfABIPtrTy.
1258193326Sed  llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
1259198092Srdivacky
1260193326Sed  llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
1261193326Sed                                    const ObjCIvarDecl *Ivar,
1262193326Sed                                    unsigned long int offset);
1263198092Srdivacky
1264193326Sed  /// GetOrEmitProtocol - Get the protocol object for the given
1265193326Sed  /// declaration, emitting it if necessary. The return value has type
1266193326Sed  /// ProtocolPtrTy.
1267193326Sed  virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
1268198092Srdivacky
1269193326Sed  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1270193326Sed  /// object for the given declaration, emitting it if needed. These
1271193326Sed  /// forward references will be filled in with empty bodies if no
1272193326Sed  /// definition is seen. The return value has type ProtocolPtrTy.
1273193326Sed  virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
1274198092Srdivacky
1275193326Sed  /// EmitProtocolList - Generate the list of referenced
1276193326Sed  /// protocols. The return value has type ProtocolListPtrTy.
1277198398Srdivacky  llvm::Constant *EmitProtocolList(llvm::Twine Name,
1278193326Sed                                   ObjCProtocolDecl::protocol_iterator begin,
1279193326Sed                                   ObjCProtocolDecl::protocol_iterator end);
1280198092Srdivacky
1281193326Sed  CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1282208600Srdivacky                                  ReturnValueSlot Return,
1283193326Sed                                  QualType ResultType,
1284193326Sed                                  Selector Sel,
1285193326Sed                                  llvm::Value *Receiver,
1286193326Sed                                  QualType Arg0Ty,
1287193326Sed                                  bool IsSuper,
1288193326Sed                                  const CallArgList &CallArgs);
1289193326Sed
1290193326Sed  /// GetClassGlobal - Return the global variable for the Objective-C
1291193326Sed  /// class of the given name.
1292193326Sed  llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
1293198092Srdivacky
1294193326Sed  /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1295193326Sed  /// for the given class reference.
1296198092Srdivacky  llvm::Value *EmitClassRef(CGBuilderTy &Builder,
1297193326Sed                            const ObjCInterfaceDecl *ID);
1298198092Srdivacky
1299193326Sed  /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1300193326Sed  /// for the given super class reference.
1301198092Srdivacky  llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1302198092Srdivacky                                 const ObjCInterfaceDecl *ID);
1303198092Srdivacky
1304193326Sed  /// EmitMetaClassRef - Return a Value * of the address of _class_t
1305193326Sed  /// meta-data
1306198092Srdivacky  llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
1307193326Sed                                const ObjCInterfaceDecl *ID);
1308193326Sed
1309193326Sed  /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1310193326Sed  /// the given ivar.
1311193326Sed  ///
1312193326Sed  llvm::GlobalVariable * ObjCIvarOffsetVariable(
1313198092Srdivacky    const ObjCInterfaceDecl *ID,
1314198092Srdivacky    const ObjCIvarDecl *Ivar);
1315198092Srdivacky
1316193326Sed  /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1317193326Sed  /// for the given selector.
1318210299Sed  llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1319210299Sed                            bool lval=false);
1320193326Sed
1321193326Sed  /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
1322193326Sed  /// interface. The return value has type EHTypePtrTy.
1323212904Sdim  llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
1324193326Sed                                  bool ForDefinition);
1325193326Sed
1326198092Srdivacky  const char *getMetaclassSymbolPrefix() const {
1327193326Sed    return "OBJC_METACLASS_$_";
1328193326Sed  }
1329198092Srdivacky
1330193326Sed  const char *getClassSymbolPrefix() const {
1331193326Sed    return "OBJC_CLASS_$_";
1332193326Sed  }
1333193326Sed
1334193326Sed  void GetClassSizeInfo(const ObjCImplementationDecl *OID,
1335193326Sed                        uint32_t &InstanceStart,
1336193326Sed                        uint32_t &InstanceSize);
1337198092Srdivacky
1338193326Sed  // Shamelessly stolen from Analysis/CFRefCount.cpp
1339193326Sed  Selector GetNullarySelector(const char* name) const {
1340193326Sed    IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1341193326Sed    return CGM.getContext().Selectors.getSelector(0, &II);
1342193326Sed  }
1343198092Srdivacky
1344193326Sed  Selector GetUnarySelector(const char* name) const {
1345193326Sed    IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1346193326Sed    return CGM.getContext().Selectors.getSelector(1, &II);
1347193326Sed  }
1348193326Sed
1349193326Sed  /// ImplementationIsNonLazy - Check whether the given category or
1350193326Sed  /// class implementation is "non-lazy".
1351193326Sed  bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
1352193326Sed
1353193326Sedpublic:
1354193326Sed  CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
1355193326Sed  // FIXME. All stubs for now!
1356193326Sed  virtual llvm::Function *ModuleInitFunction();
1357198092Srdivacky
1358193326Sed  virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1359208600Srdivacky                                              ReturnValueSlot Return,
1360193326Sed                                              QualType ResultType,
1361193326Sed                                              Selector Sel,
1362193326Sed                                              llvm::Value *Receiver,
1363193326Sed                                              const CallArgList &CallArgs,
1364207619Srdivacky                                              const ObjCInterfaceDecl *Class,
1365193326Sed                                              const ObjCMethodDecl *Method);
1366198092Srdivacky
1367198092Srdivacky  virtual CodeGen::RValue
1368193326Sed  GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1369208600Srdivacky                           ReturnValueSlot Return,
1370193326Sed                           QualType ResultType,
1371193326Sed                           Selector Sel,
1372193326Sed                           const ObjCInterfaceDecl *Class,
1373193326Sed                           bool isCategoryImpl,
1374193326Sed                           llvm::Value *Receiver,
1375193326Sed                           bool IsClassMessage,
1376198092Srdivacky                           const CallArgList &CallArgs,
1377198092Srdivacky                           const ObjCMethodDecl *Method);
1378198092Srdivacky
1379193326Sed  virtual llvm::Value *GetClass(CGBuilderTy &Builder,
1380193326Sed                                const ObjCInterfaceDecl *ID);
1381198092Srdivacky
1382210299Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1383210299Sed                                   bool lvalue = false)
1384210299Sed    { return EmitSelector(Builder, Sel, lvalue); }
1385193326Sed
1386193326Sed  /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1387193326Sed  /// untyped one.
1388193326Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1389193326Sed                                   const ObjCMethodDecl *Method)
1390193326Sed    { return EmitSelector(Builder, Method->getSelector()); }
1391198092Srdivacky
1392193326Sed  virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
1393198092Srdivacky
1394193326Sed  virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
1395193326Sed  virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
1396193326Sed                                           const ObjCProtocolDecl *PD);
1397198092Srdivacky
1398212904Sdim  virtual llvm::Constant *GetEHType(QualType T);
1399212904Sdim
1400198092Srdivacky  virtual llvm::Constant *GetPropertyGetFunction() {
1401193326Sed    return ObjCTypes.getGetPropertyFn();
1402193326Sed  }
1403198092Srdivacky  virtual llvm::Constant *GetPropertySetFunction() {
1404198092Srdivacky    return ObjCTypes.getSetPropertyFn();
1405193326Sed  }
1406207619Srdivacky
1407218893Sdim  virtual llvm::Constant *GetSetStructFunction() {
1408207619Srdivacky    return ObjCTypes.getCopyStructFn();
1409207619Srdivacky  }
1410218893Sdim  virtual llvm::Constant *GetGetStructFunction() {
1411218893Sdim    return ObjCTypes.getCopyStructFn();
1412218893Sdim  }
1413207619Srdivacky
1414193326Sed  virtual llvm::Constant *EnumerationMutationFunction() {
1415193326Sed    return ObjCTypes.getEnumerationMutationFn();
1416193326Sed  }
1417198092Srdivacky
1418210299Sed  virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1419210299Sed                           const ObjCAtTryStmt &S);
1420210299Sed  virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1421210299Sed                                    const ObjCAtSynchronizedStmt &S);
1422193326Sed  virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1423193326Sed                             const ObjCAtThrowStmt &S);
1424193326Sed  virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1425193326Sed                                         llvm::Value *AddrWeakObj);
1426193326Sed  virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1427193326Sed                                  llvm::Value *src, llvm::Value *dst);
1428193326Sed  virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1429212904Sdim                                    llvm::Value *src, llvm::Value *dest,
1430212904Sdim                                    bool threadlocal = false);
1431193326Sed  virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1432198092Srdivacky                                  llvm::Value *src, llvm::Value *dest,
1433198092Srdivacky                                  llvm::Value *ivarOffset);
1434193326Sed  virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1435193326Sed                                        llvm::Value *src, llvm::Value *dest);
1436198092Srdivacky  virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1437198092Srdivacky                                        llvm::Value *dest, llvm::Value *src,
1438210299Sed                                        llvm::Value *size);
1439193326Sed  virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1440193326Sed                                      QualType ObjectTy,
1441193326Sed                                      llvm::Value *BaseValue,
1442193326Sed                                      const ObjCIvarDecl *Ivar,
1443193326Sed                                      unsigned CVRQualifiers);
1444193326Sed  virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1445193326Sed                                      const ObjCInterfaceDecl *Interface,
1446193326Sed                                      const ObjCIvarDecl *Ivar);
1447193326Sed};
1448198092Srdivacky
1449193326Sed} // end anonymous namespace
1450193326Sed
1451193326Sed/* *** Helper Functions *** */
1452193326Sed
1453193326Sed/// getConstantGEP() - Help routine to construct simple GEPs.
1454198092Srdivackystatic llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
1455198092Srdivacky                                      llvm::Constant *C,
1456193326Sed                                      unsigned idx0,
1457193326Sed                                      unsigned idx1) {
1458193326Sed  llvm::Value *Idxs[] = {
1459198092Srdivacky    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1460198092Srdivacky    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
1461193326Sed  };
1462193326Sed  return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
1463193326Sed}
1464193326Sed
1465193326Sed/// hasObjCExceptionAttribute - Return true if this class or any super
1466193326Sed/// class has the __objc_exception__ attribute.
1467198092Srdivackystatic bool hasObjCExceptionAttribute(ASTContext &Context,
1468194613Sed                                      const ObjCInterfaceDecl *OID) {
1469195341Sed  if (OID->hasAttr<ObjCExceptionAttr>())
1470193326Sed    return true;
1471193326Sed  if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
1472194613Sed    return hasObjCExceptionAttribute(Context, Super);
1473193326Sed  return false;
1474193326Sed}
1475193326Sed
1476193326Sed/* *** CGObjCMac Public Interface *** */
1477198092Srdivacky
1478193326SedCGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
1479198092Srdivacky                                                    ObjCTypes(cgm) {
1480193326Sed  ObjCABI = 1;
1481198092Srdivacky  EmitImageInfo();
1482193326Sed}
1483193326Sed
1484193326Sed/// GetClass - Return a reference to the class for the given interface
1485193326Sed/// decl.
1486193326Sedllvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
1487193326Sed                                 const ObjCInterfaceDecl *ID) {
1488193326Sed  return EmitClassRef(Builder, ID);
1489193326Sed}
1490193326Sed
1491193326Sed/// GetSelector - Return the pointer to the unique'd string for this selector.
1492210299Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1493210299Sed                                    bool lval) {
1494210299Sed  return EmitSelector(Builder, Sel, lval);
1495193326Sed}
1496193326Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
1497198092Srdivacky                                    *Method) {
1498193326Sed  return EmitSelector(Builder, Method->getSelector());
1499193326Sed}
1500193326Sed
1501212904Sdimllvm::Constant *CGObjCMac::GetEHType(QualType T) {
1502212904Sdim  llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
1503212904Sdim  return 0;
1504212904Sdim}
1505212904Sdim
1506193326Sed/// Generate a constant CFString object.
1507198092Srdivacky/*
1508198092Srdivacky  struct __builtin_CFString {
1509198092Srdivacky  const int *isa; // point to __CFConstantStringClassReference
1510198092Srdivacky  int flags;
1511198092Srdivacky  const char *str;
1512198092Srdivacky  long length;
1513198092Srdivacky  };
1514193326Sed*/
1515193326Sed
1516207619Srdivacky/// or Generate a constant NSString object.
1517207619Srdivacky/*
1518207619Srdivacky   struct __builtin_NSString {
1519207619Srdivacky     const int *isa; // point to __NSConstantStringClassReference
1520207619Srdivacky     const char *str;
1521207619Srdivacky     unsigned int length;
1522207619Srdivacky   };
1523207619Srdivacky*/
1524207619Srdivacky
1525193326Sedllvm::Constant *CGObjCCommonMac::GenerateConstantString(
1526202879Srdivacky  const StringLiteral *SL) {
1527207619Srdivacky  return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
1528207619Srdivacky          CGM.GetAddrOfConstantCFString(SL) :
1529218893Sdim          CGM.GetAddrOfConstantString(SL));
1530193326Sed}
1531193326Sed
1532193326Sed/// Generates a message send where the super is the receiver.  This is
1533193326Sed/// a message send to self with special delivery semantics indicating
1534193326Sed/// which class's method should be called.
1535193326SedCodeGen::RValue
1536193326SedCGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1537208600Srdivacky                                    ReturnValueSlot Return,
1538193326Sed                                    QualType ResultType,
1539193326Sed                                    Selector Sel,
1540193326Sed                                    const ObjCInterfaceDecl *Class,
1541193326Sed                                    bool isCategoryImpl,
1542193326Sed                                    llvm::Value *Receiver,
1543193326Sed                                    bool IsClassMessage,
1544198092Srdivacky                                    const CodeGen::CallArgList &CallArgs,
1545198092Srdivacky                                    const ObjCMethodDecl *Method) {
1546193326Sed  // Create and init a super structure; this is a (receiver, class)
1547193326Sed  // pair we will pass to objc_msgSendSuper.
1548198092Srdivacky  llvm::Value *ObjCSuper =
1549193326Sed    CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
1550198092Srdivacky  llvm::Value *ReceiverAsObject =
1551193326Sed    CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
1552198092Srdivacky  CGF.Builder.CreateStore(ReceiverAsObject,
1553193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 0));
1554193326Sed
1555193326Sed  // If this is a class message the metaclass is passed as the target.
1556193326Sed  llvm::Value *Target;
1557193326Sed  if (IsClassMessage) {
1558193326Sed    if (isCategoryImpl) {
1559193326Sed      // Message sent to 'super' in a class method defined in a category
1560193326Sed      // implementation requires an odd treatment.
1561193326Sed      // If we are in a class method, we must retrieve the
1562193326Sed      // _metaclass_ for the current class, pointed at by
1563193326Sed      // the class's "isa" pointer.  The following assumes that
1564193326Sed      // isa" is the first ivar in a class (which it must be).
1565193326Sed      Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1566193326Sed      Target = CGF.Builder.CreateStructGEP(Target, 0);
1567193326Sed      Target = CGF.Builder.CreateLoad(Target);
1568198092Srdivacky    } else {
1569193326Sed      llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1570193326Sed      llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1571193326Sed      llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1572193326Sed      Target = Super;
1573198092Srdivacky    }
1574199482Srdivacky  }
1575199482Srdivacky  else if (isCategoryImpl)
1576193326Sed    Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1577199482Srdivacky  else {
1578199482Srdivacky    llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1579199482Srdivacky    ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1580199482Srdivacky    Target = CGF.Builder.CreateLoad(ClassPtr);
1581193326Sed  }
1582193326Sed  // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1583193326Sed  // ObjCTypes types.
1584198092Srdivacky  const llvm::Type *ClassTy =
1585193326Sed    CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
1586193326Sed  Target = CGF.Builder.CreateBitCast(Target, ClassTy);
1587198092Srdivacky  CGF.Builder.CreateStore(Target,
1588193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 1));
1589208600Srdivacky  return EmitLegacyMessageSend(CGF, Return, ResultType,
1590193326Sed                               EmitSelector(CGF.Builder, Sel),
1591193326Sed                               ObjCSuper, ObjCTypes.SuperPtrCTy,
1592198092Srdivacky                               true, CallArgs, Method, ObjCTypes);
1593193326Sed}
1594198092Srdivacky
1595198092Srdivacky/// Generate code for a message send expression.
1596193326SedCodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1597208600Srdivacky                                               ReturnValueSlot Return,
1598193326Sed                                               QualType ResultType,
1599193326Sed                                               Selector Sel,
1600193326Sed                                               llvm::Value *Receiver,
1601193326Sed                                               const CallArgList &CallArgs,
1602207619Srdivacky                                               const ObjCInterfaceDecl *Class,
1603193326Sed                                               const ObjCMethodDecl *Method) {
1604208600Srdivacky  return EmitLegacyMessageSend(CGF, Return, ResultType,
1605193326Sed                               EmitSelector(CGF.Builder, Sel),
1606193326Sed                               Receiver, CGF.getContext().getObjCIdType(),
1607198092Srdivacky                               false, CallArgs, Method, ObjCTypes);
1608193326Sed}
1609193326Sed
1610198092SrdivackyCodeGen::RValue
1611198092SrdivackyCGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
1612208600Srdivacky                                       ReturnValueSlot Return,
1613198092Srdivacky                                       QualType ResultType,
1614198092Srdivacky                                       llvm::Value *Sel,
1615198092Srdivacky                                       llvm::Value *Arg0,
1616198092Srdivacky                                       QualType Arg0Ty,
1617198092Srdivacky                                       bool IsSuper,
1618198092Srdivacky                                       const CallArgList &CallArgs,
1619198092Srdivacky                                       const ObjCMethodDecl *Method,
1620198092Srdivacky                                       const ObjCCommonTypesHelper &ObjCTypes) {
1621193326Sed  CallArgList ActualArgs;
1622193326Sed  if (!IsSuper)
1623193326Sed    Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
1624193326Sed  ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
1625193326Sed  ActualArgs.push_back(std::make_pair(RValue::get(Sel),
1626193326Sed                                      CGF.getContext().getObjCSelType()));
1627193326Sed  ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
1628198092Srdivacky
1629193326Sed  CodeGenTypes &Types = CGM.getTypes();
1630203955Srdivacky  const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
1631206084Srdivacky                                                       FunctionType::ExtInfo());
1632198092Srdivacky  const llvm::FunctionType *FTy =
1633198092Srdivacky    Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
1634198092Srdivacky
1635210299Sed  if (Method)
1636210299Sed    assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
1637210299Sed           CGM.getContext().getCanonicalType(ResultType) &&
1638210299Sed           "Result type mismatch!");
1639210299Sed
1640193326Sed  llvm::Constant *Fn = NULL;
1641210299Sed  if (CGM.ReturnTypeUsesSRet(FnInfo)) {
1642193326Sed    Fn = (ObjCABI == 2) ?  ObjCTypes.getSendStretFn2(IsSuper)
1643198092Srdivacky      : ObjCTypes.getSendStretFn(IsSuper);
1644210299Sed  } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1645210299Sed    Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1646210299Sed      : ObjCTypes.getSendFpretFn(IsSuper);
1647193326Sed  } else {
1648193326Sed    Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
1649198092Srdivacky      : ObjCTypes.getSendFn(IsSuper);
1650193326Sed  }
1651210299Sed  Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
1652208600Srdivacky  return CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
1653193326Sed}
1654193326Sed
1655212904Sdimstatic Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1656212904Sdim  if (FQT.isObjCGCStrong())
1657212904Sdim    return Qualifiers::Strong;
1658212904Sdim
1659212904Sdim  if (FQT.isObjCGCWeak())
1660212904Sdim    return Qualifiers::Weak;
1661212904Sdim
1662212904Sdim  if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1663212904Sdim    return Qualifiers::Strong;
1664212904Sdim
1665212904Sdim  if (const PointerType *PT = FQT->getAs<PointerType>())
1666212904Sdim    return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1667212904Sdim
1668212904Sdim  return Qualifiers::GCNone;
1669212904Sdim}
1670212904Sdim
1671218893Sdimllvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1672218893Sdim                                                const CGBlockInfo &blockInfo) {
1673218893Sdim  llvm::Constant *nullPtr =
1674212904Sdim    llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
1675218893Sdim
1676218893Sdim  if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
1677218893Sdim    return nullPtr;
1678218893Sdim
1679212904Sdim  bool hasUnion = false;
1680212904Sdim  SkipIvars.clear();
1681212904Sdim  IvarsInfo.clear();
1682212904Sdim  unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
1683212904Sdim  unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
1684212904Sdim
1685218893Sdim  // __isa is the first field in block descriptor and must assume by runtime's
1686218893Sdim  // convention that it is GC'able.
1687218893Sdim  IvarsInfo.push_back(GC_IVAR(0, 1));
1688218893Sdim
1689218893Sdim  const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1690218893Sdim
1691218893Sdim  // Calculate the basic layout of the block structure.
1692218893Sdim  const llvm::StructLayout *layout =
1693218893Sdim    CGM.getTargetData().getStructLayout(blockInfo.StructureType);
1694218893Sdim
1695218893Sdim  // Ignore the optional 'this' capture: C++ objects are not assumed
1696218893Sdim  // to be GC'ed.
1697218893Sdim
1698218893Sdim  // Walk the captured variables.
1699218893Sdim  for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1700218893Sdim         ce = blockDecl->capture_end(); ci != ce; ++ci) {
1701218893Sdim    const VarDecl *variable = ci->getVariable();
1702218893Sdim    QualType type = variable->getType();
1703218893Sdim
1704218893Sdim    const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1705218893Sdim
1706218893Sdim    // Ignore constant captures.
1707218893Sdim    if (capture.isConstant()) continue;
1708218893Sdim
1709218893Sdim    uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
1710218893Sdim
1711218893Sdim    // __block variables are passed by their descriptor address.
1712218893Sdim    if (ci->isByRef()) {
1713218893Sdim      IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
1714212904Sdim      continue;
1715212904Sdim    }
1716218893Sdim
1717218893Sdim    assert(!type->isArrayType() && "array variable should not be caught");
1718218893Sdim    if (const RecordType *record = type->getAs<RecordType>()) {
1719218893Sdim      BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
1720218893Sdim      continue;
1721218893Sdim    }
1722212904Sdim
1723218893Sdim    Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
1724218893Sdim    unsigned fieldSize = CGM.getContext().getTypeSize(type);
1725218893Sdim
1726218893Sdim    if (GCAttr == Qualifiers::Strong)
1727218893Sdim      IvarsInfo.push_back(GC_IVAR(fieldOffset,
1728218893Sdim                                  fieldSize / WordSizeInBits));
1729212904Sdim    else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
1730218893Sdim      SkipIvars.push_back(GC_IVAR(fieldOffset,
1731218893Sdim                                  fieldSize / ByteSizeInBits));
1732212904Sdim  }
1733212904Sdim
1734212904Sdim  if (IvarsInfo.empty())
1735218893Sdim    return nullPtr;
1736218893Sdim
1737218893Sdim  // Sort on byte position; captures might not be allocated in order,
1738218893Sdim  // and unions can do funny things.
1739218893Sdim  llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
1740218893Sdim  llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
1741212904Sdim
1742212904Sdim  std::string BitMap;
1743212904Sdim  llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
1744212904Sdim  if (CGM.getLangOptions().ObjCGCBitmapPrint) {
1745212904Sdim    printf("\n block variable layout for block: ");
1746212904Sdim    const unsigned char *s = (unsigned char*)BitMap.c_str();
1747212904Sdim    for (unsigned i = 0; i < BitMap.size(); i++)
1748212904Sdim      if (!(s[i] & 0xf0))
1749212904Sdim        printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
1750212904Sdim      else
1751212904Sdim        printf("0x%x%s",  s[i], s[i] != 0 ? ", " : "");
1752212904Sdim    printf("\n");
1753212904Sdim  }
1754212904Sdim
1755212904Sdim  return C;
1756212904Sdim}
1757212904Sdim
1758198092Srdivackyllvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
1759193326Sed                                            const ObjCProtocolDecl *PD) {
1760193326Sed  // FIXME: I don't understand why gcc generates this, or where it is
1761193326Sed  // resolved. Investigate. Its also wasteful to look this up over and over.
1762193326Sed  LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1763193326Sed
1764193326Sed  return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
1765193326Sed                                        ObjCTypes.ExternalProtocolPtrTy);
1766193326Sed}
1767193326Sed
1768193326Sedvoid CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
1769193326Sed  // FIXME: We shouldn't need this, the protocol decl should contain enough
1770193326Sed  // information to tell us whether this was a declaration or a definition.
1771193326Sed  DefinedProtocols.insert(PD->getIdentifier());
1772193326Sed
1773193326Sed  // If we have generated a forward reference to this protocol, emit
1774193326Sed  // it now. Otherwise do nothing, the protocol objects are lazily
1775193326Sed  // emitted.
1776198092Srdivacky  if (Protocols.count(PD->getIdentifier()))
1777193326Sed    GetOrEmitProtocol(PD);
1778193326Sed}
1779193326Sed
1780193326Sedllvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
1781193326Sed  if (DefinedProtocols.count(PD->getIdentifier()))
1782193326Sed    return GetOrEmitProtocol(PD);
1783193326Sed  return GetOrEmitProtocolRef(PD);
1784193326Sed}
1785193326Sed
1786193326Sed/*
1787198092Srdivacky// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1788198092Srdivackystruct _objc_protocol {
1789198092Srdivackystruct _objc_protocol_extension *isa;
1790198092Srdivackychar *protocol_name;
1791198092Srdivackystruct _objc_protocol_list *protocol_list;
1792198092Srdivackystruct _objc__method_prototype_list *instance_methods;
1793198092Srdivackystruct _objc__method_prototype_list *class_methods
1794198092Srdivacky};
1795193326Sed
1796198092SrdivackySee EmitProtocolExtension().
1797193326Sed*/
1798193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1799193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1800193326Sed
1801193326Sed  // Early exit if a defining object has already been generated.
1802193326Sed  if (Entry && Entry->hasInitializer())
1803193326Sed    return Entry;
1804193326Sed
1805193326Sed  // FIXME: I don't understand why gcc generates this, or where it is
1806193326Sed  // resolved. Investigate. Its also wasteful to look this up over and over.
1807193326Sed  LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1808193326Sed
1809193326Sed  // Construct method lists.
1810193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1811193326Sed  std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
1812198092Srdivacky  for (ObjCProtocolDecl::instmeth_iterator
1813195341Sed         i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
1814193326Sed    ObjCMethodDecl *MD = *i;
1815193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
1816193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1817193326Sed      OptInstanceMethods.push_back(C);
1818193326Sed    } else {
1819193326Sed      InstanceMethods.push_back(C);
1820198092Srdivacky    }
1821193326Sed  }
1822193326Sed
1823198092Srdivacky  for (ObjCProtocolDecl::classmeth_iterator
1824195341Sed         i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
1825193326Sed    ObjCMethodDecl *MD = *i;
1826193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
1827193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1828193326Sed      OptClassMethods.push_back(C);
1829193326Sed    } else {
1830193326Sed      ClassMethods.push_back(C);
1831198092Srdivacky    }
1832193326Sed  }
1833193326Sed
1834193326Sed  std::vector<llvm::Constant*> Values(5);
1835193326Sed  Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
1836193326Sed  Values[1] = GetClassName(PD->getIdentifier());
1837198092Srdivacky  Values[2] =
1838198398Srdivacky    EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
1839193326Sed                     PD->protocol_begin(),
1840193326Sed                     PD->protocol_end());
1841198092Srdivacky  Values[3] =
1842198398Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
1843193326Sed                       "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1844193326Sed                       InstanceMethods);
1845198092Srdivacky  Values[4] =
1846198398Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
1847193326Sed                       "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1848193326Sed                       ClassMethods);
1849193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
1850193326Sed                                                   Values);
1851198092Srdivacky
1852193326Sed  if (Entry) {
1853193326Sed    // Already created, fix the linkage and update the initializer.
1854193326Sed    Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
1855193326Sed    Entry->setInitializer(Init);
1856193326Sed  } else {
1857198092Srdivacky    Entry =
1858198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
1859193326Sed                               llvm::GlobalValue::InternalLinkage,
1860198092Srdivacky                               Init,
1861198398Srdivacky                               "\01L_OBJC_PROTOCOL_" + PD->getName());
1862193326Sed    Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
1863193326Sed    // FIXME: Is this necessary? Why only for protocol?
1864193326Sed    Entry->setAlignment(4);
1865193326Sed  }
1866198092Srdivacky  CGM.AddUsedGlobal(Entry);
1867193326Sed
1868193326Sed  return Entry;
1869193326Sed}
1870193326Sed
1871193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
1872193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1873193326Sed
1874193326Sed  if (!Entry) {
1875193326Sed    // We use the initializer as a marker of whether this is a forward
1876193326Sed    // reference or not. At module finalization we add the empty
1877193326Sed    // contents for protocols which were referenced but never defined.
1878198092Srdivacky    Entry =
1879198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
1880193326Sed                               llvm::GlobalValue::ExternalLinkage,
1881193326Sed                               0,
1882198398Srdivacky                               "\01L_OBJC_PROTOCOL_" + PD->getName());
1883193326Sed    Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
1884193326Sed    // FIXME: Is this necessary? Why only for protocol?
1885193326Sed    Entry->setAlignment(4);
1886193326Sed  }
1887198092Srdivacky
1888193326Sed  return Entry;
1889193326Sed}
1890193326Sed
1891193326Sed/*
1892193326Sed  struct _objc_protocol_extension {
1893198092Srdivacky  uint32_t size;
1894198092Srdivacky  struct objc_method_description_list *optional_instance_methods;
1895198092Srdivacky  struct objc_method_description_list *optional_class_methods;
1896198092Srdivacky  struct objc_property_list *instance_properties;
1897193326Sed  };
1898193326Sed*/
1899193326Sedllvm::Constant *
1900193326SedCGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1901193326Sed                                 const ConstantVector &OptInstanceMethods,
1902193326Sed                                 const ConstantVector &OptClassMethods) {
1903198092Srdivacky  uint64_t Size =
1904193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
1905193326Sed  std::vector<llvm::Constant*> Values(4);
1906193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
1907198092Srdivacky  Values[1] =
1908198092Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
1909198398Srdivacky                       + PD->getName(),
1910193326Sed                       "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1911193326Sed                       OptInstanceMethods);
1912198092Srdivacky  Values[2] =
1913198398Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
1914193326Sed                       "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1915193326Sed                       OptClassMethods);
1916198398Srdivacky  Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
1917193326Sed                               0, PD, ObjCTypes);
1918193326Sed
1919193326Sed  // Return null if no extension bits are used.
1920198092Srdivacky  if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
1921193326Sed      Values[3]->isNullValue())
1922193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
1923193326Sed
1924198092Srdivacky  llvm::Constant *Init =
1925193326Sed    llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
1926193326Sed
1927193326Sed  // No special section, but goes in llvm.used
1928198398Srdivacky  return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
1929198092Srdivacky                           Init,
1930193326Sed                           0, 0, true);
1931193326Sed}
1932193326Sed
1933193326Sed/*
1934193326Sed  struct objc_protocol_list {
1935198092Srdivacky  struct objc_protocol_list *next;
1936198092Srdivacky  long count;
1937198092Srdivacky  Protocol *list[];
1938193326Sed  };
1939193326Sed*/
1940193326Sedllvm::Constant *
1941198398SrdivackyCGObjCMac::EmitProtocolList(llvm::Twine Name,
1942193326Sed                            ObjCProtocolDecl::protocol_iterator begin,
1943193326Sed                            ObjCProtocolDecl::protocol_iterator end) {
1944193326Sed  std::vector<llvm::Constant*> ProtocolRefs;
1945193326Sed
1946193326Sed  for (; begin != end; ++begin)
1947193326Sed    ProtocolRefs.push_back(GetProtocolRef(*begin));
1948193326Sed
1949193326Sed  // Just return null for empty protocol lists
1950198092Srdivacky  if (ProtocolRefs.empty())
1951193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1952193326Sed
1953193326Sed  // This list is null terminated.
1954193326Sed  ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
1955193326Sed
1956193326Sed  std::vector<llvm::Constant*> Values(3);
1957193326Sed  // This field is only used by the runtime.
1958193326Sed  Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1959198092Srdivacky  Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
1960198092Srdivacky                                     ProtocolRefs.size() - 1);
1961198092Srdivacky  Values[2] =
1962198092Srdivacky    llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1963198092Srdivacky                                                  ProtocolRefs.size()),
1964193326Sed                             ProtocolRefs);
1965198092Srdivacky
1966198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
1967198092Srdivacky  llvm::GlobalVariable *GV =
1968193326Sed    CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1969193326Sed                      4, false);
1970193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
1971193326Sed}
1972193326Sed
1973200583Srdivackyvoid CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
1974200583Srdivacky                                   std::vector<llvm::Constant*> &Properties,
1975200583Srdivacky                                   const Decl *Container,
1976200583Srdivacky                                   const ObjCProtocolDecl *PROTO,
1977200583Srdivacky                                   const ObjCCommonTypesHelper &ObjCTypes) {
1978200583Srdivacky  std::vector<llvm::Constant*> Prop(2);
1979200583Srdivacky  for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
1980200583Srdivacky         E = PROTO->protocol_end(); P != E; ++P)
1981200583Srdivacky    PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
1982200583Srdivacky  for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
1983200583Srdivacky       E = PROTO->prop_end(); I != E; ++I) {
1984200583Srdivacky    const ObjCPropertyDecl *PD = *I;
1985200583Srdivacky    if (!PropertySet.insert(PD->getIdentifier()))
1986200583Srdivacky      continue;
1987200583Srdivacky    Prop[0] = GetPropertyName(PD->getIdentifier());
1988200583Srdivacky    Prop[1] = GetPropertyTypeString(PD, Container);
1989200583Srdivacky    Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
1990200583Srdivacky  }
1991200583Srdivacky}
1992200583Srdivacky
1993193326Sed/*
1994193326Sed  struct _objc_property {
1995198092Srdivacky  const char * const name;
1996198092Srdivacky  const char * const attributes;
1997193326Sed  };
1998193326Sed
1999193326Sed  struct _objc_property_list {
2000198092Srdivacky  uint32_t entsize; // sizeof (struct _objc_property)
2001198092Srdivacky  uint32_t prop_count;
2002198092Srdivacky  struct _objc_property[prop_count];
2003193326Sed  };
2004193326Sed*/
2005198398Srdivackyllvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
2006198092Srdivacky                                       const Decl *Container,
2007198092Srdivacky                                       const ObjCContainerDecl *OCD,
2008198092Srdivacky                                       const ObjCCommonTypesHelper &ObjCTypes) {
2009193326Sed  std::vector<llvm::Constant*> Properties, Prop(2);
2010200583Srdivacky  llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
2011198092Srdivacky  for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
2012198092Srdivacky         E = OCD->prop_end(); I != E; ++I) {
2013193326Sed    const ObjCPropertyDecl *PD = *I;
2014200583Srdivacky    PropertySet.insert(PD->getIdentifier());
2015193326Sed    Prop[0] = GetPropertyName(PD->getIdentifier());
2016193326Sed    Prop[1] = GetPropertyTypeString(PD, Container);
2017193326Sed    Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
2018193326Sed                                                   Prop));
2019193326Sed  }
2020210299Sed  if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
2021212904Sdim    for (ObjCInterfaceDecl::all_protocol_iterator
2022212904Sdim         P = OID->all_referenced_protocol_begin(),
2023212904Sdim         E = OID->all_referenced_protocol_end(); P != E; ++P)
2024210299Sed      PushProtocolProperties(PropertySet, Properties, Container, (*P),
2025210299Sed                             ObjCTypes);
2026210299Sed  }
2027210299Sed  else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
2028210299Sed    for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
2029210299Sed         E = CD->protocol_end(); P != E; ++P)
2030210299Sed      PushProtocolProperties(PropertySet, Properties, Container, (*P),
2031210299Sed                             ObjCTypes);
2032210299Sed  }
2033193326Sed
2034193326Sed  // Return null for empty list.
2035193326Sed  if (Properties.empty())
2036193326Sed    return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
2037193326Sed
2038198092Srdivacky  unsigned PropertySize =
2039193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
2040193326Sed  std::vector<llvm::Constant*> Values(3);
2041193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
2042193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
2043198092Srdivacky  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
2044193326Sed                                             Properties.size());
2045193326Sed  Values[2] = llvm::ConstantArray::get(AT, Properties);
2046198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
2047193326Sed
2048198092Srdivacky  llvm::GlobalVariable *GV =
2049198092Srdivacky    CreateMetadataVar(Name, Init,
2050198092Srdivacky                      (ObjCABI == 2) ? "__DATA, __objc_const" :
2051193326Sed                      "__OBJC,__property,regular,no_dead_strip",
2052198092Srdivacky                      (ObjCABI == 2) ? 8 : 4,
2053193326Sed                      true);
2054193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
2055193326Sed}
2056193326Sed
2057193326Sed/*
2058193326Sed  struct objc_method_description_list {
2059198092Srdivacky  int count;
2060198092Srdivacky  struct objc_method_description list[];
2061193326Sed  };
2062193326Sed*/
2063193326Sedllvm::Constant *
2064193326SedCGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
2065193326Sed  std::vector<llvm::Constant*> Desc(2);
2066198092Srdivacky  Desc[0] =
2067198092Srdivacky    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
2068198092Srdivacky                                   ObjCTypes.SelectorPtrTy);
2069193326Sed  Desc[1] = GetMethodVarType(MD);
2070193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
2071193326Sed                                   Desc);
2072193326Sed}
2073193326Sed
2074198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
2075193326Sed                                              const char *Section,
2076193326Sed                                              const ConstantVector &Methods) {
2077193326Sed  // Return null for empty list.
2078193326Sed  if (Methods.empty())
2079193326Sed    return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
2080193326Sed
2081193326Sed  std::vector<llvm::Constant*> Values(2);
2082193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
2083198092Srdivacky  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
2084193326Sed                                             Methods.size());
2085193326Sed  Values[1] = llvm::ConstantArray::get(AT, Methods);
2086198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
2087193326Sed
2088193326Sed  llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
2089198092Srdivacky  return llvm::ConstantExpr::getBitCast(GV,
2090193326Sed                                        ObjCTypes.MethodDescriptionListPtrTy);
2091193326Sed}
2092193326Sed
2093193326Sed/*
2094193326Sed  struct _objc_category {
2095198092Srdivacky  char *category_name;
2096198092Srdivacky  char *class_name;
2097198092Srdivacky  struct _objc_method_list *instance_methods;
2098198092Srdivacky  struct _objc_method_list *class_methods;
2099198092Srdivacky  struct _objc_protocol_list *protocols;
2100198092Srdivacky  uint32_t size; // <rdar://4585769>
2101198092Srdivacky  struct _objc_property_list *instance_properties;
2102193326Sed  };
2103198092Srdivacky*/
2104193326Sedvoid CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
2105193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
2106193326Sed
2107193326Sed  // FIXME: This is poor design, the OCD should have a pointer to the category
2108193326Sed  // decl. Additionally, note that Category can be null for the @implementation
2109193326Sed  // w/o an @interface case. Sema should just create one for us as it does for
2110193326Sed  // @implementation so everyone else can live life under a clear blue sky.
2111193326Sed  const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
2112198092Srdivacky  const ObjCCategoryDecl *Category =
2113193326Sed    Interface->FindCategoryDeclaration(OCD->getIdentifier());
2114193326Sed
2115198398Srdivacky  llvm::SmallString<256> ExtName;
2116198398Srdivacky  llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2117198398Srdivacky                                     << OCD->getName();
2118198398Srdivacky
2119193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2120198092Srdivacky  for (ObjCCategoryImplDecl::instmeth_iterator
2121195341Sed         i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
2122193326Sed    // Instance methods should always be defined.
2123193326Sed    InstanceMethods.push_back(GetMethodConstant(*i));
2124193326Sed  }
2125198092Srdivacky  for (ObjCCategoryImplDecl::classmeth_iterator
2126195341Sed         i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
2127193326Sed    // Class methods should always be defined.
2128193326Sed    ClassMethods.push_back(GetMethodConstant(*i));
2129193326Sed  }
2130193326Sed
2131193326Sed  std::vector<llvm::Constant*> Values(7);
2132193326Sed  Values[0] = GetClassName(OCD->getIdentifier());
2133193326Sed  Values[1] = GetClassName(Interface->getIdentifier());
2134193326Sed  LazySymbols.insert(Interface->getIdentifier());
2135198092Srdivacky  Values[2] =
2136198398Srdivacky    EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
2137193326Sed                   "__OBJC,__cat_inst_meth,regular,no_dead_strip",
2138193326Sed                   InstanceMethods);
2139198092Srdivacky  Values[3] =
2140198398Srdivacky    EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
2141193326Sed                   "__OBJC,__cat_cls_meth,regular,no_dead_strip",
2142193326Sed                   ClassMethods);
2143193326Sed  if (Category) {
2144198092Srdivacky    Values[4] =
2145198398Srdivacky      EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
2146193326Sed                       Category->protocol_begin(),
2147193326Sed                       Category->protocol_end());
2148193326Sed  } else {
2149193326Sed    Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
2150193326Sed  }
2151193326Sed  Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
2152193326Sed
2153193326Sed  // If there is no category @interface then there can be no properties.
2154193326Sed  if (Category) {
2155198398Srdivacky    Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
2156193326Sed                                 OCD, Category, ObjCTypes);
2157193326Sed  } else {
2158193326Sed    Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
2159193326Sed  }
2160198092Srdivacky
2161193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
2162193326Sed                                                   Values);
2163193326Sed
2164198092Srdivacky  llvm::GlobalVariable *GV =
2165198398Srdivacky    CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
2166193326Sed                      "__OBJC,__category,regular,no_dead_strip",
2167193326Sed                      4, true);
2168193326Sed  DefinedCategories.push_back(GV);
2169210299Sed  DefinedCategoryNames.insert(ExtName.str());
2170193326Sed}
2171193326Sed
2172193326Sed// FIXME: Get from somewhere?
2173193326Sedenum ClassFlags {
2174193326Sed  eClassFlags_Factory              = 0x00001,
2175193326Sed  eClassFlags_Meta                 = 0x00002,
2176193326Sed  // <rdr://5142207>
2177193326Sed  eClassFlags_HasCXXStructors      = 0x02000,
2178193326Sed  eClassFlags_Hidden               = 0x20000,
2179193326Sed  eClassFlags_ABI2_Hidden          = 0x00010,
2180193326Sed  eClassFlags_ABI2_HasCXXStructors = 0x00004   // <rdr://4923634>
2181193326Sed};
2182193326Sed
2183193326Sed/*
2184193326Sed  struct _objc_class {
2185198092Srdivacky  Class isa;
2186198092Srdivacky  Class super_class;
2187198092Srdivacky  const char *name;
2188198092Srdivacky  long version;
2189198092Srdivacky  long info;
2190198092Srdivacky  long instance_size;
2191198092Srdivacky  struct _objc_ivar_list *ivars;
2192198092Srdivacky  struct _objc_method_list *methods;
2193198092Srdivacky  struct _objc_cache *cache;
2194198092Srdivacky  struct _objc_protocol_list *protocols;
2195198092Srdivacky  // Objective-C 1.0 extensions (<rdr://4585769>)
2196198092Srdivacky  const char *ivar_layout;
2197198092Srdivacky  struct _objc_class_ext *ext;
2198193326Sed  };
2199193326Sed
2200193326Sed  See EmitClassExtension();
2201198092Srdivacky*/
2202193326Sedvoid CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
2203193326Sed  DefinedSymbols.insert(ID->getIdentifier());
2204193326Sed
2205193326Sed  std::string ClassName = ID->getNameAsString();
2206193326Sed  // FIXME: Gross
2207198092Srdivacky  ObjCInterfaceDecl *Interface =
2208193326Sed    const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
2209198092Srdivacky  llvm::Constant *Protocols =
2210198398Srdivacky    EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
2211212904Sdim                     Interface->all_referenced_protocol_begin(),
2212212904Sdim                     Interface->all_referenced_protocol_end());
2213193326Sed  unsigned Flags = eClassFlags_Factory;
2214207619Srdivacky  if (ID->getNumIvarInitializers())
2215207619Srdivacky    Flags |= eClassFlags_HasCXXStructors;
2216198092Srdivacky  unsigned Size =
2217218893Sdim    CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
2218193326Sed
2219193326Sed  // FIXME: Set CXX-structors flag.
2220218893Sdim  if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
2221193326Sed    Flags |= eClassFlags_Hidden;
2222193326Sed
2223193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2224198092Srdivacky  for (ObjCImplementationDecl::instmeth_iterator
2225195341Sed         i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
2226193326Sed    // Instance methods should always be defined.
2227193326Sed    InstanceMethods.push_back(GetMethodConstant(*i));
2228193326Sed  }
2229198092Srdivacky  for (ObjCImplementationDecl::classmeth_iterator
2230195341Sed         i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
2231193326Sed    // Class methods should always be defined.
2232193326Sed    ClassMethods.push_back(GetMethodConstant(*i));
2233193326Sed  }
2234193326Sed
2235198092Srdivacky  for (ObjCImplementationDecl::propimpl_iterator
2236195341Sed         i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
2237193326Sed    ObjCPropertyImplDecl *PID = *i;
2238193326Sed
2239193326Sed    if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2240193326Sed      ObjCPropertyDecl *PD = PID->getPropertyDecl();
2241193326Sed
2242193326Sed      if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
2243193326Sed        if (llvm::Constant *C = GetMethodConstant(MD))
2244193326Sed          InstanceMethods.push_back(C);
2245193326Sed      if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
2246193326Sed        if (llvm::Constant *C = GetMethodConstant(MD))
2247193326Sed          InstanceMethods.push_back(C);
2248193326Sed    }
2249193326Sed  }
2250193326Sed
2251193326Sed  std::vector<llvm::Constant*> Values(12);
2252193326Sed  Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
2253193326Sed  if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
2254193326Sed    // Record a reference to the super class.
2255193326Sed    LazySymbols.insert(Super->getIdentifier());
2256193326Sed
2257198092Srdivacky    Values[ 1] =
2258193326Sed      llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
2259193326Sed                                     ObjCTypes.ClassPtrTy);
2260193326Sed  } else {
2261193326Sed    Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
2262193326Sed  }
2263193326Sed  Values[ 2] = GetClassName(ID->getIdentifier());
2264193326Sed  // Version is always 0.
2265193326Sed  Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2266193326Sed  Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2267193326Sed  Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
2268193326Sed  Values[ 6] = EmitIvarList(ID, false);
2269198092Srdivacky  Values[ 7] =
2270198398Srdivacky    EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
2271193326Sed                   "__OBJC,__inst_meth,regular,no_dead_strip",
2272193326Sed                   InstanceMethods);
2273193326Sed  // cache is always NULL.
2274193326Sed  Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
2275193326Sed  Values[ 9] = Protocols;
2276198092Srdivacky  Values[10] = BuildIvarLayout(ID, true);
2277193326Sed  Values[11] = EmitClassExtension(ID);
2278193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
2279193326Sed                                                   Values);
2280199482Srdivacky  std::string Name("\01L_OBJC_CLASS_");
2281199482Srdivacky  Name += ClassName;
2282199482Srdivacky  const char *Section = "__OBJC,__class,regular,no_dead_strip";
2283199482Srdivacky  // Check for a forward reference.
2284199482Srdivacky  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2285199482Srdivacky  if (GV) {
2286199482Srdivacky    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2287199482Srdivacky           "Forward metaclass reference has incorrect type.");
2288199482Srdivacky    GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2289199482Srdivacky    GV->setInitializer(Init);
2290199482Srdivacky    GV->setSection(Section);
2291199482Srdivacky    GV->setAlignment(4);
2292199482Srdivacky    CGM.AddUsedGlobal(GV);
2293199482Srdivacky  }
2294199482Srdivacky  else
2295199482Srdivacky    GV = CreateMetadataVar(Name, Init, Section, 4, true);
2296193326Sed  DefinedClasses.push_back(GV);
2297193326Sed}
2298193326Sed
2299193326Sedllvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2300193326Sed                                         llvm::Constant *Protocols,
2301193326Sed                                         const ConstantVector &Methods) {
2302193326Sed  unsigned Flags = eClassFlags_Meta;
2303193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
2304193326Sed
2305218893Sdim  if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
2306193326Sed    Flags |= eClassFlags_Hidden;
2307198092Srdivacky
2308193326Sed  std::vector<llvm::Constant*> Values(12);
2309193326Sed  // The isa for the metaclass is the root of the hierarchy.
2310193326Sed  const ObjCInterfaceDecl *Root = ID->getClassInterface();
2311193326Sed  while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2312193326Sed    Root = Super;
2313198092Srdivacky  Values[ 0] =
2314193326Sed    llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
2315193326Sed                                   ObjCTypes.ClassPtrTy);
2316193326Sed  // The super class for the metaclass is emitted as the name of the
2317193326Sed  // super class. The runtime fixes this up to point to the
2318193326Sed  // *metaclass* for the super class.
2319193326Sed  if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
2320198092Srdivacky    Values[ 1] =
2321193326Sed      llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
2322193326Sed                                     ObjCTypes.ClassPtrTy);
2323193326Sed  } else {
2324193326Sed    Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
2325193326Sed  }
2326193326Sed  Values[ 2] = GetClassName(ID->getIdentifier());
2327193326Sed  // Version is always 0.
2328193326Sed  Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2329193326Sed  Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2330193326Sed  Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
2331193326Sed  Values[ 6] = EmitIvarList(ID, true);
2332198092Srdivacky  Values[ 7] =
2333193326Sed    EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
2334193326Sed                   "__OBJC,__cls_meth,regular,no_dead_strip",
2335193326Sed                   Methods);
2336193326Sed  // cache is always NULL.
2337193326Sed  Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
2338193326Sed  Values[ 9] = Protocols;
2339193326Sed  // ivar_layout for metaclass is always NULL.
2340193326Sed  Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
2341193326Sed  // The class extension is always unused for metaclasses.
2342193326Sed  Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
2343193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
2344193326Sed                                                   Values);
2345193326Sed
2346193326Sed  std::string Name("\01L_OBJC_METACLASS_");
2347193326Sed  Name += ID->getNameAsCString();
2348193326Sed
2349193326Sed  // Check for a forward reference.
2350193326Sed  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2351193326Sed  if (GV) {
2352193326Sed    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2353193326Sed           "Forward metaclass reference has incorrect type.");
2354193326Sed    GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2355193326Sed    GV->setInitializer(Init);
2356193326Sed  } else {
2357198092Srdivacky    GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2358193326Sed                                  llvm::GlobalValue::InternalLinkage,
2359198092Srdivacky                                  Init, Name);
2360193326Sed  }
2361193326Sed  GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
2362193326Sed  GV->setAlignment(4);
2363198092Srdivacky  CGM.AddUsedGlobal(GV);
2364193326Sed
2365193326Sed  return GV;
2366193326Sed}
2367193326Sed
2368198092Srdivackyllvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
2369193326Sed  std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
2370193326Sed
2371193326Sed  // FIXME: Should we look these up somewhere other than the module. Its a bit
2372193326Sed  // silly since we only generate these while processing an implementation, so
2373193326Sed  // exactly one pointer would work if know when we entered/exitted an
2374193326Sed  // implementation block.
2375193326Sed
2376193326Sed  // Check for an existing forward reference.
2377193326Sed  // Previously, metaclass with internal linkage may have been defined.
2378193326Sed  // pass 'true' as 2nd argument so it is returned.
2379198092Srdivacky  if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2380198092Srdivacky                                                                   true)) {
2381193326Sed    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2382193326Sed           "Forward metaclass reference has incorrect type.");
2383193326Sed    return GV;
2384193326Sed  } else {
2385193326Sed    // Generate as an external reference to keep a consistent
2386193326Sed    // module. This will be patched up when we emit the metaclass.
2387198092Srdivacky    return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2388193326Sed                                    llvm::GlobalValue::ExternalLinkage,
2389193326Sed                                    0,
2390198092Srdivacky                                    Name);
2391193326Sed  }
2392193326Sed}
2393193326Sed
2394199482Srdivackyllvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2395199482Srdivacky  std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2396199482Srdivacky
2397199482Srdivacky  if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2398199482Srdivacky                                                                   true)) {
2399199482Srdivacky    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2400199482Srdivacky           "Forward class metadata reference has incorrect type.");
2401199482Srdivacky    return GV;
2402199482Srdivacky  } else {
2403199482Srdivacky    return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2404199482Srdivacky                                    llvm::GlobalValue::ExternalLinkage,
2405199482Srdivacky                                    0,
2406199482Srdivacky                                    Name);
2407199482Srdivacky  }
2408199482Srdivacky}
2409199482Srdivacky
2410193326Sed/*
2411193326Sed  struct objc_class_ext {
2412198092Srdivacky  uint32_t size;
2413198092Srdivacky  const char *weak_ivar_layout;
2414198092Srdivacky  struct _objc_property_list *properties;
2415193326Sed  };
2416193326Sed*/
2417193326Sedllvm::Constant *
2418193326SedCGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
2419198092Srdivacky  uint64_t Size =
2420193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
2421193326Sed
2422193326Sed  std::vector<llvm::Constant*> Values(3);
2423193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
2424193326Sed  Values[1] = BuildIvarLayout(ID, false);
2425198398Srdivacky  Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
2426193326Sed                               ID, ID->getClassInterface(), ObjCTypes);
2427193326Sed
2428193326Sed  // Return null if no extension bits are used.
2429193326Sed  if (Values[1]->isNullValue() && Values[2]->isNullValue())
2430193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
2431193326Sed
2432198092Srdivacky  llvm::Constant *Init =
2433193326Sed    llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
2434198398Srdivacky  return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
2435198092Srdivacky                           Init, "__OBJC,__class_ext,regular,no_dead_strip",
2436193326Sed                           4, true);
2437193326Sed}
2438193326Sed
2439193326Sed/*
2440193326Sed  struct objc_ivar {
2441198092Srdivacky  char *ivar_name;
2442198092Srdivacky  char *ivar_type;
2443198092Srdivacky  int ivar_offset;
2444193326Sed  };
2445193326Sed
2446193326Sed  struct objc_ivar_list {
2447198092Srdivacky  int ivar_count;
2448198092Srdivacky  struct objc_ivar list[count];
2449193326Sed  };
2450198092Srdivacky*/
2451193326Sedllvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
2452193326Sed                                        bool ForClass) {
2453193326Sed  std::vector<llvm::Constant*> Ivars, Ivar(3);
2454193326Sed
2455193326Sed  // When emitting the root class GCC emits ivar entries for the
2456193326Sed  // actual class structure. It is not clear if we need to follow this
2457193326Sed  // behavior; for now lets try and get away with not doing it. If so,
2458193326Sed  // the cleanest solution would be to make up an ObjCInterfaceDecl
2459193326Sed  // for the class.
2460193326Sed  if (ForClass)
2461193326Sed    return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
2462198092Srdivacky
2463198092Srdivacky  ObjCInterfaceDecl *OID =
2464193326Sed    const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
2465198092Srdivacky
2466193326Sed  llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
2467193576Sed  CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
2468198092Srdivacky
2469193326Sed  for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2470193326Sed    ObjCIvarDecl *IVD = OIvars[i];
2471193576Sed    // Ignore unnamed bit-fields.
2472193576Sed    if (!IVD->getDeclName())
2473198092Srdivacky      continue;
2474193326Sed    Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2475193326Sed    Ivar[1] = GetMethodVarType(IVD);
2476198092Srdivacky    Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
2477193326Sed                                     ComputeIvarBaseOffset(CGM, OID, IVD));
2478193326Sed    Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
2479193326Sed  }
2480193326Sed
2481193326Sed  // Return null for empty list.
2482193326Sed  if (Ivars.empty())
2483193326Sed    return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
2484193326Sed
2485193326Sed  std::vector<llvm::Constant*> Values(2);
2486193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
2487193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
2488193326Sed                                             Ivars.size());
2489193326Sed  Values[1] = llvm::ConstantArray::get(AT, Ivars);
2490198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
2491193326Sed
2492193326Sed  llvm::GlobalVariable *GV;
2493193326Sed  if (ForClass)
2494198398Srdivacky    GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
2495198092Srdivacky                           Init, "__OBJC,__class_vars,regular,no_dead_strip",
2496193326Sed                           4, true);
2497193326Sed  else
2498198398Srdivacky    GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
2499193326Sed                           Init, "__OBJC,__instance_vars,regular,no_dead_strip",
2500193326Sed                           4, true);
2501193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
2502193326Sed}
2503193326Sed
2504193326Sed/*
2505193326Sed  struct objc_method {
2506198092Srdivacky  SEL method_name;
2507198092Srdivacky  char *method_types;
2508198092Srdivacky  void *method;
2509193326Sed  };
2510198092Srdivacky
2511193326Sed  struct objc_method_list {
2512198092Srdivacky  struct objc_method_list *obsolete;
2513198092Srdivacky  int count;
2514198092Srdivacky  struct objc_method methods_list[count];
2515193326Sed  };
2516193326Sed*/
2517193326Sed
2518193326Sed/// GetMethodConstant - Return a struct objc_method constant for the
2519193326Sed/// given method if it has been defined. The result is null if the
2520193326Sed/// method has not been defined. The return value has type MethodPtrTy.
2521193326Sedllvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
2522212904Sdim  llvm::Function *Fn = GetMethodDefinition(MD);
2523193326Sed  if (!Fn)
2524193326Sed    return 0;
2525198092Srdivacky
2526193326Sed  std::vector<llvm::Constant*> Method(3);
2527198092Srdivacky  Method[0] =
2528193326Sed    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
2529193326Sed                                   ObjCTypes.SelectorPtrTy);
2530193326Sed  Method[1] = GetMethodVarType(MD);
2531193326Sed  Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
2532193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
2533193326Sed}
2534193326Sed
2535198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
2536193326Sed                                          const char *Section,
2537193326Sed                                          const ConstantVector &Methods) {
2538193326Sed  // Return null for empty list.
2539193326Sed  if (Methods.empty())
2540193326Sed    return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
2541193326Sed
2542193326Sed  std::vector<llvm::Constant*> Values(3);
2543193326Sed  Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
2544193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
2545193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
2546193326Sed                                             Methods.size());
2547193326Sed  Values[2] = llvm::ConstantArray::get(AT, Methods);
2548198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
2549193326Sed
2550193326Sed  llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
2551193326Sed  return llvm::ConstantExpr::getBitCast(GV,
2552193326Sed                                        ObjCTypes.MethodListPtrTy);
2553193326Sed}
2554193326Sed
2555193326Sedllvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
2556198092Srdivacky                                                const ObjCContainerDecl *CD) {
2557198398Srdivacky  llvm::SmallString<256> Name;
2558193326Sed  GetNameForMethod(OMD, CD, Name);
2559193326Sed
2560193326Sed  CodeGenTypes &Types = CGM.getTypes();
2561193326Sed  const llvm::FunctionType *MethodTy =
2562193326Sed    Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
2563198092Srdivacky  llvm::Function *Method =
2564193326Sed    llvm::Function::Create(MethodTy,
2565193326Sed                           llvm::GlobalValue::InternalLinkage,
2566198398Srdivacky                           Name.str(),
2567193326Sed                           &CGM.getModule());
2568193326Sed  MethodDefinitions.insert(std::make_pair(OMD, Method));
2569193326Sed
2570193326Sed  return Method;
2571193326Sed}
2572193326Sed
2573193326Sedllvm::GlobalVariable *
2574198398SrdivackyCGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
2575193326Sed                                   llvm::Constant *Init,
2576193326Sed                                   const char *Section,
2577193326Sed                                   unsigned Align,
2578193326Sed                                   bool AddToUsed) {
2579193326Sed  const llvm::Type *Ty = Init->getType();
2580198092Srdivacky  llvm::GlobalVariable *GV =
2581198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Ty, false,
2582198092Srdivacky                             llvm::GlobalValue::InternalLinkage, Init, Name);
2583193326Sed  if (Section)
2584193326Sed    GV->setSection(Section);
2585193326Sed  if (Align)
2586193326Sed    GV->setAlignment(Align);
2587193326Sed  if (AddToUsed)
2588198092Srdivacky    CGM.AddUsedGlobal(GV);
2589193326Sed  return GV;
2590193326Sed}
2591193326Sed
2592198092Srdivackyllvm::Function *CGObjCMac::ModuleInitFunction() {
2593193326Sed  // Abuse this interface function as a place to finalize.
2594193326Sed  FinishModule();
2595193326Sed  return NULL;
2596193326Sed}
2597193326Sed
2598193326Sedllvm::Constant *CGObjCMac::GetPropertyGetFunction() {
2599193326Sed  return ObjCTypes.getGetPropertyFn();
2600193326Sed}
2601193326Sed
2602193326Sedllvm::Constant *CGObjCMac::GetPropertySetFunction() {
2603193326Sed  return ObjCTypes.getSetPropertyFn();
2604193326Sed}
2605193326Sed
2606218893Sdimllvm::Constant *CGObjCMac::GetGetStructFunction() {
2607207619Srdivacky  return ObjCTypes.getCopyStructFn();
2608207619Srdivacky}
2609218893Sdimllvm::Constant *CGObjCMac::GetSetStructFunction() {
2610218893Sdim  return ObjCTypes.getCopyStructFn();
2611218893Sdim}
2612207619Srdivacky
2613193326Sedllvm::Constant *CGObjCMac::EnumerationMutationFunction() {
2614193326Sed  return ObjCTypes.getEnumerationMutationFn();
2615193326Sed}
2616193326Sed
2617210299Sedvoid CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
2618210299Sed  return EmitTryOrSynchronizedStmt(CGF, S);
2619210299Sed}
2620210299Sed
2621210299Sedvoid CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
2622210299Sed                                     const ObjCAtSynchronizedStmt &S) {
2623210299Sed  return EmitTryOrSynchronizedStmt(CGF, S);
2624210299Sed}
2625210299Sed
2626212904Sdimnamespace {
2627212904Sdim  struct PerformFragileFinally : EHScopeStack::Cleanup {
2628212904Sdim    const Stmt &S;
2629212904Sdim    llvm::Value *SyncArgSlot;
2630212904Sdim    llvm::Value *CallTryExitVar;
2631212904Sdim    llvm::Value *ExceptionData;
2632212904Sdim    ObjCTypesHelper &ObjCTypes;
2633212904Sdim    PerformFragileFinally(const Stmt *S,
2634212904Sdim                          llvm::Value *SyncArgSlot,
2635212904Sdim                          llvm::Value *CallTryExitVar,
2636212904Sdim                          llvm::Value *ExceptionData,
2637212904Sdim                          ObjCTypesHelper *ObjCTypes)
2638212904Sdim      : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
2639212904Sdim        ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
2640212904Sdim
2641212904Sdim    void Emit(CodeGenFunction &CGF, bool IsForEH) {
2642212904Sdim      // Check whether we need to call objc_exception_try_exit.
2643212904Sdim      // In optimized code, this branch will always be folded.
2644212904Sdim      llvm::BasicBlock *FinallyCallExit =
2645212904Sdim        CGF.createBasicBlock("finally.call_exit");
2646212904Sdim      llvm::BasicBlock *FinallyNoCallExit =
2647212904Sdim        CGF.createBasicBlock("finally.no_call_exit");
2648212904Sdim      CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
2649212904Sdim                               FinallyCallExit, FinallyNoCallExit);
2650212904Sdim
2651212904Sdim      CGF.EmitBlock(FinallyCallExit);
2652212904Sdim      CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
2653212904Sdim        ->setDoesNotThrow();
2654212904Sdim
2655212904Sdim      CGF.EmitBlock(FinallyNoCallExit);
2656212904Sdim
2657212904Sdim      if (isa<ObjCAtTryStmt>(S)) {
2658212904Sdim        if (const ObjCAtFinallyStmt* FinallyStmt =
2659212904Sdim              cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
2660212904Sdim          // Save the current cleanup destination in case there's
2661212904Sdim          // control flow inside the finally statement.
2662212904Sdim          llvm::Value *CurCleanupDest =
2663212904Sdim            CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
2664212904Sdim
2665212904Sdim          CGF.EmitStmt(FinallyStmt->getFinallyBody());
2666212904Sdim
2667212904Sdim          if (CGF.HaveInsertPoint()) {
2668212904Sdim            CGF.Builder.CreateStore(CurCleanupDest,
2669212904Sdim                                    CGF.getNormalCleanupDestSlot());
2670212904Sdim          } else {
2671212904Sdim            // Currently, the end of the cleanup must always exist.
2672212904Sdim            CGF.EnsureInsertPoint();
2673212904Sdim          }
2674212904Sdim        }
2675212904Sdim      } else {
2676212904Sdim        // Emit objc_sync_exit(expr); as finally's sole statement for
2677212904Sdim        // @synchronized.
2678212904Sdim        llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
2679212904Sdim        CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
2680212904Sdim          ->setDoesNotThrow();
2681212904Sdim      }
2682212904Sdim    }
2683212904Sdim  };
2684212904Sdim
2685212904Sdim  class FragileHazards {
2686212904Sdim    CodeGenFunction &CGF;
2687212904Sdim    llvm::SmallVector<llvm::Value*, 20> Locals;
2688212904Sdim    llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
2689212904Sdim
2690212904Sdim    llvm::InlineAsm *ReadHazard;
2691212904Sdim    llvm::InlineAsm *WriteHazard;
2692212904Sdim
2693212904Sdim    llvm::FunctionType *GetAsmFnType();
2694212904Sdim
2695212904Sdim    void collectLocals();
2696212904Sdim    void emitReadHazard(CGBuilderTy &Builder);
2697212904Sdim
2698212904Sdim  public:
2699212904Sdim    FragileHazards(CodeGenFunction &CGF);
2700212904Sdim
2701212904Sdim    void emitWriteHazard();
2702212904Sdim    void emitHazardsInNewBlocks();
2703212904Sdim  };
2704212904Sdim}
2705212904Sdim
2706212904Sdim/// Create the fragile-ABI read and write hazards based on the current
2707212904Sdim/// state of the function, which is presumed to be immediately prior
2708212904Sdim/// to a @try block.  These hazards are used to maintain correct
2709212904Sdim/// semantics in the face of optimization and the fragile ABI's
2710212904Sdim/// cavalier use of setjmp/longjmp.
2711212904SdimFragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
2712212904Sdim  collectLocals();
2713212904Sdim
2714212904Sdim  if (Locals.empty()) return;
2715212904Sdim
2716212904Sdim  // Collect all the blocks in the function.
2717212904Sdim  for (llvm::Function::iterator
2718212904Sdim         I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
2719212904Sdim    BlocksBeforeTry.insert(&*I);
2720212904Sdim
2721212904Sdim  llvm::FunctionType *AsmFnTy = GetAsmFnType();
2722212904Sdim
2723212904Sdim  // Create a read hazard for the allocas.  This inhibits dead-store
2724212904Sdim  // optimizations and forces the values to memory.  This hazard is
2725212904Sdim  // inserted before any 'throwing' calls in the protected scope to
2726212904Sdim  // reflect the possibility that the variables might be read from the
2727212904Sdim  // catch block if the call throws.
2728212904Sdim  {
2729212904Sdim    std::string Constraint;
2730212904Sdim    for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2731212904Sdim      if (I) Constraint += ',';
2732212904Sdim      Constraint += "*m";
2733212904Sdim    }
2734212904Sdim
2735212904Sdim    ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2736212904Sdim  }
2737212904Sdim
2738212904Sdim  // Create a write hazard for the allocas.  This inhibits folding
2739212904Sdim  // loads across the hazard.  This hazard is inserted at the
2740212904Sdim  // beginning of the catch path to reflect the possibility that the
2741212904Sdim  // variables might have been written within the protected scope.
2742212904Sdim  {
2743212904Sdim    std::string Constraint;
2744212904Sdim    for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2745212904Sdim      if (I) Constraint += ',';
2746212904Sdim      Constraint += "=*m";
2747212904Sdim    }
2748212904Sdim
2749212904Sdim    WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2750212904Sdim  }
2751212904Sdim}
2752212904Sdim
2753212904Sdim/// Emit a write hazard at the current location.
2754212904Sdimvoid FragileHazards::emitWriteHazard() {
2755212904Sdim  if (Locals.empty()) return;
2756212904Sdim
2757212904Sdim  CGF.Builder.CreateCall(WriteHazard, Locals.begin(), Locals.end())
2758212904Sdim    ->setDoesNotThrow();
2759212904Sdim}
2760212904Sdim
2761212904Sdimvoid FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
2762212904Sdim  assert(!Locals.empty());
2763212904Sdim  Builder.CreateCall(ReadHazard, Locals.begin(), Locals.end())
2764212904Sdim    ->setDoesNotThrow();
2765212904Sdim}
2766212904Sdim
2767212904Sdim/// Emit read hazards in all the protected blocks, i.e. all the blocks
2768212904Sdim/// which have been inserted since the beginning of the try.
2769212904Sdimvoid FragileHazards::emitHazardsInNewBlocks() {
2770212904Sdim  if (Locals.empty()) return;
2771212904Sdim
2772212904Sdim  CGBuilderTy Builder(CGF.getLLVMContext());
2773212904Sdim
2774212904Sdim  // Iterate through all blocks, skipping those prior to the try.
2775212904Sdim  for (llvm::Function::iterator
2776212904Sdim         FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
2777212904Sdim    llvm::BasicBlock &BB = *FI;
2778212904Sdim    if (BlocksBeforeTry.count(&BB)) continue;
2779212904Sdim
2780212904Sdim    // Walk through all the calls in the block.
2781212904Sdim    for (llvm::BasicBlock::iterator
2782212904Sdim           BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
2783212904Sdim      llvm::Instruction &I = *BI;
2784212904Sdim
2785212904Sdim      // Ignore instructions that aren't non-intrinsic calls.
2786212904Sdim      // These are the only calls that can possibly call longjmp.
2787212904Sdim      if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
2788212904Sdim      if (isa<llvm::IntrinsicInst>(I))
2789212904Sdim        continue;
2790212904Sdim
2791212904Sdim      // Ignore call sites marked nounwind.  This may be questionable,
2792212904Sdim      // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
2793212904Sdim      llvm::CallSite CS(&I);
2794212904Sdim      if (CS.doesNotThrow()) continue;
2795212904Sdim
2796212904Sdim      // Insert a read hazard before the call.  This will ensure that
2797212904Sdim      // any writes to the locals are performed before making the
2798212904Sdim      // call.  If the call throws, then this is sufficient to
2799212904Sdim      // guarantee correctness as long as it doesn't also write to any
2800212904Sdim      // locals.
2801212904Sdim      Builder.SetInsertPoint(&BB, BI);
2802212904Sdim      emitReadHazard(Builder);
2803212904Sdim    }
2804212904Sdim  }
2805212904Sdim}
2806212904Sdim
2807212904Sdimstatic void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
2808212904Sdim  if (V) S.insert(V);
2809212904Sdim}
2810212904Sdim
2811212904Sdimvoid FragileHazards::collectLocals() {
2812212904Sdim  // Compute a set of allocas to ignore.
2813212904Sdim  llvm::DenseSet<llvm::Value*> AllocasToIgnore;
2814212904Sdim  addIfPresent(AllocasToIgnore, CGF.ReturnValue);
2815212904Sdim  addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
2816212904Sdim  addIfPresent(AllocasToIgnore, CGF.EHCleanupDest);
2817212904Sdim
2818212904Sdim  // Collect all the allocas currently in the function.  This is
2819212904Sdim  // probably way too aggressive.
2820212904Sdim  llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
2821212904Sdim  for (llvm::BasicBlock::iterator
2822212904Sdim         I = Entry.begin(), E = Entry.end(); I != E; ++I)
2823212904Sdim    if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
2824212904Sdim      Locals.push_back(&*I);
2825212904Sdim}
2826212904Sdim
2827212904Sdimllvm::FunctionType *FragileHazards::GetAsmFnType() {
2828212904Sdim  std::vector<const llvm::Type *> Tys(Locals.size());
2829212904Sdim  for (unsigned I = 0, E = Locals.size(); I != E; ++I)
2830212904Sdim    Tys[I] = Locals[I]->getType();
2831212904Sdim  return llvm::FunctionType::get(CGF.Builder.getVoidTy(), Tys, false);
2832212904Sdim}
2833212904Sdim
2834198092Srdivacky/*
2835193326Sed
2836198092Srdivacky  Objective-C setjmp-longjmp (sjlj) Exception Handling
2837198092Srdivacky  --
2838193326Sed
2839210299Sed  A catch buffer is a setjmp buffer plus:
2840210299Sed    - a pointer to the exception that was caught
2841210299Sed    - a pointer to the previous exception data buffer
2842210299Sed    - two pointers of reserved storage
2843210299Sed  Therefore catch buffers form a stack, with a pointer to the top
2844210299Sed  of the stack kept in thread-local storage.
2845210299Sed
2846210299Sed  objc_exception_try_enter pushes a catch buffer onto the EH stack.
2847210299Sed  objc_exception_try_exit pops the given catch buffer, which is
2848210299Sed    required to be the top of the EH stack.
2849210299Sed  objc_exception_throw pops the top of the EH stack, writes the
2850210299Sed    thrown exception into the appropriate field, and longjmps
2851210299Sed    to the setjmp buffer.  It crashes the process (with a printf
2852210299Sed    and an abort()) if there are no catch buffers on the stack.
2853210299Sed  objc_exception_extract just reads the exception pointer out of the
2854210299Sed    catch buffer.
2855210299Sed
2856210299Sed  There's no reason an implementation couldn't use a light-weight
2857210299Sed  setjmp here --- something like __builtin_setjmp, but API-compatible
2858210299Sed  with the heavyweight setjmp.  This will be more important if we ever
2859210299Sed  want to implement correct ObjC/C++ exception interactions for the
2860210299Sed  fragile ABI.
2861210299Sed
2862210299Sed  Note that for this use of setjmp/longjmp to be correct, we may need
2863210299Sed  to mark some local variables volatile: if a non-volatile local
2864210299Sed  variable is modified between the setjmp and the longjmp, it has
2865210299Sed  indeterminate value.  For the purposes of LLVM IR, it may be
2866210299Sed  sufficient to make loads and stores within the @try (to variables
2867210299Sed  declared outside the @try) volatile.  This is necessary for
2868210299Sed  optimized correctness, but is not currently being done; this is
2869210299Sed  being tracked as rdar://problem/8160285
2870210299Sed
2871198092Srdivacky  The basic framework for a @try-catch-finally is as follows:
2872198092Srdivacky  {
2873193326Sed  objc_exception_data d;
2874193326Sed  id _rethrow = null;
2875193326Sed  bool _call_try_exit = true;
2876198092Srdivacky
2877193326Sed  objc_exception_try_enter(&d);
2878193326Sed  if (!setjmp(d.jmp_buf)) {
2879198092Srdivacky  ... try body ...
2880193326Sed  } else {
2881198092Srdivacky  // exception path
2882198092Srdivacky  id _caught = objc_exception_extract(&d);
2883198092Srdivacky
2884198092Srdivacky  // enter new try scope for handlers
2885198092Srdivacky  if (!setjmp(d.jmp_buf)) {
2886198092Srdivacky  ... match exception and execute catch blocks ...
2887198092Srdivacky
2888198092Srdivacky  // fell off end, rethrow.
2889198092Srdivacky  _rethrow = _caught;
2890198092Srdivacky  ... jump-through-finally to finally_rethrow ...
2891198092Srdivacky  } else {
2892198092Srdivacky  // exception in catch block
2893198092Srdivacky  _rethrow = objc_exception_extract(&d);
2894198092Srdivacky  _call_try_exit = false;
2895198092Srdivacky  ... jump-through-finally to finally_rethrow ...
2896193326Sed  }
2897198092Srdivacky  }
2898193326Sed  ... jump-through-finally to finally_end ...
2899193326Sed
2900198092Srdivacky  finally:
2901193326Sed  if (_call_try_exit)
2902198092Srdivacky  objc_exception_try_exit(&d);
2903193326Sed
2904193326Sed  ... finally block ....
2905193326Sed  ... dispatch to finally destination ...
2906193326Sed
2907198092Srdivacky  finally_rethrow:
2908193326Sed  objc_exception_throw(_rethrow);
2909193326Sed
2910198092Srdivacky  finally_end:
2911198092Srdivacky  }
2912193326Sed
2913198092Srdivacky  This framework differs slightly from the one gcc uses, in that gcc
2914198092Srdivacky  uses _rethrow to determine if objc_exception_try_exit should be called
2915198092Srdivacky  and if the object should be rethrown. This breaks in the face of
2916198092Srdivacky  throwing nil and introduces unnecessary branches.
2917193326Sed
2918198092Srdivacky  We specialize this framework for a few particular circumstances:
2919193326Sed
2920198092Srdivacky  - If there are no catch blocks, then we avoid emitting the second
2921198092Srdivacky  exception handling context.
2922193326Sed
2923198092Srdivacky  - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
2924198092Srdivacky  e)) we avoid emitting the code to rethrow an uncaught exception.
2925193326Sed
2926198092Srdivacky  - FIXME: If there is no @finally block we can do a few more
2927198092Srdivacky  simplifications.
2928193326Sed
2929198092Srdivacky  Rethrows and Jumps-Through-Finally
2930198092Srdivacky  --
2931193326Sed
2932210299Sed  '@throw;' is supported by pushing the currently-caught exception
2933210299Sed  onto ObjCEHStack while the @catch blocks are emitted.
2934193326Sed
2935210299Sed  Branches through the @finally block are handled with an ordinary
2936210299Sed  normal cleanup.  We do not register an EH cleanup; fragile-ABI ObjC
2937210299Sed  exceptions are not compatible with C++ exceptions, and this is
2938210299Sed  hardly the only place where this will go wrong.
2939193326Sed
2940210299Sed  @synchronized(expr) { stmt; } is emitted as if it were:
2941210299Sed    id synch_value = expr;
2942210299Sed    objc_sync_enter(synch_value);
2943210299Sed    @try { stmt; } @finally { objc_sync_exit(synch_value); }
2944193326Sed*/
2945193326Sed
2946193326Sedvoid CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2947193326Sed                                          const Stmt &S) {
2948193326Sed  bool isTry = isa<ObjCAtTryStmt>(S);
2949198092Srdivacky
2950210299Sed  // A destination for the fall-through edges of the catch handlers to
2951210299Sed  // jump to.
2952210299Sed  CodeGenFunction::JumpDest FinallyEnd =
2953210299Sed    CGF.getJumpDestInCurrentScope("finally.end");
2954210299Sed
2955210299Sed  // A destination for the rethrow edge of the catch handlers to jump
2956210299Sed  // to.
2957210299Sed  CodeGenFunction::JumpDest FinallyRethrow =
2958210299Sed    CGF.getJumpDestInCurrentScope("finally.rethrow");
2959210299Sed
2960193326Sed  // For @synchronized, call objc_sync_enter(sync.expr). The
2961193326Sed  // evaluation of the expression must occur before we enter the
2962212904Sdim  // @synchronized.  We can't avoid a temp here because we need the
2963212904Sdim  // value to be preserved.  If the backend ever does liveness
2964212904Sdim  // correctly after setjmp, this will be unnecessary.
2965212904Sdim  llvm::Value *SyncArgSlot = 0;
2966193326Sed  if (!isTry) {
2967212904Sdim    llvm::Value *SyncArg =
2968193326Sed      CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2969193326Sed    SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
2970210299Sed    CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
2971210299Sed      ->setDoesNotThrow();
2972212904Sdim
2973212904Sdim    SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
2974212904Sdim    CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
2975193326Sed  }
2976193326Sed
2977212904Sdim  // Allocate memory for the setjmp buffer.  This needs to be kept
2978212904Sdim  // live throughout the try and catch blocks.
2979193326Sed  llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2980193326Sed                                                    "exceptiondata.ptr");
2981210299Sed
2982212904Sdim  // Create the fragile hazards.  Note that this will not capture any
2983212904Sdim  // of the allocas required for exception processing, but will
2984212904Sdim  // capture the current basic block (which extends all the way to the
2985212904Sdim  // setjmp call) as "before the @try".
2986212904Sdim  FragileHazards Hazards(CGF);
2987212904Sdim
2988210299Sed  // Create a flag indicating whether the cleanup needs to call
2989210299Sed  // objc_exception_try_exit.  This is true except when
2990210299Sed  //   - no catches match and we're branching through the cleanup
2991210299Sed  //     just to rethrow the exception, or
2992210299Sed  //   - a catch matched and we're falling out of the catch handler.
2993212904Sdim  // The setjmp-safety rule here is that we should always store to this
2994212904Sdim  // variable in a place that dominates the branch through the cleanup
2995212904Sdim  // without passing through any setjmps.
2996210299Sed  llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
2997193326Sed                                                     "_call_try_exit");
2998198092Srdivacky
2999218893Sdim  // A slot containing the exception to rethrow.  Only needed when we
3000218893Sdim  // have both a @catch and a @finally.
3001218893Sdim  llvm::Value *PropagatingExnVar = 0;
3002218893Sdim
3003210299Sed  // Push a normal cleanup to leave the try scope.
3004212904Sdim  CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
3005212904Sdim                                                 SyncArgSlot,
3006212904Sdim                                                 CallTryExitVar,
3007212904Sdim                                                 ExceptionData,
3008212904Sdim                                                 &ObjCTypes);
3009193326Sed
3010210299Sed  // Enter a try block:
3011210299Sed  //  - Call objc_exception_try_enter to push ExceptionData on top of
3012210299Sed  //    the EH stack.
3013210299Sed  CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3014210299Sed      ->setDoesNotThrow();
3015210299Sed
3016210299Sed  //  - Call setjmp on the exception data buffer.
3017210299Sed  llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
3018210299Sed  llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
3019210299Sed  llvm::Value *SetJmpBuffer =
3020210299Sed    CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, GEPIndexes+3, "setjmp_buffer");
3021210299Sed  llvm::CallInst *SetJmpResult =
3022210299Sed    CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
3023210299Sed  SetJmpResult->setDoesNotThrow();
3024210299Sed
3025210299Sed  // If setjmp returned 0, enter the protected block; otherwise,
3026210299Sed  // branch to the handler.
3027193326Sed  llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3028193326Sed  llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
3029210299Sed  llvm::Value *DidCatch =
3030212904Sdim    CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3031212904Sdim  CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
3032193326Sed
3033210299Sed  // Emit the protected block.
3034193326Sed  CGF.EmitBlock(TryBlock);
3035212904Sdim  CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
3036198092Srdivacky  CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
3037210299Sed                     : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
3038198092Srdivacky
3039212904Sdim  CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
3040212904Sdim
3041210299Sed  // Emit the exception handler block.
3042193326Sed  CGF.EmitBlock(TryHandler);
3043193326Sed
3044212904Sdim  // Don't optimize loads of the in-scope locals across this point.
3045212904Sdim  Hazards.emitWriteHazard();
3046210299Sed
3047210299Sed  // For a @synchronized (or a @try with no catches), just branch
3048210299Sed  // through the cleanup to the rethrow block.
3049210299Sed  if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
3050210299Sed    // Tell the cleanup not to re-pop the exit.
3051212904Sdim    CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
3052193326Sed    CGF.EmitBranchThroughCleanup(FinallyRethrow);
3053210299Sed
3054210299Sed  // Otherwise, we have to match against the caught exceptions.
3055210299Sed  } else {
3056212904Sdim    // Retrieve the exception object.  We may emit multiple blocks but
3057212904Sdim    // nothing can cross this so the value is already in SSA form.
3058212904Sdim    llvm::CallInst *Caught =
3059212904Sdim      CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3060212904Sdim                             ExceptionData, "caught");
3061212904Sdim    Caught->setDoesNotThrow();
3062212904Sdim
3063210299Sed    // Push the exception to rethrow onto the EH value stack for the
3064210299Sed    // benefit of any @throws in the handlers.
3065210299Sed    CGF.ObjCEHValueStack.push_back(Caught);
3066210299Sed
3067207619Srdivacky    const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
3068198092Srdivacky
3069212904Sdim    bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
3070193326Sed
3071212904Sdim    llvm::BasicBlock *CatchBlock = 0;
3072212904Sdim    llvm::BasicBlock *CatchHandler = 0;
3073212904Sdim    if (HasFinally) {
3074218893Sdim      // Save the currently-propagating exception before
3075218893Sdim      // objc_exception_try_enter clears the exception slot.
3076218893Sdim      PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
3077218893Sdim                                               "propagating_exception");
3078218893Sdim      CGF.Builder.CreateStore(Caught, PropagatingExnVar);
3079218893Sdim
3080212904Sdim      // Enter a new exception try block (in case a @catch block
3081212904Sdim      // throws an exception).
3082212904Sdim      CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3083212904Sdim        ->setDoesNotThrow();
3084210299Sed
3085212904Sdim      llvm::CallInst *SetJmpResult =
3086212904Sdim        CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3087212904Sdim                               "setjmp.result");
3088212904Sdim      SetJmpResult->setDoesNotThrow();
3089198092Srdivacky
3090212904Sdim      llvm::Value *Threw =
3091212904Sdim        CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3092198092Srdivacky
3093212904Sdim      CatchBlock = CGF.createBasicBlock("catch");
3094212904Sdim      CatchHandler = CGF.createBasicBlock("catch_for_catch");
3095212904Sdim      CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3096212904Sdim
3097212904Sdim      CGF.EmitBlock(CatchBlock);
3098212904Sdim    }
3099212904Sdim
3100212904Sdim    CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
3101212904Sdim
3102193326Sed    // Handle catch list. As a special case we check if everything is
3103193326Sed    // matched and avoid generating code for falling off the end if
3104193326Sed    // so.
3105193326Sed    bool AllMatched = false;
3106207619Srdivacky    for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3107207619Srdivacky      const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
3108193326Sed
3109207619Srdivacky      const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
3110198092Srdivacky      const ObjCObjectPointerType *OPT = 0;
3111193326Sed
3112193326Sed      // catch(...) always matches.
3113193326Sed      if (!CatchParam) {
3114193326Sed        AllMatched = true;
3115193326Sed      } else {
3116198092Srdivacky        OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
3117198092Srdivacky
3118210299Sed        // catch(id e) always matches under this ABI, since only
3119210299Sed        // ObjC exceptions end up here in the first place.
3120193326Sed        // FIXME: For the time being we also match id<X>; this should
3121193326Sed        // be rejected by Sema instead.
3122198092Srdivacky        if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
3123193326Sed          AllMatched = true;
3124193326Sed      }
3125198092Srdivacky
3126210299Sed      // If this is a catch-all, we don't need to test anything.
3127198092Srdivacky      if (AllMatched) {
3128210299Sed        CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3129210299Sed
3130193326Sed        if (CatchParam) {
3131218893Sdim          CGF.EmitAutoVarDecl(*CatchParam);
3132193326Sed          assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
3133210299Sed
3134210299Sed          // These types work out because ConvertType(id) == i8*.
3135193326Sed          CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
3136193326Sed        }
3137198092Srdivacky
3138193326Sed        CGF.EmitStmt(CatchStmt->getCatchBody());
3139210299Sed
3140210299Sed        // The scope of the catch variable ends right here.
3141210299Sed        CatchVarCleanups.ForceCleanup();
3142210299Sed
3143193326Sed        CGF.EmitBranchThroughCleanup(FinallyEnd);
3144193326Sed        break;
3145193326Sed      }
3146198092Srdivacky
3147198092Srdivacky      assert(OPT && "Unexpected non-object pointer type in @catch");
3148208600Srdivacky      const ObjCObjectType *ObjTy = OPT->getObjectType();
3149210299Sed
3150210299Sed      // FIXME: @catch (Class c) ?
3151208600Srdivacky      ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3152208600Srdivacky      assert(IDecl && "Catch parameter must have Objective-C type!");
3153193326Sed
3154193326Sed      // Check if the @catch block matches the exception object.
3155208600Srdivacky      llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
3156198092Srdivacky
3157210299Sed      llvm::CallInst *Match =
3158193326Sed        CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3159193326Sed                                Class, Caught, "match");
3160210299Sed      Match->setDoesNotThrow();
3161198092Srdivacky
3162210299Sed      llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3163210299Sed      llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
3164198092Srdivacky
3165198092Srdivacky      CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
3166193326Sed                               MatchedBlock, NextCatchBlock);
3167198092Srdivacky
3168193326Sed      // Emit the @catch block.
3169193326Sed      CGF.EmitBlock(MatchedBlock);
3170210299Sed
3171210299Sed      // Collect any cleanups for the catch variable.  The scope lasts until
3172210299Sed      // the end of the catch body.
3173212904Sdim      CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3174210299Sed
3175218893Sdim      CGF.EmitAutoVarDecl(*CatchParam);
3176193326Sed      assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
3177193326Sed
3178210299Sed      // Initialize the catch variable.
3179198092Srdivacky      llvm::Value *Tmp =
3180198092Srdivacky        CGF.Builder.CreateBitCast(Caught,
3181198092Srdivacky                                  CGF.ConvertType(CatchParam->getType()),
3182193326Sed                                  "tmp");
3183193326Sed      CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
3184198092Srdivacky
3185193326Sed      CGF.EmitStmt(CatchStmt->getCatchBody());
3186210299Sed
3187210299Sed      // We're done with the catch variable.
3188210299Sed      CatchVarCleanups.ForceCleanup();
3189210299Sed
3190193326Sed      CGF.EmitBranchThroughCleanup(FinallyEnd);
3191198092Srdivacky
3192193326Sed      CGF.EmitBlock(NextCatchBlock);
3193193326Sed    }
3194193326Sed
3195210299Sed    CGF.ObjCEHValueStack.pop_back();
3196210299Sed
3197212904Sdim    // If nothing wanted anything to do with the caught exception,
3198212904Sdim    // kill the extract call.
3199212904Sdim    if (Caught->use_empty())
3200212904Sdim      Caught->eraseFromParent();
3201212904Sdim
3202212904Sdim    if (!AllMatched)
3203193326Sed      CGF.EmitBranchThroughCleanup(FinallyRethrow);
3204198092Srdivacky
3205212904Sdim    if (HasFinally) {
3206212904Sdim      // Emit the exception handler for the @catch blocks.
3207212904Sdim      CGF.EmitBlock(CatchHandler);
3208210299Sed
3209212904Sdim      // In theory we might now need a write hazard, but actually it's
3210212904Sdim      // unnecessary because there's no local-accessing code between
3211212904Sdim      // the try's write hazard and here.
3212212904Sdim      //Hazards.emitWriteHazard();
3213210299Sed
3214218893Sdim      // Extract the new exception and save it to the
3215218893Sdim      // propagating-exception slot.
3216218893Sdim      assert(PropagatingExnVar);
3217218893Sdim      llvm::CallInst *NewCaught =
3218218893Sdim        CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3219218893Sdim                               ExceptionData, "caught");
3220218893Sdim      NewCaught->setDoesNotThrow();
3221218893Sdim      CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
3222218893Sdim
3223212904Sdim      // Don't pop the catch handler; the throw already did.
3224212904Sdim      CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
3225212904Sdim      CGF.EmitBranchThroughCleanup(FinallyRethrow);
3226212904Sdim    }
3227193326Sed  }
3228198092Srdivacky
3229212904Sdim  // Insert read hazards as required in the new blocks.
3230212904Sdim  Hazards.emitHazardsInNewBlocks();
3231212904Sdim
3232210299Sed  // Pop the cleanup.
3233212904Sdim  CGF.Builder.restoreIP(TryFallthroughIP);
3234212904Sdim  if (CGF.HaveInsertPoint())
3235212904Sdim    CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
3236210299Sed  CGF.PopCleanupBlock();
3237212904Sdim  CGF.EmitBlock(FinallyEnd.getBlock(), true);
3238193326Sed
3239210299Sed  // Emit the rethrow block.
3240212904Sdim  CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
3241212904Sdim  CGF.EmitBlock(FinallyRethrow.getBlock(), true);
3242210299Sed  if (CGF.HaveInsertPoint()) {
3243218893Sdim    // If we have a propagating-exception variable, check it.
3244218893Sdim    llvm::Value *PropagatingExn;
3245218893Sdim    if (PropagatingExnVar) {
3246218893Sdim      PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
3247212904Sdim
3248218893Sdim    // Otherwise, just look in the buffer for the exception to throw.
3249218893Sdim    } else {
3250218893Sdim      llvm::CallInst *Caught =
3251218893Sdim        CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3252218893Sdim                               ExceptionData);
3253218893Sdim      Caught->setDoesNotThrow();
3254218893Sdim      PropagatingExn = Caught;
3255218893Sdim    }
3256218893Sdim
3257218893Sdim    CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
3258210299Sed      ->setDoesNotThrow();
3259210299Sed    CGF.Builder.CreateUnreachable();
3260193326Sed  }
3261193326Sed
3262212904Sdim  CGF.Builder.restoreIP(SavedIP);
3263193326Sed}
3264193326Sed
3265193326Sedvoid CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
3266193326Sed                              const ObjCAtThrowStmt &S) {
3267193326Sed  llvm::Value *ExceptionAsObject;
3268198092Srdivacky
3269193326Sed  if (const Expr *ThrowExpr = S.getThrowExpr()) {
3270193326Sed    llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
3271198092Srdivacky    ExceptionAsObject =
3272193326Sed      CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
3273193326Sed  } else {
3274198092Srdivacky    assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
3275193326Sed           "Unexpected rethrow outside @catch block.");
3276193326Sed    ExceptionAsObject = CGF.ObjCEHValueStack.back();
3277193326Sed  }
3278198092Srdivacky
3279210299Sed  CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3280210299Sed    ->setDoesNotReturn();
3281193326Sed  CGF.Builder.CreateUnreachable();
3282193326Sed
3283193326Sed  // Clear the insertion point to indicate we are in unreachable code.
3284193326Sed  CGF.Builder.ClearInsertionPoint();
3285193326Sed}
3286193326Sed
3287193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak
3288193326Sed/// object: objc_read_weak (id *src)
3289193326Sed///
3290193326Sedllvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
3291198092Srdivacky                                          llvm::Value *AddrWeakObj) {
3292193326Sed  const llvm::Type* DestTy =
3293198092Srdivacky    cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3294198092Srdivacky  AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3295198092Srdivacky                                          ObjCTypes.PtrObjectPtrTy);
3296193326Sed  llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
3297193326Sed                                                  AddrWeakObj, "weakread");
3298193326Sed  read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
3299193326Sed  return read_weak;
3300193326Sed}
3301193326Sed
3302193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
3303193326Sed/// objc_assign_weak (id src, id *dst)
3304193326Sed///
3305193326Sedvoid CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
3306198092Srdivacky                                   llvm::Value *src, llvm::Value *dst) {
3307193326Sed  const llvm::Type * SrcTy = src->getType();
3308193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
3309193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
3310193326Sed    assert(Size <= 8 && "does not support size > 8");
3311193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
3312198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
3313193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3314193326Sed  }
3315193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3316193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
3317193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
3318193326Sed                          src, dst, "weakassign");
3319193326Sed  return;
3320193326Sed}
3321193326Sed
3322193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
3323193326Sed/// objc_assign_global (id src, id *dst)
3324193326Sed///
3325193326Sedvoid CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
3326212904Sdim                                     llvm::Value *src, llvm::Value *dst,
3327212904Sdim                                     bool threadlocal) {
3328193326Sed  const llvm::Type * SrcTy = src->getType();
3329193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
3330193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
3331193326Sed    assert(Size <= 8 && "does not support size > 8");
3332193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
3333198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
3334193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3335193326Sed  }
3336193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3337193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
3338212904Sdim  if (!threadlocal)
3339212904Sdim    CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
3340212904Sdim                            src, dst, "globalassign");
3341212904Sdim  else
3342212904Sdim    CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
3343212904Sdim                            src, dst, "threadlocalassign");
3344193326Sed  return;
3345193326Sed}
3346193326Sed
3347193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
3348198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
3349193326Sed///
3350193326Sedvoid CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
3351198092Srdivacky                                   llvm::Value *src, llvm::Value *dst,
3352198092Srdivacky                                   llvm::Value *ivarOffset) {
3353198092Srdivacky  assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
3354193326Sed  const llvm::Type * SrcTy = src->getType();
3355193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
3356193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
3357193326Sed    assert(Size <= 8 && "does not support size > 8");
3358193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
3359198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
3360193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3361193326Sed  }
3362193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3363193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
3364198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3365198092Srdivacky                          src, dst, ivarOffset);
3366193326Sed  return;
3367193326Sed}
3368193326Sed
3369193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
3370193326Sed/// objc_assign_strongCast (id src, id *dst)
3371193326Sed///
3372193326Sedvoid CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
3373198092Srdivacky                                         llvm::Value *src, llvm::Value *dst) {
3374193326Sed  const llvm::Type * SrcTy = src->getType();
3375193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
3376193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
3377193326Sed    assert(Size <= 8 && "does not support size > 8");
3378193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
3379198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
3380193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3381193326Sed  }
3382193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3383193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
3384193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
3385193326Sed                          src, dst, "weakassign");
3386193326Sed  return;
3387193326Sed}
3388193326Sed
3389198092Srdivackyvoid CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
3390198092Srdivacky                                         llvm::Value *DestPtr,
3391198092Srdivacky                                         llvm::Value *SrcPtr,
3392210299Sed                                         llvm::Value *size) {
3393198092Srdivacky  SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3394198092Srdivacky  DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
3395198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
3396210299Sed                          DestPtr, SrcPtr, size);
3397198092Srdivacky  return;
3398198092Srdivacky}
3399198092Srdivacky
3400193326Sed/// EmitObjCValueForIvar - Code Gen for ivar reference.
3401193326Sed///
3402193326SedLValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3403193326Sed                                       QualType ObjectTy,
3404193326Sed                                       llvm::Value *BaseValue,
3405193326Sed                                       const ObjCIvarDecl *Ivar,
3406193326Sed                                       unsigned CVRQualifiers) {
3407208600Srdivacky  const ObjCInterfaceDecl *ID =
3408208600Srdivacky    ObjectTy->getAs<ObjCObjectType>()->getInterface();
3409193326Sed  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3410193326Sed                                  EmitIvarOffset(CGF, ID, Ivar));
3411193326Sed}
3412193326Sed
3413193326Sedllvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
3414193326Sed                                       const ObjCInterfaceDecl *Interface,
3415193326Sed                                       const ObjCIvarDecl *Ivar) {
3416193326Sed  uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
3417193326Sed  return llvm::ConstantInt::get(
3418198092Srdivacky    CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3419198092Srdivacky    Offset);
3420193326Sed}
3421193326Sed
3422193326Sed/* *** Private Interface *** */
3423193326Sed
3424193326Sed/// EmitImageInfo - Emit the image info marker used to encode some module
3425193326Sed/// level information.
3426193326Sed///
3427193326Sed/// See: <rdr://4810609&4810587&4810587>
3428193326Sed/// struct IMAGE_INFO {
3429193326Sed///   unsigned version;
3430193326Sed///   unsigned flags;
3431193326Sed/// };
3432193326Sedenum ImageInfoFlags {
3433207619Srdivacky  eImageInfo_FixAndContinue      = (1 << 0),
3434198092Srdivacky  eImageInfo_GarbageCollected    = (1 << 1),
3435198092Srdivacky  eImageInfo_GCOnly              = (1 << 2),
3436193326Sed  eImageInfo_OptimizedByDyld     = (1 << 3), // FIXME: When is this set.
3437193326Sed
3438207619Srdivacky  // A flag indicating that the module has no instances of a @synthesize of a
3439207619Srdivacky  // superclass variable. <rdar://problem/6803242>
3440193326Sed  eImageInfo_CorrectedSynthesize = (1 << 4)
3441193326Sed};
3442193326Sed
3443207619Srdivackyvoid CGObjCCommonMac::EmitImageInfo() {
3444193326Sed  unsigned version = 0; // Version is unused?
3445193326Sed  unsigned flags = 0;
3446193326Sed
3447193326Sed  // FIXME: Fix and continue?
3448193326Sed  if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
3449193326Sed    flags |= eImageInfo_GarbageCollected;
3450193326Sed  if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
3451193326Sed    flags |= eImageInfo_GCOnly;
3452198092Srdivacky
3453193326Sed  // We never allow @synthesize of a superclass property.
3454193326Sed  flags |= eImageInfo_CorrectedSynthesize;
3455193326Sed
3456210299Sed  const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
3457210299Sed
3458193326Sed  // Emitted as int[2];
3459193326Sed  llvm::Constant *values[2] = {
3460210299Sed    llvm::ConstantInt::get(Int32Ty, version),
3461210299Sed    llvm::ConstantInt::get(Int32Ty, flags)
3462193326Sed  };
3463210299Sed  llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
3464193326Sed
3465193326Sed  const char *Section;
3466193326Sed  if (ObjCABI == 1)
3467193326Sed    Section = "__OBJC, __image_info,regular";
3468193326Sed  else
3469193326Sed    Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
3470198092Srdivacky  llvm::GlobalVariable *GV =
3471193326Sed    CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
3472193326Sed                      llvm::ConstantArray::get(AT, values, 2),
3473193326Sed                      Section,
3474193326Sed                      0,
3475193326Sed                      true);
3476193326Sed  GV->setConstant(true);
3477193326Sed}
3478193326Sed
3479193326Sed
3480193326Sed// struct objc_module {
3481193326Sed//   unsigned long version;
3482193326Sed//   unsigned long size;
3483193326Sed//   const char *name;
3484193326Sed//   Symtab symtab;
3485193326Sed// };
3486193326Sed
3487193326Sed// FIXME: Get from somewhere
3488193326Sedstatic const int ModuleVersion = 7;
3489193326Sed
3490193326Sedvoid CGObjCMac::EmitModuleInfo() {
3491193326Sed  uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
3492198092Srdivacky
3493193326Sed  std::vector<llvm::Constant*> Values(4);
3494193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
3495193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
3496193326Sed  // This used to be the filename, now it is unused. <rdr://4327263>
3497193326Sed  Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
3498193326Sed  Values[3] = EmitModuleSymbols();
3499198092Srdivacky  CreateMetadataVar("\01L_OBJC_MODULES",
3500193326Sed                    llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
3501193326Sed                    "__OBJC,__module_info,regular,no_dead_strip",
3502193326Sed                    4, true);
3503193326Sed}
3504193326Sed
3505193326Sedllvm::Constant *CGObjCMac::EmitModuleSymbols() {
3506193326Sed  unsigned NumClasses = DefinedClasses.size();
3507193326Sed  unsigned NumCategories = DefinedCategories.size();
3508193326Sed
3509193326Sed  // Return null if no symbols were defined.
3510193326Sed  if (!NumClasses && !NumCategories)
3511193326Sed    return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
3512193326Sed
3513193326Sed  std::vector<llvm::Constant*> Values(5);
3514193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3515193326Sed  Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
3516193326Sed  Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3517193326Sed  Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
3518193326Sed
3519193326Sed  // The runtime expects exactly the list of defined classes followed
3520193326Sed  // by the list of defined categories, in a single array.
3521193326Sed  std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
3522193326Sed  for (unsigned i=0; i<NumClasses; i++)
3523193326Sed    Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
3524193326Sed                                                ObjCTypes.Int8PtrTy);
3525193326Sed  for (unsigned i=0; i<NumCategories; i++)
3526198092Srdivacky    Symbols[NumClasses + i] =
3527193326Sed      llvm::ConstantExpr::getBitCast(DefinedCategories[i],
3528193326Sed                                     ObjCTypes.Int8PtrTy);
3529193326Sed
3530198092Srdivacky  Values[4] =
3531193326Sed    llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3532193326Sed                                                  NumClasses + NumCategories),
3533193326Sed                             Symbols);
3534193326Sed
3535198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
3536193326Sed
3537193326Sed  llvm::GlobalVariable *GV =
3538193326Sed    CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3539193326Sed                      "__OBJC,__symbols,regular,no_dead_strip",
3540193326Sed                      4, true);
3541193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
3542193326Sed}
3543193326Sed
3544198092Srdivackyllvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
3545193326Sed                                     const ObjCInterfaceDecl *ID) {
3546193326Sed  LazySymbols.insert(ID->getIdentifier());
3547193326Sed
3548193326Sed  llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
3549198092Srdivacky
3550193326Sed  if (!Entry) {
3551198092Srdivacky    llvm::Constant *Casted =
3552193326Sed      llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
3553193326Sed                                     ObjCTypes.ClassPtrTy);
3554198092Srdivacky    Entry =
3555193326Sed      CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3556193326Sed                        "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
3557193326Sed                        4, true);
3558193326Sed  }
3559193326Sed
3560199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
3561193326Sed}
3562193326Sed
3563210299Sedllvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
3564210299Sed                                     bool lvalue) {
3565193326Sed  llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
3566198092Srdivacky
3567193326Sed  if (!Entry) {
3568198092Srdivacky    llvm::Constant *Casted =
3569193326Sed      llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
3570193326Sed                                     ObjCTypes.SelectorPtrTy);
3571198092Srdivacky    Entry =
3572193326Sed      CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3573193326Sed                        "__OBJC,__message_refs,literal_pointers,no_dead_strip",
3574193326Sed                        4, true);
3575193326Sed  }
3576193326Sed
3577210299Sed  if (lvalue)
3578210299Sed    return Entry;
3579199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
3580193326Sed}
3581193326Sed
3582193326Sedllvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
3583193326Sed  llvm::GlobalVariable *&Entry = ClassNames[Ident];
3584193326Sed
3585193326Sed  if (!Entry)
3586198092Srdivacky    Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3587198398Srdivacky                          llvm::ConstantArray::get(VMContext,
3588198398Srdivacky                                                   Ident->getNameStart()),
3589193326Sed                              "__TEXT,__cstring,cstring_literals",
3590193326Sed                              1, true);
3591193326Sed
3592198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3593193326Sed}
3594193326Sed
3595212904Sdimllvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
3596212904Sdim  llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
3597212904Sdim      I = MethodDefinitions.find(MD);
3598212904Sdim  if (I != MethodDefinitions.end())
3599212904Sdim    return I->second;
3600212904Sdim
3601212904Sdim  if (MD->hasBody() && MD->getPCHLevel() > 0) {
3602212904Sdim    // MD isn't emitted yet because it comes from PCH.
3603212904Sdim    CGM.EmitTopLevelDecl(const_cast<ObjCMethodDecl*>(MD));
3604212904Sdim    assert(MethodDefinitions[MD] && "EmitTopLevelDecl didn't emit the method!");
3605212904Sdim    return MethodDefinitions[MD];
3606212904Sdim  }
3607212904Sdim
3608212904Sdim  return NULL;
3609212904Sdim}
3610212904Sdim
3611193326Sed/// GetIvarLayoutName - Returns a unique constant for the given
3612193326Sed/// ivar layout bitmap.
3613193326Sedllvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
3614198092Srdivacky                                       const ObjCCommonTypesHelper &ObjCTypes) {
3615193326Sed  return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
3616193326Sed}
3617193326Sed
3618193326Sedvoid CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
3619198092Srdivacky                                                unsigned int BytePos,
3620193326Sed                                                bool ForStrongLayout,
3621193326Sed                                                bool &HasUnion) {
3622193326Sed  const RecordDecl *RD = RT->getDecl();
3623193326Sed  // FIXME - Use iterator.
3624195341Sed  llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
3625193326Sed  const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
3626198092Srdivacky  const llvm::StructLayout *RecLayout =
3627193326Sed    CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
3628198092Srdivacky
3629193326Sed  BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3630193326Sed                      ForStrongLayout, HasUnion);
3631193326Sed}
3632193326Sed
3633193326Sedvoid CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
3634198092Srdivacky                             const llvm::StructLayout *Layout,
3635198092Srdivacky                             const RecordDecl *RD,
3636193326Sed                             const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
3637198092Srdivacky                             unsigned int BytePos, bool ForStrongLayout,
3638198092Srdivacky                             bool &HasUnion) {
3639193326Sed  bool IsUnion = (RD && RD->isUnion());
3640193326Sed  uint64_t MaxUnionIvarSize = 0;
3641193326Sed  uint64_t MaxSkippedUnionIvarSize = 0;
3642193326Sed  FieldDecl *MaxField = 0;
3643193326Sed  FieldDecl *MaxSkippedField = 0;
3644218893Sdim  FieldDecl *LastFieldBitfieldOrUnnamed = 0;
3645193326Sed  uint64_t MaxFieldOffset = 0;
3646193326Sed  uint64_t MaxSkippedFieldOffset = 0;
3647218893Sdim  uint64_t LastBitfieldOrUnnamedOffset = 0;
3648198092Srdivacky
3649193326Sed  if (RecFields.empty())
3650193326Sed    return;
3651193326Sed  unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3652193326Sed  unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3653193326Sed
3654193326Sed  for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
3655193326Sed    FieldDecl *Field = RecFields[i];
3656193326Sed    uint64_t FieldOffset;
3657198092Srdivacky    if (RD) {
3658207619Srdivacky      // Note that 'i' here is actually the field index inside RD of Field,
3659207619Srdivacky      // although this dependency is hidden.
3660207619Srdivacky      const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
3661207619Srdivacky      FieldOffset = RL.getFieldOffset(i) / 8;
3662198092Srdivacky    } else
3663193326Sed      FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
3664193326Sed
3665193326Sed    // Skip over unnamed or bitfields
3666193326Sed    if (!Field->getIdentifier() || Field->isBitField()) {
3667218893Sdim      LastFieldBitfieldOrUnnamed = Field;
3668218893Sdim      LastBitfieldOrUnnamedOffset = FieldOffset;
3669193326Sed      continue;
3670193326Sed    }
3671193326Sed
3672218893Sdim    LastFieldBitfieldOrUnnamed = 0;
3673193326Sed    QualType FQT = Field->getType();
3674193326Sed    if (FQT->isRecordType() || FQT->isUnionType()) {
3675193326Sed      if (FQT->isUnionType())
3676193326Sed        HasUnion = true;
3677193326Sed
3678198092Srdivacky      BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
3679193326Sed                                BytePos + FieldOffset,
3680193326Sed                                ForStrongLayout, HasUnion);
3681193326Sed      continue;
3682193326Sed    }
3683198092Srdivacky
3684193326Sed    if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3685198092Srdivacky      const ConstantArrayType *CArray =
3686193326Sed        dyn_cast_or_null<ConstantArrayType>(Array);
3687193326Sed      uint64_t ElCount = CArray->getSize().getZExtValue();
3688193326Sed      assert(CArray && "only array with known element size is supported");
3689193326Sed      FQT = CArray->getElementType();
3690193326Sed      while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3691193326Sed        const ConstantArrayType *CArray =
3692193326Sed          dyn_cast_or_null<ConstantArrayType>(Array);
3693193326Sed        ElCount *= CArray->getSize().getZExtValue();
3694193326Sed        FQT = CArray->getElementType();
3695193326Sed      }
3696198092Srdivacky
3697198092Srdivacky      assert(!FQT->isUnionType() &&
3698193326Sed             "layout for array of unions not supported");
3699218893Sdim      if (FQT->isRecordType() && ElCount) {
3700193326Sed        int OldIndex = IvarsInfo.size() - 1;
3701193326Sed        int OldSkIndex = SkipIvars.size() -1;
3702198092Srdivacky
3703198092Srdivacky        const RecordType *RT = FQT->getAs<RecordType>();
3704193326Sed        BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
3705193326Sed                                  ForStrongLayout, HasUnion);
3706198092Srdivacky
3707193326Sed        // Replicate layout information for each array element. Note that
3708193326Sed        // one element is already done.
3709193326Sed        uint64_t ElIx = 1;
3710198092Srdivacky        for (int FirstIndex = IvarsInfo.size() - 1,
3711198092Srdivacky               FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
3712193326Sed          uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
3713193326Sed          for (int i = OldIndex+1; i <= FirstIndex; ++i)
3714193326Sed            IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
3715193326Sed                                        IvarsInfo[i].ivar_size));
3716193326Sed          for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
3717193326Sed            SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
3718193326Sed                                        SkipIvars[i].ivar_size));
3719193326Sed        }
3720193326Sed        continue;
3721193326Sed      }
3722193326Sed    }
3723193326Sed    // At this point, we are done with Record/Union and array there of.
3724193326Sed    // For other arrays we are down to its element type.
3725198092Srdivacky    Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
3726193326Sed
3727193326Sed    unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
3728198092Srdivacky    if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3729198092Srdivacky        || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
3730193326Sed      if (IsUnion) {
3731193326Sed        uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
3732193326Sed        if (UnionIvarSize > MaxUnionIvarSize) {
3733193326Sed          MaxUnionIvarSize = UnionIvarSize;
3734193326Sed          MaxField = Field;
3735193326Sed          MaxFieldOffset = FieldOffset;
3736193326Sed        }
3737193326Sed      } else {
3738193326Sed        IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
3739193326Sed                                    FieldSize / WordSizeInBits));
3740193326Sed      }
3741198092Srdivacky    } else if ((ForStrongLayout &&
3742198092Srdivacky                (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3743198092Srdivacky               || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
3744193326Sed      if (IsUnion) {
3745193326Sed        // FIXME: Why the asymmetry? We divide by word size in bits on other
3746193326Sed        // side.
3747193326Sed        uint64_t UnionIvarSize = FieldSize;
3748193326Sed        if (UnionIvarSize > MaxSkippedUnionIvarSize) {
3749193326Sed          MaxSkippedUnionIvarSize = UnionIvarSize;
3750193326Sed          MaxSkippedField = Field;
3751193326Sed          MaxSkippedFieldOffset = FieldOffset;
3752193326Sed        }
3753193326Sed      } else {
3754193326Sed        // FIXME: Why the asymmetry, we divide by byte size in bits here?
3755193326Sed        SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
3756193326Sed                                    FieldSize / ByteSizeInBits));
3757193326Sed      }
3758193326Sed    }
3759193326Sed  }
3760193326Sed
3761218893Sdim  if (LastFieldBitfieldOrUnnamed) {
3762218893Sdim    if (LastFieldBitfieldOrUnnamed->isBitField()) {
3763218893Sdim      // Last field was a bitfield. Must update skip info.
3764218893Sdim      Expr *BitWidth = LastFieldBitfieldOrUnnamed->getBitWidth();
3765218893Sdim      uint64_t BitFieldSize =
3766218893Sdim        BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
3767218893Sdim      GC_IVAR skivar;
3768218893Sdim      skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
3769218893Sdim      skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3770218893Sdim        + ((BitFieldSize % ByteSizeInBits) != 0);
3771218893Sdim      SkipIvars.push_back(skivar);
3772218893Sdim    } else {
3773218893Sdim      assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
3774218893Sdim      // Last field was unnamed. Must update skip info.
3775218893Sdim      unsigned FieldSize
3776218893Sdim          = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
3777218893Sdim      SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
3778218893Sdim                                  FieldSize / ByteSizeInBits));
3779218893Sdim    }
3780193326Sed  }
3781198092Srdivacky
3782193326Sed  if (MaxField)
3783198092Srdivacky    IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
3784193326Sed                                MaxUnionIvarSize));
3785193326Sed  if (MaxSkippedField)
3786193326Sed    SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
3787193326Sed                                MaxSkippedUnionIvarSize));
3788193326Sed}
3789193326Sed
3790212904Sdim/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
3791212904Sdim/// the computations and returning the layout bitmap (for ivar or blocks) in
3792212904Sdim/// the given argument BitMap string container. Routine reads
3793212904Sdim/// two containers, IvarsInfo and SkipIvars which are assumed to be
3794212904Sdim/// filled already by the caller.
3795212904Sdimllvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string& BitMap) {
3796193326Sed  unsigned int WordsToScan, WordsToSkip;
3797198092Srdivacky  const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
3798212904Sdim
3799193326Sed  // Build the string of skip/scan nibbles
3800193326Sed  llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
3801198092Srdivacky  unsigned int WordSize =
3802212904Sdim  CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
3803193326Sed  if (IvarsInfo[0].ivar_bytepos == 0) {
3804193326Sed    WordsToSkip = 0;
3805193326Sed    WordsToScan = IvarsInfo[0].ivar_size;
3806193326Sed  } else {
3807193326Sed    WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3808193326Sed    WordsToScan = IvarsInfo[0].ivar_size;
3809193326Sed  }
3810193326Sed  for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
3811198092Srdivacky    unsigned int TailPrevGCObjC =
3812212904Sdim    IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
3813193326Sed    if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
3814193326Sed      // consecutive 'scanned' object pointers.
3815193326Sed      WordsToScan += IvarsInfo[i].ivar_size;
3816193326Sed    } else {
3817193326Sed      // Skip over 'gc'able object pointer which lay over each other.
3818193326Sed      if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
3819193326Sed        continue;
3820193326Sed      // Must skip over 1 or more words. We save current skip/scan values
3821193326Sed      //  and start a new pair.
3822193326Sed      SKIP_SCAN SkScan;
3823193326Sed      SkScan.skip = WordsToSkip;
3824193326Sed      SkScan.scan = WordsToScan;
3825193326Sed      SkipScanIvars.push_back(SkScan);
3826212904Sdim
3827193326Sed      // Skip the hole.
3828193326Sed      SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3829193326Sed      SkScan.scan = 0;
3830193326Sed      SkipScanIvars.push_back(SkScan);
3831193326Sed      WordsToSkip = 0;
3832193326Sed      WordsToScan = IvarsInfo[i].ivar_size;
3833193326Sed    }
3834193326Sed  }
3835193326Sed  if (WordsToScan > 0) {
3836193326Sed    SKIP_SCAN SkScan;
3837193326Sed    SkScan.skip = WordsToSkip;
3838193326Sed    SkScan.scan = WordsToScan;
3839193326Sed    SkipScanIvars.push_back(SkScan);
3840193326Sed  }
3841212904Sdim
3842193326Sed  if (!SkipIvars.empty()) {
3843193326Sed    unsigned int LastIndex = SkipIvars.size()-1;
3844198092Srdivacky    int LastByteSkipped =
3845212904Sdim    SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
3846193326Sed    LastIndex = IvarsInfo.size()-1;
3847198092Srdivacky    int LastByteScanned =
3848212904Sdim    IvarsInfo[LastIndex].ivar_bytepos +
3849212904Sdim    IvarsInfo[LastIndex].ivar_size * WordSize;
3850193326Sed    // Compute number of bytes to skip at the tail end of the last ivar scanned.
3851201361Srdivacky    if (LastByteSkipped > LastByteScanned) {
3852193326Sed      unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
3853193326Sed      SKIP_SCAN SkScan;
3854193326Sed      SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3855193326Sed      SkScan.scan = 0;
3856193326Sed      SkipScanIvars.push_back(SkScan);
3857193326Sed    }
3858193326Sed  }
3859193326Sed  // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3860193326Sed  // as 0xMN.
3861193326Sed  int SkipScan = SkipScanIvars.size()-1;
3862193326Sed  for (int i = 0; i <= SkipScan; i++) {
3863193326Sed    if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3864193326Sed        && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3865193326Sed      // 0xM0 followed by 0x0N detected.
3866193326Sed      SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
3867193326Sed      for (int j = i+1; j < SkipScan; j++)
3868193326Sed        SkipScanIvars[j] = SkipScanIvars[j+1];
3869193326Sed      --SkipScan;
3870193326Sed    }
3871193326Sed  }
3872212904Sdim
3873193326Sed  // Generate the string.
3874193326Sed  for (int i = 0; i <= SkipScan; i++) {
3875193326Sed    unsigned char byte;
3876193326Sed    unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
3877193326Sed    unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
3878193326Sed    unsigned int skip_big  = SkipScanIvars[i].skip / 0xf;
3879193326Sed    unsigned int scan_big  = SkipScanIvars[i].scan / 0xf;
3880212904Sdim
3881193326Sed    // first skip big.
3882193326Sed    for (unsigned int ix = 0; ix < skip_big; ix++)
3883193326Sed      BitMap += (unsigned char)(0xf0);
3884212904Sdim
3885193326Sed    // next (skip small, scan)
3886193326Sed    if (skip_small) {
3887193326Sed      byte = skip_small << 4;
3888193326Sed      if (scan_big > 0) {
3889193326Sed        byte |= 0xf;
3890193326Sed        --scan_big;
3891193326Sed      } else if (scan_small) {
3892193326Sed        byte |= scan_small;
3893193326Sed        scan_small = 0;
3894193326Sed      }
3895193326Sed      BitMap += byte;
3896193326Sed    }
3897193326Sed    // next scan big
3898193326Sed    for (unsigned int ix = 0; ix < scan_big; ix++)
3899193326Sed      BitMap += (unsigned char)(0x0f);
3900193326Sed    // last scan small
3901193326Sed    if (scan_small) {
3902193326Sed      byte = scan_small;
3903193326Sed      BitMap += byte;
3904193326Sed    }
3905193326Sed  }
3906193326Sed  // null terminate string.
3907193326Sed  unsigned char zero = 0;
3908193326Sed  BitMap += zero;
3909212904Sdim
3910212904Sdim  llvm::GlobalVariable * Entry =
3911212904Sdim  CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3912212904Sdim                    llvm::ConstantArray::get(VMContext, BitMap.c_str()),
3913212904Sdim                    "__TEXT,__cstring,cstring_literals",
3914212904Sdim                    1, true);
3915212904Sdim  return getConstantGEP(VMContext, Entry, 0, 0);
3916212904Sdim}
3917198092Srdivacky
3918212904Sdim/// BuildIvarLayout - Builds ivar layout bitmap for the class
3919212904Sdim/// implementation for the __strong or __weak case.
3920212904Sdim/// The layout map displays which words in ivar list must be skipped
3921212904Sdim/// and which must be scanned by GC (see below). String is built of bytes.
3922212904Sdim/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
3923212904Sdim/// of words to skip and right nibble is count of words to scan. So, each
3924212904Sdim/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
3925212904Sdim/// represented by a 0x00 byte which also ends the string.
3926212904Sdim/// 1. when ForStrongLayout is true, following ivars are scanned:
3927212904Sdim/// - id, Class
3928212904Sdim/// - object *
3929212904Sdim/// - __strong anything
3930212904Sdim///
3931212904Sdim/// 2. When ForStrongLayout is false, following ivars are scanned:
3932212904Sdim/// - __weak anything
3933212904Sdim///
3934212904Sdimllvm::Constant *CGObjCCommonMac::BuildIvarLayout(
3935212904Sdim  const ObjCImplementationDecl *OMD,
3936212904Sdim  bool ForStrongLayout) {
3937212904Sdim  bool hasUnion = false;
3938212904Sdim
3939212904Sdim  const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
3940212904Sdim  if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
3941212904Sdim    return llvm::Constant::getNullValue(PtrTy);
3942212904Sdim
3943212904Sdim  llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
3944212904Sdim  const ObjCInterfaceDecl *OI = OMD->getClassInterface();
3945212904Sdim  CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
3946212904Sdim
3947212904Sdim  llvm::SmallVector<FieldDecl*, 32> RecFields;
3948212904Sdim  for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
3949212904Sdim    RecFields.push_back(cast<FieldDecl>(Ivars[k]));
3950212904Sdim
3951212904Sdim  if (RecFields.empty())
3952212904Sdim    return llvm::Constant::getNullValue(PtrTy);
3953212904Sdim
3954212904Sdim  SkipIvars.clear();
3955212904Sdim  IvarsInfo.clear();
3956212904Sdim
3957212904Sdim  BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
3958212904Sdim  if (IvarsInfo.empty())
3959212904Sdim    return llvm::Constant::getNullValue(PtrTy);
3960212904Sdim  // Sort on byte position in case we encounterred a union nested in
3961212904Sdim  // the ivar list.
3962212904Sdim  if (hasUnion && !IvarsInfo.empty())
3963212904Sdim    std::sort(IvarsInfo.begin(), IvarsInfo.end());
3964212904Sdim  if (hasUnion && !SkipIvars.empty())
3965212904Sdim    std::sort(SkipIvars.begin(), SkipIvars.end());
3966212904Sdim
3967212904Sdim  std::string BitMap;
3968212904Sdim  llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
3969212904Sdim
3970212904Sdim   if (CGM.getLangOptions().ObjCGCBitmapPrint) {
3971198092Srdivacky    printf("\n%s ivar layout for class '%s': ",
3972193326Sed           ForStrongLayout ? "strong" : "weak",
3973212904Sdim           OMD->getClassInterface()->getName().data());
3974193326Sed    const unsigned char *s = (unsigned char*)BitMap.c_str();
3975193326Sed    for (unsigned i = 0; i < BitMap.size(); i++)
3976193326Sed      if (!(s[i] & 0xf0))
3977193326Sed        printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
3978193326Sed      else
3979193326Sed        printf("0x%x%s",  s[i], s[i] != 0 ? ", " : "");
3980193326Sed    printf("\n");
3981193326Sed  }
3982212904Sdim  return C;
3983193326Sed}
3984193326Sed
3985193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
3986193326Sed  llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3987193326Sed
3988193326Sed  // FIXME: Avoid std::string copying.
3989193326Sed  if (!Entry)
3990198092Srdivacky    Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
3991198092Srdivacky                        llvm::ConstantArray::get(VMContext, Sel.getAsString()),
3992193326Sed                              "__TEXT,__cstring,cstring_literals",
3993193326Sed                              1, true);
3994193326Sed
3995198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3996193326Sed}
3997193326Sed
3998193326Sed// FIXME: Merge into a single cstring creation function.
3999193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
4000193326Sed  return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
4001193326Sed}
4002193326Sed
4003193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
4004193326Sed  std::string TypeStr;
4005193326Sed  CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
4006193326Sed
4007193326Sed  llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4008193326Sed
4009193326Sed  if (!Entry)
4010193326Sed    Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
4011198092Srdivacky                              llvm::ConstantArray::get(VMContext, TypeStr),
4012193326Sed                              "__TEXT,__cstring,cstring_literals",
4013193326Sed                              1, true);
4014198092Srdivacky
4015198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
4016193326Sed}
4017193326Sed
4018193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
4019193326Sed  std::string TypeStr;
4020193326Sed  CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
4021193326Sed                                                TypeStr);
4022193326Sed
4023193326Sed  llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4024193326Sed
4025193326Sed  if (!Entry)
4026193326Sed    Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
4027198092Srdivacky                              llvm::ConstantArray::get(VMContext, TypeStr),
4028193326Sed                              "__TEXT,__cstring,cstring_literals",
4029193326Sed                              1, true);
4030193326Sed
4031198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
4032193326Sed}
4033193326Sed
4034193326Sed// FIXME: Merge into a single cstring creation function.
4035193326Sedllvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
4036193326Sed  llvm::GlobalVariable *&Entry = PropertyNames[Ident];
4037198092Srdivacky
4038193326Sed  if (!Entry)
4039198092Srdivacky    Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
4040198398Srdivacky                          llvm::ConstantArray::get(VMContext,
4041198398Srdivacky                                                   Ident->getNameStart()),
4042193326Sed                              "__TEXT,__cstring,cstring_literals",
4043193326Sed                              1, true);
4044193326Sed
4045198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
4046193326Sed}
4047193326Sed
4048193326Sed// FIXME: Merge into a single cstring creation function.
4049193326Sed// FIXME: This Decl should be more precise.
4050193326Sedllvm::Constant *
4051198092SrdivackyCGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4052198092Srdivacky                                       const Decl *Container) {
4053193326Sed  std::string TypeStr;
4054193326Sed  CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
4055193326Sed  return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4056193326Sed}
4057193326Sed
4058198092Srdivackyvoid CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
4059193326Sed                                       const ObjCContainerDecl *CD,
4060198398Srdivacky                                       llvm::SmallVectorImpl<char> &Name) {
4061198398Srdivacky  llvm::raw_svector_ostream OS(Name);
4062193326Sed  assert (CD && "Missing container decl in GetNameForMethod");
4063198398Srdivacky  OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4064198398Srdivacky     << '[' << CD->getName();
4065198092Srdivacky  if (const ObjCCategoryImplDecl *CID =
4066198398Srdivacky      dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
4067207619Srdivacky    OS << '(' << CID << ')';
4068198398Srdivacky  OS << ' ' << D->getSelector().getAsString() << ']';
4069193326Sed}
4070193326Sed
4071193326Sedvoid CGObjCMac::FinishModule() {
4072193326Sed  EmitModuleInfo();
4073193326Sed
4074193326Sed  // Emit the dummy bodies for any protocols which were referenced but
4075193326Sed  // never defined.
4076198092Srdivacky  for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
4077198092Srdivacky         I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4078198092Srdivacky    if (I->second->hasInitializer())
4079193326Sed      continue;
4080193326Sed
4081193326Sed    std::vector<llvm::Constant*> Values(5);
4082193326Sed    Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
4083198092Srdivacky    Values[1] = GetClassName(I->first);
4084193326Sed    Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
4085193326Sed    Values[3] = Values[4] =
4086193326Sed      llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
4087198092Srdivacky    I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
4088198092Srdivacky    I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
4089193326Sed                                                        Values));
4090198092Srdivacky    CGM.AddUsedGlobal(I->second);
4091193326Sed  }
4092193326Sed
4093193326Sed  // Add assembler directives to add lazy undefined symbol references
4094193326Sed  // for classes which are referenced but not defined. This is
4095193326Sed  // important for correct linker interaction.
4096198092Srdivacky  //
4097198092Srdivacky  // FIXME: It would be nice if we had an LLVM construct for this.
4098198092Srdivacky  if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
4099198092Srdivacky    llvm::SmallString<256> Asm;
4100198092Srdivacky    Asm += CGM.getModule().getModuleInlineAsm();
4101198092Srdivacky    if (!Asm.empty() && Asm.back() != '\n')
4102198092Srdivacky      Asm += '\n';
4103193326Sed
4104198092Srdivacky    llvm::raw_svector_ostream OS(Asm);
4105198092Srdivacky    for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4106198092Srdivacky           e = DefinedSymbols.end(); I != e; ++I)
4107198092Srdivacky      OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4108198092Srdivacky         << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
4109207619Srdivacky    for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
4110210299Sed         e = LazySymbols.end(); I != e; ++I) {
4111207619Srdivacky      OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
4112210299Sed    }
4113210299Sed
4114210299Sed    for (size_t i = 0; i < DefinedCategoryNames.size(); ++i) {
4115210299Sed      OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4116210299Sed         << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4117210299Sed    }
4118207619Srdivacky
4119198092Srdivacky    CGM.getModule().setModuleInlineAsm(OS.str());
4120193326Sed  }
4121193326Sed}
4122193326Sed
4123198092SrdivackyCGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
4124193326Sed  : CGObjCCommonMac(cgm),
4125198092Srdivacky    ObjCTypes(cgm) {
4126193326Sed  ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
4127193326Sed  ObjCABI = 2;
4128193326Sed}
4129193326Sed
4130193326Sed/* *** */
4131193326Sed
4132193326SedObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
4133198092Srdivacky  : VMContext(cgm.getLLVMContext()), CGM(cgm) {
4134193326Sed  CodeGen::CodeGenTypes &Types = CGM.getTypes();
4135193326Sed  ASTContext &Ctx = CGM.getContext();
4136198092Srdivacky
4137193326Sed  ShortTy = Types.ConvertType(Ctx.ShortTy);
4138193326Sed  IntTy = Types.ConvertType(Ctx.IntTy);
4139193326Sed  LongTy = Types.ConvertType(Ctx.LongTy);
4140193326Sed  LongLongTy = Types.ConvertType(Ctx.LongLongTy);
4141198092Srdivacky  Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
4142198092Srdivacky
4143193326Sed  ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
4144193326Sed  PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
4145193326Sed  SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
4146198092Srdivacky
4147193326Sed  // FIXME: It would be nice to unify this with the opaque type, so that the IR
4148193326Sed  // comes out a bit cleaner.
4149193326Sed  const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
4150193326Sed  ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
4151198092Srdivacky
4152193326Sed  // I'm not sure I like this. The implicit coordination is a bit
4153193326Sed  // gross. We should solve this in a reasonable fashion because this
4154193326Sed  // is a pretty common task (match some runtime data structure with
4155193326Sed  // an LLVM data structure).
4156198092Srdivacky
4157193326Sed  // FIXME: This is leaked.
4158193326Sed  // FIXME: Merge with rewriter code?
4159198092Srdivacky
4160193326Sed  // struct _objc_super {
4161193326Sed  //   id self;
4162193326Sed  //   Class cls;
4163193326Sed  // }
4164208600Srdivacky  RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
4165207619Srdivacky                                      Ctx.getTranslationUnitDecl(),
4166193326Sed                                      SourceLocation(),
4167198092Srdivacky                                      &Ctx.Idents.get("_objc_super"));
4168195341Sed  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
4169198092Srdivacky                                Ctx.getObjCIdType(), 0, 0, false));
4170198092Srdivacky  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
4171198092Srdivacky                                Ctx.getObjCClassType(), 0, 0, false));
4172203955Srdivacky  RD->completeDefinition();
4173198092Srdivacky
4174193326Sed  SuperCTy = Ctx.getTagDeclType(RD);
4175193326Sed  SuperPtrCTy = Ctx.getPointerType(SuperCTy);
4176198092Srdivacky
4177193326Sed  SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
4178198092Srdivacky  SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4179198092Srdivacky
4180193326Sed  // struct _prop_t {
4181193326Sed  //   char *name;
4182198092Srdivacky  //   char *attributes;
4183193326Sed  // }
4184198092Srdivacky  PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
4185198092Srdivacky  CGM.getModule().addTypeName("struct._prop_t",
4186193326Sed                              PropertyTy);
4187198092Srdivacky
4188193326Sed  // struct _prop_list_t {
4189193326Sed  //   uint32_t entsize;      // sizeof(struct _prop_t)
4190193326Sed  //   uint32_t count_of_properties;
4191193326Sed  //   struct _prop_t prop_list[count_of_properties];
4192193326Sed  // }
4193198092Srdivacky  PropertyListTy = llvm::StructType::get(VMContext, IntTy,
4194193326Sed                                         IntTy,
4195193326Sed                                         llvm::ArrayType::get(PropertyTy, 0),
4196193326Sed                                         NULL);
4197198092Srdivacky  CGM.getModule().addTypeName("struct._prop_list_t",
4198193326Sed                              PropertyListTy);
4199193326Sed  // struct _prop_list_t *
4200193326Sed  PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
4201198092Srdivacky
4202193326Sed  // struct _objc_method {
4203193326Sed  //   SEL _cmd;
4204193326Sed  //   char *method_type;
4205193326Sed  //   char *_imp;
4206193326Sed  // }
4207198092Srdivacky  MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
4208193326Sed                                   Int8PtrTy,
4209193326Sed                                   Int8PtrTy,
4210193326Sed                                   NULL);
4211193326Sed  CGM.getModule().addTypeName("struct._objc_method", MethodTy);
4212198092Srdivacky
4213193326Sed  // struct _objc_cache *
4214198092Srdivacky  CacheTy = llvm::OpaqueType::get(VMContext);
4215193326Sed  CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
4216193326Sed  CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
4217193326Sed}
4218193326Sed
4219198092SrdivackyObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
4220198092Srdivacky  : ObjCCommonTypesHelper(cgm) {
4221193326Sed  // struct _objc_method_description {
4222193326Sed  //   SEL name;
4223193326Sed  //   char *types;
4224193326Sed  // }
4225198092Srdivacky  MethodDescriptionTy =
4226198092Srdivacky    llvm::StructType::get(VMContext, SelectorPtrTy,
4227193326Sed                          Int8PtrTy,
4228193326Sed                          NULL);
4229198092Srdivacky  CGM.getModule().addTypeName("struct._objc_method_description",
4230193326Sed                              MethodDescriptionTy);
4231193326Sed
4232193326Sed  // struct _objc_method_description_list {
4233193326Sed  //   int count;
4234193326Sed  //   struct _objc_method_description[1];
4235193326Sed  // }
4236198092Srdivacky  MethodDescriptionListTy =
4237198092Srdivacky    llvm::StructType::get(VMContext, IntTy,
4238193326Sed                          llvm::ArrayType::get(MethodDescriptionTy, 0),
4239193326Sed                          NULL);
4240198092Srdivacky  CGM.getModule().addTypeName("struct._objc_method_description_list",
4241193326Sed                              MethodDescriptionListTy);
4242198092Srdivacky
4243193326Sed  // struct _objc_method_description_list *
4244198092Srdivacky  MethodDescriptionListPtrTy =
4245193326Sed    llvm::PointerType::getUnqual(MethodDescriptionListTy);
4246193326Sed
4247193326Sed  // Protocol description structures
4248193326Sed
4249193326Sed  // struct _objc_protocol_extension {
4250193326Sed  //   uint32_t size;  // sizeof(struct _objc_protocol_extension)
4251193326Sed  //   struct _objc_method_description_list *optional_instance_methods;
4252193326Sed  //   struct _objc_method_description_list *optional_class_methods;
4253193326Sed  //   struct _objc_property_list *instance_properties;
4254193326Sed  // }
4255198092Srdivacky  ProtocolExtensionTy =
4256198092Srdivacky    llvm::StructType::get(VMContext, IntTy,
4257193326Sed                          MethodDescriptionListPtrTy,
4258193326Sed                          MethodDescriptionListPtrTy,
4259193326Sed                          PropertyListPtrTy,
4260193326Sed                          NULL);
4261198092Srdivacky  CGM.getModule().addTypeName("struct._objc_protocol_extension",
4262193326Sed                              ProtocolExtensionTy);
4263198092Srdivacky
4264193326Sed  // struct _objc_protocol_extension *
4265193326Sed  ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
4266193326Sed
4267193326Sed  // Handle recursive construction of Protocol and ProtocolList types
4268193326Sed
4269198092Srdivacky  llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
4270198092Srdivacky  llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
4271193326Sed
4272198092Srdivacky  const llvm::Type *T =
4273198092Srdivacky    llvm::StructType::get(VMContext,
4274198092Srdivacky                          llvm::PointerType::getUnqual(ProtocolListTyHolder),
4275193326Sed                          LongTy,
4276193326Sed                          llvm::ArrayType::get(ProtocolTyHolder, 0),
4277193326Sed                          NULL);
4278193326Sed  cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
4279193326Sed
4280193326Sed  // struct _objc_protocol {
4281193326Sed  //   struct _objc_protocol_extension *isa;
4282193326Sed  //   char *protocol_name;
4283193326Sed  //   struct _objc_protocol **_objc_protocol_list;
4284193326Sed  //   struct _objc_method_description_list *instance_methods;
4285193326Sed  //   struct _objc_method_description_list *class_methods;
4286193326Sed  // }
4287198092Srdivacky  T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
4288193326Sed                            Int8PtrTy,
4289193326Sed                            llvm::PointerType::getUnqual(ProtocolListTyHolder),
4290193326Sed                            MethodDescriptionListPtrTy,
4291193326Sed                            MethodDescriptionListPtrTy,
4292193326Sed                            NULL);
4293193326Sed  cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
4294193326Sed
4295193326Sed  ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
4296198092Srdivacky  CGM.getModule().addTypeName("struct._objc_protocol_list",
4297193326Sed                              ProtocolListTy);
4298193326Sed  // struct _objc_protocol_list *
4299193326Sed  ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
4300193326Sed
4301193326Sed  ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
4302193326Sed  CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
4303193326Sed  ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
4304193326Sed
4305193326Sed  // Class description structures
4306193326Sed
4307193326Sed  // struct _objc_ivar {
4308193326Sed  //   char *ivar_name;
4309193326Sed  //   char *ivar_type;
4310193326Sed  //   int  ivar_offset;
4311193326Sed  // }
4312198092Srdivacky  IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
4313198092Srdivacky                                 Int8PtrTy,
4314198092Srdivacky                                 IntTy,
4315193326Sed                                 NULL);
4316193326Sed  CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
4317193326Sed
4318193326Sed  // struct _objc_ivar_list *
4319198092Srdivacky  IvarListTy = llvm::OpaqueType::get(VMContext);
4320193326Sed  CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
4321193326Sed  IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
4322193326Sed
4323193326Sed  // struct _objc_method_list *
4324198092Srdivacky  MethodListTy = llvm::OpaqueType::get(VMContext);
4325193326Sed  CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
4326193326Sed  MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
4327193326Sed
4328193326Sed  // struct _objc_class_extension *
4329198092Srdivacky  ClassExtensionTy =
4330198092Srdivacky    llvm::StructType::get(VMContext, IntTy,
4331193326Sed                          Int8PtrTy,
4332193326Sed                          PropertyListPtrTy,
4333193326Sed                          NULL);
4334193326Sed  CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
4335193326Sed  ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
4336193326Sed
4337198092Srdivacky  llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
4338193326Sed
4339193326Sed  // struct _objc_class {
4340193326Sed  //   Class isa;
4341193326Sed  //   Class super_class;
4342193326Sed  //   char *name;
4343193326Sed  //   long version;
4344193326Sed  //   long info;
4345193326Sed  //   long instance_size;
4346193326Sed  //   struct _objc_ivar_list *ivars;
4347193326Sed  //   struct _objc_method_list *methods;
4348193326Sed  //   struct _objc_cache *cache;
4349193326Sed  //   struct _objc_protocol_list *protocols;
4350193326Sed  //   char *ivar_layout;
4351193326Sed  //   struct _objc_class_ext *ext;
4352193326Sed  // };
4353198092Srdivacky  T = llvm::StructType::get(VMContext,
4354193326Sed                            llvm::PointerType::getUnqual(ClassTyHolder),
4355198092Srdivacky                            llvm::PointerType::getUnqual(ClassTyHolder),
4356193326Sed                            Int8PtrTy,
4357193326Sed                            LongTy,
4358193326Sed                            LongTy,
4359193326Sed                            LongTy,
4360193326Sed                            IvarListPtrTy,
4361193326Sed                            MethodListPtrTy,
4362193326Sed                            CachePtrTy,
4363193326Sed                            ProtocolListPtrTy,
4364193326Sed                            Int8PtrTy,
4365193326Sed                            ClassExtensionPtrTy,
4366193326Sed                            NULL);
4367193326Sed  cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
4368198092Srdivacky
4369193326Sed  ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
4370193326Sed  CGM.getModule().addTypeName("struct._objc_class", ClassTy);
4371193326Sed  ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
4372193326Sed
4373193326Sed  // struct _objc_category {
4374193326Sed  //   char *category_name;
4375193326Sed  //   char *class_name;
4376193326Sed  //   struct _objc_method_list *instance_method;
4377193326Sed  //   struct _objc_method_list *class_method;
4378193326Sed  //   uint32_t size;  // sizeof(struct _objc_category)
4379193326Sed  //   struct _objc_property_list *instance_properties;// category's @property
4380193326Sed  // }
4381198092Srdivacky  CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
4382193326Sed                                     Int8PtrTy,
4383193326Sed                                     MethodListPtrTy,
4384193326Sed                                     MethodListPtrTy,
4385193326Sed                                     ProtocolListPtrTy,
4386193326Sed                                     IntTy,
4387193326Sed                                     PropertyListPtrTy,
4388193326Sed                                     NULL);
4389193326Sed  CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
4390193326Sed
4391193326Sed  // Global metadata structures
4392193326Sed
4393193326Sed  // struct _objc_symtab {
4394193326Sed  //   long sel_ref_cnt;
4395193326Sed  //   SEL *refs;
4396193326Sed  //   short cls_def_cnt;
4397193326Sed  //   short cat_def_cnt;
4398193326Sed  //   char *defs[cls_def_cnt + cat_def_cnt];
4399193326Sed  // }
4400198092Srdivacky  SymtabTy = llvm::StructType::get(VMContext, LongTy,
4401193326Sed                                   SelectorPtrTy,
4402193326Sed                                   ShortTy,
4403193326Sed                                   ShortTy,
4404193326Sed                                   llvm::ArrayType::get(Int8PtrTy, 0),
4405193326Sed                                   NULL);
4406193326Sed  CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
4407193326Sed  SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
4408193326Sed
4409193326Sed  // struct _objc_module {
4410193326Sed  //   long version;
4411193326Sed  //   long size;   // sizeof(struct _objc_module)
4412193326Sed  //   char *name;
4413193326Sed  //   struct _objc_symtab* symtab;
4414193326Sed  //  }
4415198092Srdivacky  ModuleTy =
4416198092Srdivacky    llvm::StructType::get(VMContext, LongTy,
4417193326Sed                          LongTy,
4418193326Sed                          Int8PtrTy,
4419193326Sed                          SymtabPtrTy,
4420193326Sed                          NULL);
4421193326Sed  CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
4422193326Sed
4423198092Srdivacky
4424193326Sed  // FIXME: This is the size of the setjmp buffer and should be target
4425193326Sed  // specific. 18 is what's used on 32-bit X86.
4426193326Sed  uint64_t SetJmpBufferSize = 18;
4427198092Srdivacky
4428193326Sed  // Exceptions
4429198092Srdivacky  const llvm::Type *StackPtrTy = llvm::ArrayType::get(
4430198092Srdivacky    llvm::Type::getInt8PtrTy(VMContext), 4);
4431198092Srdivacky
4432198092Srdivacky  ExceptionDataTy =
4433210299Sed    llvm::StructType::get(VMContext,
4434210299Sed                        llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
4435210299Sed                                             SetJmpBufferSize),
4436193326Sed                          StackPtrTy, NULL);
4437198092Srdivacky  CGM.getModule().addTypeName("struct._objc_exception_data",
4438193326Sed                              ExceptionDataTy);
4439193326Sed
4440193326Sed}
4441193326Sed
4442198092SrdivackyObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
4443198092Srdivacky  : ObjCCommonTypesHelper(cgm) {
4444193326Sed  // struct _method_list_t {
4445193326Sed  //   uint32_t entsize;  // sizeof(struct _objc_method)
4446193326Sed  //   uint32_t method_count;
4447193326Sed  //   struct _objc_method method_list[method_count];
4448193326Sed  // }
4449198092Srdivacky  MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
4450193326Sed                                            IntTy,
4451193326Sed                                            llvm::ArrayType::get(MethodTy, 0),
4452193326Sed                                            NULL);
4453193326Sed  CGM.getModule().addTypeName("struct.__method_list_t",
4454193326Sed                              MethodListnfABITy);
4455193326Sed  // struct method_list_t *
4456193326Sed  MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
4457198092Srdivacky
4458193326Sed  // struct _protocol_t {
4459193326Sed  //   id isa;  // NULL
4460193326Sed  //   const char * const protocol_name;
4461193326Sed  //   const struct _protocol_list_t * protocol_list; // super protocols
4462193326Sed  //   const struct method_list_t * const instance_methods;
4463193326Sed  //   const struct method_list_t * const class_methods;
4464193326Sed  //   const struct method_list_t *optionalInstanceMethods;
4465193326Sed  //   const struct method_list_t *optionalClassMethods;
4466193326Sed  //   const struct _prop_list_t * properties;
4467193326Sed  //   const uint32_t size;  // sizeof(struct _protocol_t)
4468193326Sed  //   const uint32_t flags;  // = 0
4469193326Sed  // }
4470198092Srdivacky
4471193326Sed  // Holder for struct _protocol_list_t *
4472198092Srdivacky  llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
4473198092Srdivacky
4474198092Srdivacky  ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
4475193326Sed                                          Int8PtrTy,
4476193326Sed                                          llvm::PointerType::getUnqual(
4477193326Sed                                            ProtocolListTyHolder),
4478193326Sed                                          MethodListnfABIPtrTy,
4479193326Sed                                          MethodListnfABIPtrTy,
4480193326Sed                                          MethodListnfABIPtrTy,
4481193326Sed                                          MethodListnfABIPtrTy,
4482193326Sed                                          PropertyListPtrTy,
4483193326Sed                                          IntTy,
4484193326Sed                                          IntTy,
4485193326Sed                                          NULL);
4486193326Sed  CGM.getModule().addTypeName("struct._protocol_t",
4487193326Sed                              ProtocolnfABITy);
4488193326Sed
4489193326Sed  // struct _protocol_t*
4490193326Sed  ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
4491198092Srdivacky
4492193326Sed  // struct _protocol_list_t {
4493193326Sed  //   long protocol_count;   // Note, this is 32/64 bit
4494193326Sed  //   struct _protocol_t *[protocol_count];
4495193326Sed  // }
4496198092Srdivacky  ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
4497193326Sed                                              llvm::ArrayType::get(
4498193326Sed                                                ProtocolnfABIPtrTy, 0),
4499193326Sed                                              NULL);
4500193326Sed  CGM.getModule().addTypeName("struct._objc_protocol_list",
4501193326Sed                              ProtocolListnfABITy);
4502193326Sed  cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
4503198092Srdivacky    ProtocolListnfABITy);
4504198092Srdivacky
4505193326Sed  // struct _objc_protocol_list*
4506193326Sed  ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
4507198092Srdivacky
4508193326Sed  // struct _ivar_t {
4509193326Sed  //   unsigned long int *offset;  // pointer to ivar offset location
4510193326Sed  //   char *name;
4511193326Sed  //   char *type;
4512193326Sed  //   uint32_t alignment;
4513193326Sed  //   uint32_t size;
4514193326Sed  // }
4515198092Srdivacky  IvarnfABITy = llvm::StructType::get(VMContext,
4516198092Srdivacky                                      llvm::PointerType::getUnqual(LongTy),
4517193326Sed                                      Int8PtrTy,
4518193326Sed                                      Int8PtrTy,
4519193326Sed                                      IntTy,
4520193326Sed                                      IntTy,
4521193326Sed                                      NULL);
4522193326Sed  CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
4523198092Srdivacky
4524193326Sed  // struct _ivar_list_t {
4525193326Sed  //   uint32 entsize;  // sizeof(struct _ivar_t)
4526193326Sed  //   uint32 count;
4527193326Sed  //   struct _iver_t list[count];
4528193326Sed  // }
4529198092Srdivacky  IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
4530193326Sed                                          IntTy,
4531193326Sed                                          llvm::ArrayType::get(
4532198092Srdivacky                                            IvarnfABITy, 0),
4533193326Sed                                          NULL);
4534193326Sed  CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
4535198092Srdivacky
4536193326Sed  IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
4537198092Srdivacky
4538193326Sed  // struct _class_ro_t {
4539193326Sed  //   uint32_t const flags;
4540193326Sed  //   uint32_t const instanceStart;
4541193326Sed  //   uint32_t const instanceSize;
4542193326Sed  //   uint32_t const reserved;  // only when building for 64bit targets
4543193326Sed  //   const uint8_t * const ivarLayout;
4544193326Sed  //   const char *const name;
4545193326Sed  //   const struct _method_list_t * const baseMethods;
4546193326Sed  //   const struct _objc_protocol_list *const baseProtocols;
4547193326Sed  //   const struct _ivar_list_t *const ivars;
4548193326Sed  //   const uint8_t * const weakIvarLayout;
4549193326Sed  //   const struct _prop_list_t * const properties;
4550193326Sed  // }
4551198092Srdivacky
4552193326Sed  // FIXME. Add 'reserved' field in 64bit abi mode!
4553198092Srdivacky  ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
4554193326Sed                                         IntTy,
4555193326Sed                                         IntTy,
4556193326Sed                                         Int8PtrTy,
4557193326Sed                                         Int8PtrTy,
4558193326Sed                                         MethodListnfABIPtrTy,
4559193326Sed                                         ProtocolListnfABIPtrTy,
4560193326Sed                                         IvarListnfABIPtrTy,
4561193326Sed                                         Int8PtrTy,
4562193326Sed                                         PropertyListPtrTy,
4563193326Sed                                         NULL);
4564193326Sed  CGM.getModule().addTypeName("struct._class_ro_t",
4565193326Sed                              ClassRonfABITy);
4566198092Srdivacky
4567193326Sed  // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
4568193326Sed  std::vector<const llvm::Type*> Params;
4569193326Sed  Params.push_back(ObjectPtrTy);
4570193326Sed  Params.push_back(SelectorPtrTy);
4571193326Sed  ImpnfABITy = llvm::PointerType::getUnqual(
4572198092Srdivacky    llvm::FunctionType::get(ObjectPtrTy, Params, false));
4573198092Srdivacky
4574193326Sed  // struct _class_t {
4575193326Sed  //   struct _class_t *isa;
4576193326Sed  //   struct _class_t * const superclass;
4577193326Sed  //   void *cache;
4578193326Sed  //   IMP *vtable;
4579193326Sed  //   struct class_ro_t *ro;
4580193326Sed  // }
4581198092Srdivacky
4582198092Srdivacky  llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
4583198092Srdivacky  ClassnfABITy =
4584198092Srdivacky    llvm::StructType::get(VMContext,
4585198092Srdivacky                          llvm::PointerType::getUnqual(ClassTyHolder),
4586198092Srdivacky                          llvm::PointerType::getUnqual(ClassTyHolder),
4587198092Srdivacky                          CachePtrTy,
4588198092Srdivacky                          llvm::PointerType::getUnqual(ImpnfABITy),
4589198092Srdivacky                          llvm::PointerType::getUnqual(ClassRonfABITy),
4590198092Srdivacky                          NULL);
4591193326Sed  CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
4592193326Sed
4593193326Sed  cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
4594198092Srdivacky    ClassnfABITy);
4595198092Srdivacky
4596193326Sed  // LLVM for struct _class_t *
4597193326Sed  ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
4598198092Srdivacky
4599193326Sed  // struct _category_t {
4600193326Sed  //   const char * const name;
4601193326Sed  //   struct _class_t *const cls;
4602193326Sed  //   const struct _method_list_t * const instance_methods;
4603193326Sed  //   const struct _method_list_t * const class_methods;
4604193326Sed  //   const struct _protocol_list_t * const protocols;
4605193326Sed  //   const struct _prop_list_t * const properties;
4606193326Sed  // }
4607198092Srdivacky  CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
4608193326Sed                                          ClassnfABIPtrTy,
4609193326Sed                                          MethodListnfABIPtrTy,
4610193326Sed                                          MethodListnfABIPtrTy,
4611193326Sed                                          ProtocolListnfABIPtrTy,
4612193326Sed                                          PropertyListPtrTy,
4613193326Sed                                          NULL);
4614193326Sed  CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
4615198092Srdivacky
4616193326Sed  // New types for nonfragile abi messaging.
4617193326Sed  CodeGen::CodeGenTypes &Types = CGM.getTypes();
4618193326Sed  ASTContext &Ctx = CGM.getContext();
4619198092Srdivacky
4620193326Sed  // MessageRefTy - LLVM for:
4621193326Sed  // struct _message_ref_t {
4622193326Sed  //   IMP messenger;
4623193326Sed  //   SEL name;
4624193326Sed  // };
4625198092Srdivacky
4626193326Sed  // First the clang type for struct _message_ref_t
4627208600Srdivacky  RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
4628207619Srdivacky                                      Ctx.getTranslationUnitDecl(),
4629193326Sed                                      SourceLocation(),
4630193326Sed                                      &Ctx.Idents.get("_message_ref_t"));
4631195341Sed  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
4632198092Srdivacky                                Ctx.VoidPtrTy, 0, 0, false));
4633195341Sed  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
4634198092Srdivacky                                Ctx.getObjCSelType(), 0, 0, false));
4635203955Srdivacky  RD->completeDefinition();
4636198092Srdivacky
4637193326Sed  MessageRefCTy = Ctx.getTagDeclType(RD);
4638193326Sed  MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4639193326Sed  MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
4640198092Srdivacky
4641193326Sed  // MessageRefPtrTy - LLVM for struct _message_ref_t*
4642193326Sed  MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
4643198092Srdivacky
4644193326Sed  // SuperMessageRefTy - LLVM for:
4645193326Sed  // struct _super_message_ref_t {
4646193326Sed  //   SUPER_IMP messenger;
4647193326Sed  //   SEL name;
4648193326Sed  // };
4649198092Srdivacky  SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
4650193326Sed                                            SelectorPtrTy,
4651193326Sed                                            NULL);
4652193326Sed  CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
4653198092Srdivacky
4654193326Sed  // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
4655198092Srdivacky  SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
4656193326Sed
4657198092Srdivacky
4658193326Sed  // struct objc_typeinfo {
4659193326Sed  //   const void** vtable; // objc_ehtype_vtable + 2
4660193326Sed  //   const char*  name;    // c++ typeinfo string
4661193326Sed  //   Class        cls;
4662193326Sed  // };
4663198092Srdivacky  EHTypeTy = llvm::StructType::get(VMContext,
4664198092Srdivacky                                   llvm::PointerType::getUnqual(Int8PtrTy),
4665193326Sed                                   Int8PtrTy,
4666193326Sed                                   ClassnfABIPtrTy,
4667193326Sed                                   NULL);
4668193326Sed  CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
4669193326Sed  EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
4670193326Sed}
4671193326Sed
4672198092Srdivackyllvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
4673193326Sed  FinishNonFragileABIModule();
4674198092Srdivacky
4675193326Sed  return NULL;
4676193326Sed}
4677193326Sed
4678198092Srdivackyvoid CGObjCNonFragileABIMac::AddModuleClassList(const
4679198092Srdivacky                                                std::vector<llvm::GlobalValue*>
4680198092Srdivacky                                                &Container,
4681193326Sed                                                const char *SymbolName,
4682193326Sed                                                const char *SectionName) {
4683193326Sed  unsigned NumClasses = Container.size();
4684198092Srdivacky
4685193326Sed  if (!NumClasses)
4686193326Sed    return;
4687198092Srdivacky
4688193326Sed  std::vector<llvm::Constant*> Symbols(NumClasses);
4689193326Sed  for (unsigned i=0; i<NumClasses; i++)
4690193326Sed    Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
4691193326Sed                                                ObjCTypes.Int8PtrTy);
4692198092Srdivacky  llvm::Constant* Init =
4693193326Sed    llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
4694193326Sed                                                  NumClasses),
4695193326Sed                             Symbols);
4696198092Srdivacky
4697193326Sed  llvm::GlobalVariable *GV =
4698198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
4699193326Sed                             llvm::GlobalValue::InternalLinkage,
4700193326Sed                             Init,
4701198092Srdivacky                             SymbolName);
4702207619Srdivacky  GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
4703193326Sed  GV->setSection(SectionName);
4704198092Srdivacky  CGM.AddUsedGlobal(GV);
4705193326Sed}
4706198092Srdivacky
4707193326Sedvoid CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4708193326Sed  // nonfragile abi has no module definition.
4709198092Srdivacky
4710193326Sed  // Build list of all implemented class addresses in array
4711193326Sed  // L_OBJC_LABEL_CLASS_$.
4712198092Srdivacky  AddModuleClassList(DefinedClasses,
4713193326Sed                     "\01L_OBJC_LABEL_CLASS_$",
4714193326Sed                     "__DATA, __objc_classlist, regular, no_dead_strip");
4715199482Srdivacky
4716199482Srdivacky  for (unsigned i = 0; i < DefinedClasses.size(); i++) {
4717199482Srdivacky    llvm::GlobalValue *IMPLGV = DefinedClasses[i];
4718199482Srdivacky    if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4719199482Srdivacky      continue;
4720199482Srdivacky    IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4721199482Srdivacky  }
4722199482Srdivacky
4723200583Srdivacky  for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
4724200583Srdivacky    llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
4725200583Srdivacky    if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4726200583Srdivacky      continue;
4727200583Srdivacky    IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4728200583Srdivacky  }
4729199482Srdivacky
4730198092Srdivacky  AddModuleClassList(DefinedNonLazyClasses,
4731193326Sed                     "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4732193326Sed                     "__DATA, __objc_nlclslist, regular, no_dead_strip");
4733198092Srdivacky
4734193326Sed  // Build list of all implemented category addresses in array
4735193326Sed  // L_OBJC_LABEL_CATEGORY_$.
4736198092Srdivacky  AddModuleClassList(DefinedCategories,
4737193326Sed                     "\01L_OBJC_LABEL_CATEGORY_$",
4738193326Sed                     "__DATA, __objc_catlist, regular, no_dead_strip");
4739198092Srdivacky  AddModuleClassList(DefinedNonLazyCategories,
4740193326Sed                     "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4741193326Sed                     "__DATA, __objc_nlcatlist, regular, no_dead_strip");
4742198092Srdivacky
4743207619Srdivacky  EmitImageInfo();
4744193326Sed}
4745193326Sed
4746193326Sed/// LegacyDispatchedSelector - Returns true if SEL is not in the list of
4747193326Sed/// NonLegacyDispatchMethods; false otherwise. What this means is that
4748198092Srdivacky/// except for the 19 selectors in the list, we generate 32bit-style
4749193326Sed/// message dispatch call for all the rest.
4750193326Sed///
4751193326Sedbool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) {
4752207619Srdivacky  switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
4753207619Srdivacky  default:
4754207619Srdivacky    assert(0 && "Invalid dispatch method!");
4755207619Srdivacky  case CodeGenOptions::Legacy:
4756203955Srdivacky    return true;
4757207619Srdivacky  case CodeGenOptions::NonLegacy:
4758207619Srdivacky    return false;
4759207619Srdivacky  case CodeGenOptions::Mixed:
4760207619Srdivacky    break;
4761207619Srdivacky  }
4762203955Srdivacky
4763207619Srdivacky  // If so, see whether this selector is in the white-list of things which must
4764207619Srdivacky  // use the new dispatch convention. We lazily build a dense set for this.
4765193326Sed  if (NonLegacyDispatchMethods.empty()) {
4766193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("alloc"));
4767193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("class"));
4768193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("self"));
4769193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("isFlipped"));
4770193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("length"));
4771193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("count"));
4772193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("retain"));
4773193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("release"));
4774193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("autorelease"));
4775193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("hash"));
4776198092Srdivacky
4777193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("allocWithZone"));
4778193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
4779193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
4780193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("objectForKey"));
4781193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
4782193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("isEqualToString"));
4783193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("isEqual"));
4784193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("addObject"));
4785198092Srdivacky    // "countByEnumeratingWithState:objects:count"
4786193326Sed    IdentifierInfo *KeyIdents[] = {
4787198092Srdivacky      &CGM.getContext().Idents.get("countByEnumeratingWithState"),
4788198092Srdivacky      &CGM.getContext().Idents.get("objects"),
4789198092Srdivacky      &CGM.getContext().Idents.get("count")
4790193326Sed    };
4791193326Sed    NonLegacyDispatchMethods.insert(
4792193326Sed      CGM.getContext().Selectors.getSelector(3, KeyIdents));
4793193326Sed  }
4794207619Srdivacky
4795193326Sed  return (NonLegacyDispatchMethods.count(Sel) == 0);
4796193326Sed}
4797193326Sed
4798193326Sed// Metadata flags
4799193326Sedenum MetaDataDlags {
4800193326Sed  CLS = 0x0,
4801193326Sed  CLS_META = 0x1,
4802193326Sed  CLS_ROOT = 0x2,
4803193326Sed  OBJC2_CLS_HIDDEN = 0x10,
4804193326Sed  CLS_EXCEPTION = 0x20
4805193326Sed};
4806193326Sed/// BuildClassRoTInitializer - generate meta-data for:
4807193326Sed/// struct _class_ro_t {
4808193326Sed///   uint32_t const flags;
4809193326Sed///   uint32_t const instanceStart;
4810193326Sed///   uint32_t const instanceSize;
4811193326Sed///   uint32_t const reserved;  // only when building for 64bit targets
4812193326Sed///   const uint8_t * const ivarLayout;
4813193326Sed///   const char *const name;
4814193326Sed///   const struct _method_list_t * const baseMethods;
4815193326Sed///   const struct _protocol_list_t *const baseProtocols;
4816193326Sed///   const struct _ivar_list_t *const ivars;
4817193326Sed///   const uint8_t * const weakIvarLayout;
4818193326Sed///   const struct _prop_list_t * const properties;
4819193326Sed/// }
4820193326Sed///
4821193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
4822198092Srdivacky  unsigned flags,
4823198092Srdivacky  unsigned InstanceStart,
4824198092Srdivacky  unsigned InstanceSize,
4825198092Srdivacky  const ObjCImplementationDecl *ID) {
4826193326Sed  std::string ClassName = ID->getNameAsString();
4827193326Sed  std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
4828193326Sed  Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4829193326Sed  Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
4830193326Sed  Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
4831193326Sed  // FIXME. For 64bit targets add 0 here.
4832198092Srdivacky  Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4833198092Srdivacky    : BuildIvarLayout(ID, true);
4834193326Sed  Values[ 4] = GetClassName(ID->getIdentifier());
4835193326Sed  // const struct _method_list_t * const baseMethods;
4836193326Sed  std::vector<llvm::Constant*> Methods;
4837193326Sed  std::string MethodListName("\01l_OBJC_$_");
4838193326Sed  if (flags & CLS_META) {
4839193326Sed    MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
4840198092Srdivacky    for (ObjCImplementationDecl::classmeth_iterator
4841195341Sed           i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
4842193326Sed      // Class methods should always be defined.
4843193326Sed      Methods.push_back(GetMethodConstant(*i));
4844193326Sed    }
4845193326Sed  } else {
4846193326Sed    MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
4847198092Srdivacky    for (ObjCImplementationDecl::instmeth_iterator
4848195341Sed           i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
4849193326Sed      // Instance methods should always be defined.
4850193326Sed      Methods.push_back(GetMethodConstant(*i));
4851193326Sed    }
4852198092Srdivacky    for (ObjCImplementationDecl::propimpl_iterator
4853195341Sed           i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
4854193326Sed      ObjCPropertyImplDecl *PID = *i;
4855198092Srdivacky
4856193326Sed      if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4857193326Sed        ObjCPropertyDecl *PD = PID->getPropertyDecl();
4858198092Srdivacky
4859193326Sed        if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
4860193326Sed          if (llvm::Constant *C = GetMethodConstant(MD))
4861193326Sed            Methods.push_back(C);
4862193326Sed        if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
4863193326Sed          if (llvm::Constant *C = GetMethodConstant(MD))
4864193326Sed            Methods.push_back(C);
4865193326Sed      }
4866193326Sed    }
4867193326Sed  }
4868198092Srdivacky  Values[ 5] = EmitMethodList(MethodListName,
4869198092Srdivacky                              "__DATA, __objc_const", Methods);
4870198092Srdivacky
4871193326Sed  const ObjCInterfaceDecl *OID = ID->getClassInterface();
4872193326Sed  assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
4873198092Srdivacky  Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
4874198398Srdivacky                                + OID->getName(),
4875212904Sdim                                OID->all_referenced_protocol_begin(),
4876212904Sdim                                OID->all_referenced_protocol_end());
4877198092Srdivacky
4878193326Sed  if (flags & CLS_META)
4879193326Sed    Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
4880193326Sed  else
4881193326Sed    Values[ 7] = EmitIvarList(ID);
4882198092Srdivacky  Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4883198092Srdivacky    : BuildIvarLayout(ID, false);
4884193326Sed  if (flags & CLS_META)
4885193326Sed    Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
4886193326Sed  else
4887198398Srdivacky    Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4888198398Srdivacky                                  ID, ID->getClassInterface(), ObjCTypes);
4889193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
4890193326Sed                                                   Values);
4891193326Sed  llvm::GlobalVariable *CLASS_RO_GV =
4892198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
4893198092Srdivacky                             llvm::GlobalValue::InternalLinkage,
4894198092Srdivacky                             Init,
4895198092Srdivacky                             (flags & CLS_META) ?
4896198092Srdivacky                             std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
4897198092Srdivacky                             std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
4898193326Sed  CLASS_RO_GV->setAlignment(
4899207619Srdivacky    CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
4900193326Sed  CLASS_RO_GV->setSection("__DATA, __objc_const");
4901193326Sed  return CLASS_RO_GV;
4902193326Sed
4903193326Sed}
4904193326Sed
4905193326Sed/// BuildClassMetaData - This routine defines that to-level meta-data
4906193326Sed/// for the given ClassName for:
4907193326Sed/// struct _class_t {
4908193326Sed///   struct _class_t *isa;
4909193326Sed///   struct _class_t * const superclass;
4910193326Sed///   void *cache;
4911193326Sed///   IMP *vtable;
4912193326Sed///   struct class_ro_t *ro;
4913193326Sed/// }
4914193326Sed///
4915193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
4916198092Srdivacky  std::string &ClassName,
4917198092Srdivacky  llvm::Constant *IsAGV,
4918198092Srdivacky  llvm::Constant *SuperClassGV,
4919198092Srdivacky  llvm::Constant *ClassRoGV,
4920198092Srdivacky  bool HiddenVisibility) {
4921193326Sed  std::vector<llvm::Constant*> Values(5);
4922193326Sed  Values[0] = IsAGV;
4923198092Srdivacky  Values[1] = SuperClassGV;
4924198092Srdivacky  if (!Values[1])
4925198092Srdivacky    Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
4926193326Sed  Values[2] = ObjCEmptyCacheVar;  // &ObjCEmptyCacheVar
4927193326Sed  Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4928193326Sed  Values[4] = ClassRoGV;                 // &CLASS_RO_GV
4929198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
4930193326Sed                                                   Values);
4931193326Sed  llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4932193326Sed  GV->setInitializer(Init);
4933193326Sed  GV->setSection("__DATA, __objc_data");
4934193326Sed  GV->setAlignment(
4935207619Srdivacky    CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
4936193326Sed  if (HiddenVisibility)
4937193326Sed    GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4938193326Sed  return GV;
4939193326Sed}
4940193326Sed
4941198092Srdivackybool
4942193326SedCGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
4943195341Sed  return OD->getClassMethod(GetNullarySelector("load")) != 0;
4944193326Sed}
4945193326Sed
4946193326Sedvoid CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
4947193326Sed                                              uint32_t &InstanceStart,
4948193326Sed                                              uint32_t &InstanceSize) {
4949198092Srdivacky  const ASTRecordLayout &RL =
4950193326Sed    CGM.getContext().getASTObjCImplementationLayout(OID);
4951198092Srdivacky
4952193326Sed  // InstanceSize is really instance end.
4953218893Sdim  InstanceSize = RL.getDataSize().getQuantity();
4954193326Sed
4955193326Sed  // If there are no fields, the start is the same as the end.
4956193326Sed  if (!RL.getFieldCount())
4957193326Sed    InstanceStart = InstanceSize;
4958193326Sed  else
4959193326Sed    InstanceStart = RL.getFieldOffset(0) / 8;
4960193326Sed}
4961193326Sed
4962193326Sedvoid CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
4963193326Sed  std::string ClassName = ID->getNameAsString();
4964193326Sed  if (!ObjCEmptyCacheVar) {
4965193326Sed    ObjCEmptyCacheVar = new llvm::GlobalVariable(
4966198092Srdivacky      CGM.getModule(),
4967198092Srdivacky      ObjCTypes.CacheTy,
4968198092Srdivacky      false,
4969198092Srdivacky      llvm::GlobalValue::ExternalLinkage,
4970198092Srdivacky      0,
4971198092Srdivacky      "_objc_empty_cache");
4972198092Srdivacky
4973193326Sed    ObjCEmptyVtableVar = new llvm::GlobalVariable(
4974198092Srdivacky      CGM.getModule(),
4975198092Srdivacky      ObjCTypes.ImpnfABITy,
4976198092Srdivacky      false,
4977198092Srdivacky      llvm::GlobalValue::ExternalLinkage,
4978198092Srdivacky      0,
4979198092Srdivacky      "_objc_empty_vtable");
4980193326Sed  }
4981198092Srdivacky  assert(ID->getClassInterface() &&
4982193326Sed         "CGObjCNonFragileABIMac::GenerateClass - class is 0");
4983193326Sed  // FIXME: Is this correct (that meta class size is never computed)?
4984198092Srdivacky  uint32_t InstanceStart =
4985193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
4986193326Sed  uint32_t InstanceSize = InstanceStart;
4987193326Sed  uint32_t flags = CLS_META;
4988193326Sed  std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4989193326Sed  std::string ObjCClassName(getClassSymbolPrefix());
4990198092Srdivacky
4991193326Sed  llvm::GlobalVariable *SuperClassGV, *IsAGV;
4992198092Srdivacky
4993198092Srdivacky  bool classIsHidden =
4994218893Sdim    ID->getClassInterface()->getVisibility() == HiddenVisibility;
4995193326Sed  if (classIsHidden)
4996193326Sed    flags |= OBJC2_CLS_HIDDEN;
4997207619Srdivacky  if (ID->getNumIvarInitializers())
4998207619Srdivacky    flags |= eClassFlags_ABI2_HasCXXStructors;
4999193326Sed  if (!ID->getClassInterface()->getSuperClass()) {
5000193326Sed    // class is root
5001193326Sed    flags |= CLS_ROOT;
5002193326Sed    SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
5003193326Sed    IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
5004193326Sed  } else {
5005193326Sed    // Has a root. Current class is not a root.
5006193326Sed    const ObjCInterfaceDecl *Root = ID->getClassInterface();
5007193326Sed    while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
5008193326Sed      Root = Super;
5009193326Sed    IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
5010200583Srdivacky    if (Root->hasAttr<WeakImportAttr>())
5011200583Srdivacky      IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5012193326Sed    // work on super class metadata symbol.
5013198092Srdivacky    std::string SuperClassName =
5014200583Srdivacky      ObjCMetaClassName +
5015200583Srdivacky        ID->getClassInterface()->getSuperClass()->getNameAsString();
5016193326Sed    SuperClassGV = GetClassGlobal(SuperClassName);
5017199482Srdivacky    if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
5018199482Srdivacky      SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5019193326Sed  }
5020193326Sed  llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
5021193326Sed                                                               InstanceStart,
5022193326Sed                                                               InstanceSize,ID);
5023193326Sed  std::string TClassName = ObjCMetaClassName + ClassName;
5024198092Srdivacky  llvm::GlobalVariable *MetaTClass =
5025193326Sed    BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
5026193326Sed                       classIsHidden);
5027199482Srdivacky  DefinedMetaClasses.push_back(MetaTClass);
5028193326Sed
5029193326Sed  // Metadata for the class
5030193326Sed  flags = CLS;
5031193326Sed  if (classIsHidden)
5032193326Sed    flags |= OBJC2_CLS_HIDDEN;
5033207619Srdivacky  if (ID->getNumIvarInitializers())
5034207619Srdivacky    flags |= eClassFlags_ABI2_HasCXXStructors;
5035193326Sed
5036194613Sed  if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
5037193326Sed    flags |= CLS_EXCEPTION;
5038193326Sed
5039193326Sed  if (!ID->getClassInterface()->getSuperClass()) {
5040193326Sed    flags |= CLS_ROOT;
5041193326Sed    SuperClassGV = 0;
5042193326Sed  } else {
5043193326Sed    // Has a root. Current class is not a root.
5044193326Sed    std::string RootClassName =
5045193326Sed      ID->getClassInterface()->getSuperClass()->getNameAsString();
5046193326Sed    SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
5047199482Srdivacky    if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
5048199482Srdivacky      SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5049193326Sed  }
5050193326Sed  GetClassSizeInfo(ID, InstanceStart, InstanceSize);
5051193326Sed  CLASS_RO_GV = BuildClassRoTInitializer(flags,
5052193326Sed                                         InstanceStart,
5053198092Srdivacky                                         InstanceSize,
5054193326Sed                                         ID);
5055198092Srdivacky
5056193326Sed  TClassName = ObjCClassName + ClassName;
5057198092Srdivacky  llvm::GlobalVariable *ClassMD =
5058193326Sed    BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5059193326Sed                       classIsHidden);
5060193326Sed  DefinedClasses.push_back(ClassMD);
5061193326Sed
5062193326Sed  // Determine if this class is also "non-lazy".
5063193326Sed  if (ImplementationIsNonLazy(ID))
5064193326Sed    DefinedNonLazyClasses.push_back(ClassMD);
5065193326Sed
5066193326Sed  // Force the definition of the EHType if necessary.
5067193326Sed  if (flags & CLS_EXCEPTION)
5068193326Sed    GetInterfaceEHType(ID->getClassInterface(), true);
5069193326Sed}
5070193326Sed
5071193326Sed/// GenerateProtocolRef - This routine is called to generate code for
5072193326Sed/// a protocol reference expression; as in:
5073193326Sed/// @code
5074193326Sed///   @protocol(Proto1);
5075193326Sed/// @endcode
5076193326Sed/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5077193326Sed/// which will hold address of the protocol meta-data.
5078193326Sed///
5079193326Sedllvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
5080198092Srdivacky                                                         const ObjCProtocolDecl *PD) {
5081198092Srdivacky
5082193326Sed  // This routine is called for @protocol only. So, we must build definition
5083193326Sed  // of protocol's meta-data (not a reference to it!)
5084193326Sed  //
5085198092Srdivacky  llvm::Constant *Init =
5086198092Srdivacky    llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
5087198092Srdivacky                                   ObjCTypes.ExternalProtocolPtrTy);
5088198092Srdivacky
5089193326Sed  std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
5090212904Sdim  ProtocolName += PD->getName();
5091198092Srdivacky
5092193326Sed  llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5093193326Sed  if (PTGV)
5094199990Srdivacky    return Builder.CreateLoad(PTGV, "tmp");
5095193326Sed  PTGV = new llvm::GlobalVariable(
5096198092Srdivacky    CGM.getModule(),
5097198092Srdivacky    Init->getType(), false,
5098198092Srdivacky    llvm::GlobalValue::WeakAnyLinkage,
5099198092Srdivacky    Init,
5100198092Srdivacky    ProtocolName);
5101193326Sed  PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5102193326Sed  PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
5103198092Srdivacky  CGM.AddUsedGlobal(PTGV);
5104199990Srdivacky  return Builder.CreateLoad(PTGV, "tmp");
5105193326Sed}
5106193326Sed
5107193326Sed/// GenerateCategory - Build metadata for a category implementation.
5108193326Sed/// struct _category_t {
5109193326Sed///   const char * const name;
5110193326Sed///   struct _class_t *const cls;
5111193326Sed///   const struct _method_list_t * const instance_methods;
5112193326Sed///   const struct _method_list_t * const class_methods;
5113193326Sed///   const struct _protocol_list_t * const protocols;
5114193326Sed///   const struct _prop_list_t * const properties;
5115193326Sed/// }
5116193326Sed///
5117193326Sedvoid CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
5118193326Sed  const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
5119193326Sed  const char *Prefix = "\01l_OBJC_$_CATEGORY_";
5120198092Srdivacky  std::string ExtCatName(Prefix + Interface->getNameAsString()+
5121198092Srdivacky                         "_$_" + OCD->getNameAsString());
5122198092Srdivacky  std::string ExtClassName(getClassSymbolPrefix() +
5123193326Sed                           Interface->getNameAsString());
5124198092Srdivacky
5125193326Sed  std::vector<llvm::Constant*> Values(6);
5126193326Sed  Values[0] = GetClassName(OCD->getIdentifier());
5127193326Sed  // meta-class entry symbol
5128193326Sed  llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
5129199482Srdivacky  if (Interface->hasAttr<WeakImportAttr>())
5130199482Srdivacky    ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5131199482Srdivacky
5132193326Sed  Values[1] = ClassGV;
5133193326Sed  std::vector<llvm::Constant*> Methods;
5134193326Sed  std::string MethodListName(Prefix);
5135198092Srdivacky  MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
5136193326Sed    "_$_" + OCD->getNameAsString();
5137198092Srdivacky
5138198092Srdivacky  for (ObjCCategoryImplDecl::instmeth_iterator
5139195341Sed         i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
5140193326Sed    // Instance methods should always be defined.
5141193326Sed    Methods.push_back(GetMethodConstant(*i));
5142193326Sed  }
5143198092Srdivacky
5144198092Srdivacky  Values[2] = EmitMethodList(MethodListName,
5145198092Srdivacky                             "__DATA, __objc_const",
5146193326Sed                             Methods);
5147193326Sed
5148193326Sed  MethodListName = Prefix;
5149193326Sed  MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5150193326Sed    OCD->getNameAsString();
5151193326Sed  Methods.clear();
5152198092Srdivacky  for (ObjCCategoryImplDecl::classmeth_iterator
5153195341Sed         i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
5154193326Sed    // Class methods should always be defined.
5155193326Sed    Methods.push_back(GetMethodConstant(*i));
5156193326Sed  }
5157198092Srdivacky
5158198092Srdivacky  Values[3] = EmitMethodList(MethodListName,
5159198092Srdivacky                             "__DATA, __objc_const",
5160193326Sed                             Methods);
5161198092Srdivacky  const ObjCCategoryDecl *Category =
5162193326Sed    Interface->FindCategoryDeclaration(OCD->getIdentifier());
5163193326Sed  if (Category) {
5164198398Srdivacky    llvm::SmallString<256> ExtName;
5165198398Srdivacky    llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5166198398Srdivacky                                       << OCD->getName();
5167193326Sed    Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
5168198398Srdivacky                                 + Interface->getName() + "_$_"
5169198398Srdivacky                                 + Category->getName(),
5170193326Sed                                 Category->protocol_begin(),
5171193326Sed                                 Category->protocol_end());
5172198398Srdivacky    Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5173198398Srdivacky                                 OCD, Category, ObjCTypes);
5174198092Srdivacky  } else {
5175193326Sed    Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5176193326Sed    Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
5177193326Sed  }
5178198092Srdivacky
5179198092Srdivacky  llvm::Constant *Init =
5180198092Srdivacky    llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
5181193326Sed                              Values);
5182193326Sed  llvm::GlobalVariable *GCATV
5183198092Srdivacky    = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
5184193326Sed                               false,
5185193326Sed                               llvm::GlobalValue::InternalLinkage,
5186193326Sed                               Init,
5187198092Srdivacky                               ExtCatName);
5188193326Sed  GCATV->setAlignment(
5189207619Srdivacky    CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
5190193326Sed  GCATV->setSection("__DATA, __objc_const");
5191198092Srdivacky  CGM.AddUsedGlobal(GCATV);
5192193326Sed  DefinedCategories.push_back(GCATV);
5193193326Sed
5194193326Sed  // Determine if this category is also "non-lazy".
5195193326Sed  if (ImplementationIsNonLazy(OCD))
5196193326Sed    DefinedNonLazyCategories.push_back(GCATV);
5197193326Sed}
5198193326Sed
5199193326Sed/// GetMethodConstant - Return a struct objc_method constant for the
5200193326Sed/// given method if it has been defined. The result is null if the
5201193326Sed/// method has not been defined. The return value has type MethodPtrTy.
5202193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
5203198092Srdivacky  const ObjCMethodDecl *MD) {
5204212904Sdim  llvm::Function *Fn = GetMethodDefinition(MD);
5205193326Sed  if (!Fn)
5206193326Sed    return 0;
5207198092Srdivacky
5208193326Sed  std::vector<llvm::Constant*> Method(3);
5209198092Srdivacky  Method[0] =
5210198092Srdivacky    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5211198092Srdivacky                                   ObjCTypes.SelectorPtrTy);
5212193326Sed  Method[1] = GetMethodVarType(MD);
5213193326Sed  Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
5214193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
5215193326Sed}
5216193326Sed
5217193326Sed/// EmitMethodList - Build meta-data for method declarations
5218193326Sed/// struct _method_list_t {
5219193326Sed///   uint32_t entsize;  // sizeof(struct _objc_method)
5220193326Sed///   uint32_t method_count;
5221193326Sed///   struct _objc_method method_list[method_count];
5222193326Sed/// }
5223193326Sed///
5224198398Srdivackyllvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
5225198398Srdivacky                                                       const char *Section,
5226198398Srdivacky                                                const ConstantVector &Methods) {
5227193326Sed  // Return null for empty list.
5228193326Sed  if (Methods.empty())
5229193326Sed    return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
5230198092Srdivacky
5231193326Sed  std::vector<llvm::Constant*> Values(3);
5232193326Sed  // sizeof(struct _objc_method)
5233193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
5234193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5235193326Sed  // method_count
5236193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
5237193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
5238193326Sed                                             Methods.size());
5239193326Sed  Values[2] = llvm::ConstantArray::get(AT, Methods);
5240198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
5241198092Srdivacky
5242193326Sed  llvm::GlobalVariable *GV =
5243198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
5244193326Sed                             llvm::GlobalValue::InternalLinkage,
5245193326Sed                             Init,
5246198092Srdivacky                             Name);
5247193326Sed  GV->setAlignment(
5248207619Srdivacky    CGM.getTargetData().getABITypeAlignment(Init->getType()));
5249193326Sed  GV->setSection(Section);
5250198092Srdivacky  CGM.AddUsedGlobal(GV);
5251193326Sed  return llvm::ConstantExpr::getBitCast(GV,
5252193326Sed                                        ObjCTypes.MethodListnfABIPtrTy);
5253193326Sed}
5254193326Sed
5255193326Sed/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5256193326Sed/// the given ivar.
5257206125Srdivackyllvm::GlobalVariable *
5258206125SrdivackyCGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5259206125Srdivacky                                               const ObjCIvarDecl *Ivar) {
5260206125Srdivacky  const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
5261193326Sed  std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
5262193326Sed    '.' + Ivar->getNameAsString();
5263198092Srdivacky  llvm::GlobalVariable *IvarOffsetGV =
5264193326Sed    CGM.getModule().getGlobalVariable(Name);
5265193326Sed  if (!IvarOffsetGV)
5266198092Srdivacky    IvarOffsetGV =
5267198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
5268193326Sed                               false,
5269193326Sed                               llvm::GlobalValue::ExternalLinkage,
5270193326Sed                               0,
5271198092Srdivacky                               Name);
5272193326Sed  return IvarOffsetGV;
5273193326Sed}
5274193326Sed
5275206125Srdivackyllvm::Constant *
5276206125SrdivackyCGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5277206125Srdivacky                                          const ObjCIvarDecl *Ivar,
5278206125Srdivacky                                          unsigned long int Offset) {
5279193326Sed  llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
5280198092Srdivacky  IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
5281193326Sed                                                      Offset));
5282193326Sed  IvarOffsetGV->setAlignment(
5283207619Srdivacky    CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
5284193326Sed
5285193326Sed  // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
5286193326Sed  // well (i.e., in ObjCIvarOffsetVariable).
5287193326Sed  if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5288193326Sed      Ivar->getAccessControl() == ObjCIvarDecl::Package ||
5289218893Sdim      ID->getVisibility() == HiddenVisibility)
5290193326Sed    IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
5291193326Sed  else
5292193326Sed    IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
5293193326Sed  IvarOffsetGV->setSection("__DATA, __objc_const");
5294193326Sed  return IvarOffsetGV;
5295193326Sed}
5296193326Sed
5297193326Sed/// EmitIvarList - Emit the ivar list for the given
5298193326Sed/// implementation. The return value has type
5299193326Sed/// IvarListnfABIPtrTy.
5300193326Sed///  struct _ivar_t {
5301193326Sed///   unsigned long int *offset;  // pointer to ivar offset location
5302193326Sed///   char *name;
5303193326Sed///   char *type;
5304193326Sed///   uint32_t alignment;
5305193326Sed///   uint32_t size;
5306193326Sed/// }
5307193326Sed/// struct _ivar_list_t {
5308193326Sed///   uint32 entsize;  // sizeof(struct _ivar_t)
5309193326Sed///   uint32 count;
5310193326Sed///   struct _iver_t list[count];
5311193326Sed/// }
5312193326Sed///
5313193326Sed
5314193326Sedllvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
5315198092Srdivacky  const ObjCImplementationDecl *ID) {
5316198092Srdivacky
5317193326Sed  std::vector<llvm::Constant*> Ivars, Ivar(5);
5318198092Srdivacky
5319193326Sed  const ObjCInterfaceDecl *OID = ID->getClassInterface();
5320193326Sed  assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
5321198092Srdivacky
5322193326Sed  // FIXME. Consolidate this with similar code in GenerateClass.
5323198092Srdivacky
5324193326Sed  // Collect declared and synthesized ivars in a small vector.
5325193326Sed  llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
5326193576Sed  CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
5327198092Srdivacky
5328193326Sed  for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
5329193326Sed    ObjCIvarDecl *IVD = OIvars[i];
5330193576Sed    // Ignore unnamed bit-fields.
5331193576Sed    if (!IVD->getDeclName())
5332193576Sed      continue;
5333198092Srdivacky    Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
5334193326Sed                                ComputeIvarBaseOffset(CGM, ID, IVD));
5335193326Sed    Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5336193326Sed    Ivar[2] = GetMethodVarType(IVD);
5337193326Sed    const llvm::Type *FieldTy =
5338193326Sed      CGM.getTypes().ConvertTypeForMem(IVD->getType());
5339193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
5340193326Sed    unsigned Align = CGM.getContext().getPreferredTypeAlign(
5341198092Srdivacky      IVD->getType().getTypePtr()) >> 3;
5342193326Sed    Align = llvm::Log2_32(Align);
5343193326Sed    Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
5344193326Sed    // NOTE. Size of a bitfield does not match gcc's, because of the
5345193326Sed    // way bitfields are treated special in each. But I am told that
5346193326Sed    // 'size' for bitfield ivars is ignored by the runtime so it does
5347193326Sed    // not matter.  If it matters, there is enough info to get the
5348193326Sed    // bitfield right!
5349193326Sed    Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5350193326Sed    Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
5351193326Sed  }
5352193326Sed  // Return null for empty list.
5353193326Sed  if (Ivars.empty())
5354193326Sed    return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
5355193326Sed  std::vector<llvm::Constant*> Values(3);
5356193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
5357193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5358193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
5359193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
5360193326Sed                                             Ivars.size());
5361193326Sed  Values[2] = llvm::ConstantArray::get(AT, Ivars);
5362198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
5363193326Sed  const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5364193326Sed  llvm::GlobalVariable *GV =
5365198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
5366193326Sed                             llvm::GlobalValue::InternalLinkage,
5367193326Sed                             Init,
5368198398Srdivacky                             Prefix + OID->getName());
5369193326Sed  GV->setAlignment(
5370207619Srdivacky    CGM.getTargetData().getABITypeAlignment(Init->getType()));
5371193326Sed  GV->setSection("__DATA, __objc_const");
5372198092Srdivacky
5373198092Srdivacky  CGM.AddUsedGlobal(GV);
5374198092Srdivacky  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
5375193326Sed}
5376193326Sed
5377193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
5378198092Srdivacky  const ObjCProtocolDecl *PD) {
5379193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
5380198092Srdivacky
5381193326Sed  if (!Entry) {
5382193326Sed    // We use the initializer as a marker of whether this is a forward
5383193326Sed    // reference or not. At module finalization we add the empty
5384193326Sed    // contents for protocols which were referenced but never defined.
5385198092Srdivacky    Entry =
5386198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5387198092Srdivacky                               llvm::GlobalValue::ExternalLinkage,
5388198092Srdivacky                               0,
5389198398Srdivacky                               "\01l_OBJC_PROTOCOL_$_" + PD->getName());
5390193326Sed    Entry->setSection("__DATA,__datacoal_nt,coalesced");
5391193326Sed  }
5392198092Srdivacky
5393193326Sed  return Entry;
5394193326Sed}
5395193326Sed
5396193326Sed/// GetOrEmitProtocol - Generate the protocol meta-data:
5397193326Sed/// @code
5398193326Sed/// struct _protocol_t {
5399193326Sed///   id isa;  // NULL
5400193326Sed///   const char * const protocol_name;
5401193326Sed///   const struct _protocol_list_t * protocol_list; // super protocols
5402193326Sed///   const struct method_list_t * const instance_methods;
5403193326Sed///   const struct method_list_t * const class_methods;
5404193326Sed///   const struct method_list_t *optionalInstanceMethods;
5405193326Sed///   const struct method_list_t *optionalClassMethods;
5406193326Sed///   const struct _prop_list_t * properties;
5407193326Sed///   const uint32_t size;  // sizeof(struct _protocol_t)
5408193326Sed///   const uint32_t flags;  // = 0
5409193326Sed/// }
5410193326Sed/// @endcode
5411193326Sed///
5412193326Sed
5413193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
5414198092Srdivacky  const ObjCProtocolDecl *PD) {
5415193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
5416198092Srdivacky
5417193326Sed  // Early exit if a defining object has already been generated.
5418193326Sed  if (Entry && Entry->hasInitializer())
5419193326Sed    return Entry;
5420193326Sed
5421193326Sed  // Construct method lists.
5422193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5423193326Sed  std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
5424198092Srdivacky  for (ObjCProtocolDecl::instmeth_iterator
5425195341Sed         i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
5426193326Sed    ObjCMethodDecl *MD = *i;
5427193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
5428193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5429193326Sed      OptInstanceMethods.push_back(C);
5430193326Sed    } else {
5431193326Sed      InstanceMethods.push_back(C);
5432198092Srdivacky    }
5433193326Sed  }
5434198092Srdivacky
5435198092Srdivacky  for (ObjCProtocolDecl::classmeth_iterator
5436195341Sed         i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
5437193326Sed    ObjCMethodDecl *MD = *i;
5438193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
5439193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5440193326Sed      OptClassMethods.push_back(C);
5441193326Sed    } else {
5442193326Sed      ClassMethods.push_back(C);
5443198092Srdivacky    }
5444193326Sed  }
5445198092Srdivacky
5446193326Sed  std::vector<llvm::Constant*> Values(10);
5447193326Sed  // isa is NULL
5448193326Sed  Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
5449193326Sed  Values[1] = GetClassName(PD->getIdentifier());
5450198398Srdivacky  Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5451198398Srdivacky                               PD->protocol_begin(),
5452198398Srdivacky                               PD->protocol_end());
5453198092Srdivacky
5454193326Sed  Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
5455198398Srdivacky                             + PD->getName(),
5456193326Sed                             "__DATA, __objc_const",
5457193326Sed                             InstanceMethods);
5458198092Srdivacky  Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
5459198398Srdivacky                             + PD->getName(),
5460193326Sed                             "__DATA, __objc_const",
5461193326Sed                             ClassMethods);
5462193326Sed  Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
5463198398Srdivacky                             + PD->getName(),
5464193326Sed                             "__DATA, __objc_const",
5465193326Sed                             OptInstanceMethods);
5466198092Srdivacky  Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
5467198398Srdivacky                             + PD->getName(),
5468193326Sed                             "__DATA, __objc_const",
5469193326Sed                             OptClassMethods);
5470198398Srdivacky  Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
5471193326Sed                               0, PD, ObjCTypes);
5472198092Srdivacky  uint32_t Size =
5473193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
5474193326Sed  Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5475193326Sed  Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
5476193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
5477193326Sed                                                   Values);
5478198092Srdivacky
5479193326Sed  if (Entry) {
5480193326Sed    // Already created, fix the linkage and update the initializer.
5481193326Sed    Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
5482193326Sed    Entry->setInitializer(Init);
5483193326Sed  } else {
5484198092Srdivacky    Entry =
5485198398Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
5486198398Srdivacky                               false, llvm::GlobalValue::WeakAnyLinkage, Init,
5487198398Srdivacky                               "\01l_OBJC_PROTOCOL_$_" + PD->getName());
5488193326Sed    Entry->setAlignment(
5489207619Srdivacky      CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
5490193326Sed    Entry->setSection("__DATA,__datacoal_nt,coalesced");
5491193326Sed  }
5492193326Sed  Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
5493198092Srdivacky  CGM.AddUsedGlobal(Entry);
5494198092Srdivacky
5495193326Sed  // Use this protocol meta-data to build protocol list table in section
5496193326Sed  // __DATA, __objc_protolist
5497198398Srdivacky  llvm::GlobalVariable *PTGV =
5498198398Srdivacky    new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
5499198398Srdivacky                             false, llvm::GlobalValue::WeakAnyLinkage, Entry,
5500198398Srdivacky                             "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
5501193326Sed  PTGV->setAlignment(
5502207619Srdivacky    CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
5503193326Sed  PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
5504193326Sed  PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
5505198092Srdivacky  CGM.AddUsedGlobal(PTGV);
5506193326Sed  return Entry;
5507193326Sed}
5508193326Sed
5509193326Sed/// EmitProtocolList - Generate protocol list meta-data:
5510193326Sed/// @code
5511193326Sed/// struct _protocol_list_t {
5512193326Sed///   long protocol_count;   // Note, this is 32/64 bit
5513193326Sed///   struct _protocol_t[protocol_count];
5514193326Sed/// }
5515193326Sed/// @endcode
5516193326Sed///
5517193326Sedllvm::Constant *
5518198398SrdivackyCGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
5519198398Srdivacky                                      ObjCProtocolDecl::protocol_iterator begin,
5520198398Srdivacky                                      ObjCProtocolDecl::protocol_iterator end) {
5521193326Sed  std::vector<llvm::Constant*> ProtocolRefs;
5522198092Srdivacky
5523193326Sed  // Just return null for empty protocol lists
5524198092Srdivacky  if (begin == end)
5525193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5526198092Srdivacky
5527193326Sed  // FIXME: We shouldn't need to do this lookup here, should we?
5528198398Srdivacky  llvm::SmallString<256> TmpName;
5529198398Srdivacky  Name.toVector(TmpName);
5530198398Srdivacky  llvm::GlobalVariable *GV =
5531198398Srdivacky    CGM.getModule().getGlobalVariable(TmpName.str(), true);
5532193326Sed  if (GV)
5533198398Srdivacky    return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
5534198092Srdivacky
5535193326Sed  for (; begin != end; ++begin)
5536193326Sed    ProtocolRefs.push_back(GetProtocolRef(*begin));  // Implemented???
5537193326Sed
5538193326Sed  // This list is null terminated.
5539193326Sed  ProtocolRefs.push_back(llvm::Constant::getNullValue(
5540198092Srdivacky                           ObjCTypes.ProtocolnfABIPtrTy));
5541198092Srdivacky
5542193326Sed  std::vector<llvm::Constant*> Values(2);
5543198092Srdivacky  Values[0] =
5544198092Srdivacky    llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
5545198092Srdivacky  Values[1] =
5546198092Srdivacky    llvm::ConstantArray::get(
5547198092Srdivacky      llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
5548198092Srdivacky                           ProtocolRefs.size()),
5549198092Srdivacky      ProtocolRefs);
5550198092Srdivacky
5551198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
5552198092Srdivacky  GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
5553193326Sed                                llvm::GlobalValue::InternalLinkage,
5554193326Sed                                Init,
5555198092Srdivacky                                Name);
5556193326Sed  GV->setSection("__DATA, __objc_const");
5557193326Sed  GV->setAlignment(
5558207619Srdivacky    CGM.getTargetData().getABITypeAlignment(Init->getType()));
5559198092Srdivacky  CGM.AddUsedGlobal(GV);
5560198092Srdivacky  return llvm::ConstantExpr::getBitCast(GV,
5561193326Sed                                        ObjCTypes.ProtocolListnfABIPtrTy);
5562193326Sed}
5563193326Sed
5564193326Sed/// GetMethodDescriptionConstant - This routine build following meta-data:
5565193326Sed/// struct _objc_method {
5566193326Sed///   SEL _cmd;
5567193326Sed///   char *method_type;
5568193326Sed///   char *_imp;
5569193326Sed/// }
5570193326Sed
5571193326Sedllvm::Constant *
5572193326SedCGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
5573193326Sed  std::vector<llvm::Constant*> Desc(3);
5574198092Srdivacky  Desc[0] =
5575198092Srdivacky    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5576198092Srdivacky                                   ObjCTypes.SelectorPtrTy);
5577193326Sed  Desc[1] = GetMethodVarType(MD);
5578193326Sed  // Protocol methods have no implementation. So, this entry is always NULL.
5579193326Sed  Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5580193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
5581193326Sed}
5582193326Sed
5583193326Sed/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
5584193326Sed/// This code gen. amounts to generating code for:
5585193326Sed/// @code
5586193326Sed/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
5587193326Sed/// @encode
5588198092Srdivacky///
5589193326SedLValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
5590208600Srdivacky                                               CodeGen::CodeGenFunction &CGF,
5591208600Srdivacky                                               QualType ObjectTy,
5592208600Srdivacky                                               llvm::Value *BaseValue,
5593208600Srdivacky                                               const ObjCIvarDecl *Ivar,
5594208600Srdivacky                                               unsigned CVRQualifiers) {
5595208600Srdivacky  ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
5596193326Sed  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5597193326Sed                                  EmitIvarOffset(CGF, ID, Ivar));
5598193326Sed}
5599193326Sed
5600193326Sedllvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
5601198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5602198092Srdivacky  const ObjCInterfaceDecl *Interface,
5603198092Srdivacky  const ObjCIvarDecl *Ivar) {
5604199990Srdivacky  return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
5605193326Sed}
5606193326Sed
5607193326SedCodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
5608198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5609208600Srdivacky  ReturnValueSlot Return,
5610198092Srdivacky  QualType ResultType,
5611198092Srdivacky  Selector Sel,
5612198092Srdivacky  llvm::Value *Receiver,
5613198092Srdivacky  QualType Arg0Ty,
5614198092Srdivacky  bool IsSuper,
5615198092Srdivacky  const CallArgList &CallArgs) {
5616193326Sed  // FIXME. Even though IsSuper is passes. This function doese not handle calls
5617193326Sed  // to 'super' receivers.
5618193326Sed  CodeGenTypes &Types = CGM.getTypes();
5619193326Sed  llvm::Value *Arg0 = Receiver;
5620193326Sed  if (!IsSuper)
5621193326Sed    Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
5622198092Srdivacky
5623193326Sed  // Find the message function name.
5624193326Sed  // FIXME. This is too much work to get the ABI-specific result type needed to
5625193326Sed  // find the message name.
5626204643Srdivacky  const CGFunctionInfo &FnInfo
5627206084Srdivacky      = Types.getFunctionInfo(ResultType, CallArgList(),
5628206084Srdivacky                              FunctionType::ExtInfo());
5629193326Sed  llvm::Constant *Fn = 0;
5630193326Sed  std::string Name("\01l_");
5631210299Sed  if (CGM.ReturnTypeUsesSRet(FnInfo)) {
5632212904Sdim    if (IsSuper) {
5633212904Sdim      Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
5634212904Sdim      Name += "objc_msgSendSuper2_stret_fixup";
5635212904Sdim    } else {
5636212904Sdim      Fn = ObjCTypes.getMessageSendStretFixupFn();
5637212904Sdim      Name += "objc_msgSend_stret_fixup";
5638212904Sdim    }
5639210299Sed  } else if (!IsSuper && CGM.ReturnTypeUsesFPRet(ResultType)) {
5640210299Sed    Fn = ObjCTypes.getMessageSendFpretFixupFn();
5641210299Sed    Name += "objc_msgSend_fpret_fixup";
5642198092Srdivacky  } else {
5643212904Sdim    if (IsSuper) {
5644212904Sdim      Fn = ObjCTypes.getMessageSendSuper2FixupFn();
5645212904Sdim      Name += "objc_msgSendSuper2_fixup";
5646212904Sdim    } else {
5647212904Sdim      Fn = ObjCTypes.getMessageSendFixupFn();
5648212904Sdim      Name += "objc_msgSend_fixup";
5649212904Sdim    }
5650193326Sed  }
5651193326Sed  assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend");
5652193326Sed  Name += '_';
5653193326Sed  std::string SelName(Sel.getAsString());
5654193326Sed  // Replace all ':' in selector name with '_'  ouch!
5655198092Srdivacky  for (unsigned i = 0; i < SelName.size(); i++)
5656193326Sed    if (SelName[i] == ':')
5657193326Sed      SelName[i] = '_';
5658193326Sed  Name += SelName;
5659193326Sed  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5660193326Sed  if (!GV) {
5661193326Sed    // Build message ref table entry.
5662193326Sed    std::vector<llvm::Constant*> Values(2);
5663193326Sed    Values[0] = Fn;
5664193326Sed    Values[1] = GetMethodVarName(Sel);
5665198092Srdivacky    llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
5666198092Srdivacky    GV =  new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
5667193326Sed                                   llvm::GlobalValue::WeakAnyLinkage,
5668193326Sed                                   Init,
5669198092Srdivacky                                   Name);
5670193326Sed    GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
5671193326Sed    GV->setAlignment(16);
5672193326Sed    GV->setSection("__DATA, __objc_msgrefs, coalesced");
5673193326Sed  }
5674193326Sed  llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy);
5675198092Srdivacky
5676193326Sed  CallArgList ActualArgs;
5677193326Sed  ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
5678198092Srdivacky  ActualArgs.push_back(std::make_pair(RValue::get(Arg1),
5679193326Sed                                      ObjCTypes.MessageRefCPtrTy));
5680193326Sed  ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
5681203955Srdivacky  const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs,
5682206084Srdivacky                                                      FunctionType::ExtInfo());
5683193326Sed  llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0);
5684193326Sed  Callee = CGF.Builder.CreateLoad(Callee);
5685193326Sed  const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true);
5686193326Sed  Callee = CGF.Builder.CreateBitCast(Callee,
5687193326Sed                                     llvm::PointerType::getUnqual(FTy));
5688208600Srdivacky  return CGF.EmitCall(FnInfo1, Callee, Return, ActualArgs);
5689193326Sed}
5690193326Sed
5691193326Sed/// Generate code for a message send expression in the nonfragile abi.
5692198092SrdivackyCodeGen::RValue
5693198092SrdivackyCGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
5694208600Srdivacky                                            ReturnValueSlot Return,
5695198092Srdivacky                                            QualType ResultType,
5696198092Srdivacky                                            Selector Sel,
5697198092Srdivacky                                            llvm::Value *Receiver,
5698198092Srdivacky                                            const CallArgList &CallArgs,
5699207619Srdivacky                                            const ObjCInterfaceDecl *Class,
5700198092Srdivacky                                            const ObjCMethodDecl *Method) {
5701193326Sed  return LegacyDispatchedSelector(Sel)
5702208600Srdivacky    ? EmitLegacyMessageSend(CGF, Return, ResultType,
5703208600Srdivacky                            EmitSelector(CGF.Builder, Sel),
5704198092Srdivacky                            Receiver, CGF.getContext().getObjCIdType(),
5705198092Srdivacky                            false, CallArgs, Method, ObjCTypes)
5706208600Srdivacky    : EmitMessageSend(CGF, Return, ResultType, Sel,
5707198092Srdivacky                      Receiver, CGF.getContext().getObjCIdType(),
5708198092Srdivacky                      false, CallArgs);
5709193326Sed}
5710193326Sed
5711193326Sedllvm::GlobalVariable *
5712193326SedCGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
5713193326Sed  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5714193326Sed
5715193326Sed  if (!GV) {
5716198092Srdivacky    GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
5717198092Srdivacky                                  false, llvm::GlobalValue::ExternalLinkage,
5718198092Srdivacky                                  0, Name);
5719193326Sed  }
5720193326Sed
5721193326Sed  return GV;
5722193326Sed}
5723193326Sed
5724198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5725198092Srdivacky                                                  const ObjCInterfaceDecl *ID) {
5726193326Sed  llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
5727198092Srdivacky
5728193326Sed  if (!Entry) {
5729193326Sed    std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5730193326Sed    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5731198092Srdivacky    Entry =
5732198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
5733198092Srdivacky                               false, llvm::GlobalValue::InternalLinkage,
5734198092Srdivacky                               ClassGV,
5735198092Srdivacky                               "\01L_OBJC_CLASSLIST_REFERENCES_$_");
5736193326Sed    Entry->setAlignment(
5737207619Srdivacky      CGM.getTargetData().getABITypeAlignment(
5738198092Srdivacky        ObjCTypes.ClassnfABIPtrTy));
5739193326Sed    Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
5740198092Srdivacky    CGM.AddUsedGlobal(Entry);
5741193326Sed  }
5742198092Srdivacky
5743199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
5744193326Sed}
5745193326Sed
5746193326Sedllvm::Value *
5747198092SrdivackyCGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
5748193326Sed                                          const ObjCInterfaceDecl *ID) {
5749193326Sed  llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
5750198092Srdivacky
5751193326Sed  if (!Entry) {
5752193326Sed    std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5753193326Sed    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5754198092Srdivacky    Entry =
5755198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
5756198092Srdivacky                               false, llvm::GlobalValue::InternalLinkage,
5757198092Srdivacky                               ClassGV,
5758198092Srdivacky                               "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
5759193326Sed    Entry->setAlignment(
5760207619Srdivacky      CGM.getTargetData().getABITypeAlignment(
5761198092Srdivacky        ObjCTypes.ClassnfABIPtrTy));
5762193326Sed    Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
5763198092Srdivacky    CGM.AddUsedGlobal(Entry);
5764193326Sed  }
5765198092Srdivacky
5766199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
5767193326Sed}
5768193326Sed
5769193326Sed/// EmitMetaClassRef - Return a Value * of the address of _class_t
5770193326Sed/// meta-data
5771193326Sed///
5772198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5773198092Srdivacky                                                      const ObjCInterfaceDecl *ID) {
5774193326Sed  llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5775193326Sed  if (Entry)
5776199990Srdivacky    return Builder.CreateLoad(Entry, "tmp");
5777198092Srdivacky
5778193326Sed  std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
5779193326Sed  llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
5780198092Srdivacky  Entry =
5781198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
5782193326Sed                             llvm::GlobalValue::InternalLinkage,
5783198092Srdivacky                             MetaClassGV,
5784198092Srdivacky                             "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
5785193326Sed  Entry->setAlignment(
5786207619Srdivacky    CGM.getTargetData().getABITypeAlignment(
5787198092Srdivacky      ObjCTypes.ClassnfABIPtrTy));
5788198092Srdivacky
5789193326Sed  Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
5790198092Srdivacky  CGM.AddUsedGlobal(Entry);
5791198092Srdivacky
5792199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
5793193326Sed}
5794193326Sed
5795193326Sed/// GetClass - Return a reference to the class for the given interface
5796193326Sed/// decl.
5797193326Sedllvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
5798193326Sed                                              const ObjCInterfaceDecl *ID) {
5799199482Srdivacky  if (ID->hasAttr<WeakImportAttr>()) {
5800199482Srdivacky    std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5801199482Srdivacky    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5802199482Srdivacky    ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5803199482Srdivacky  }
5804199482Srdivacky
5805193326Sed  return EmitClassRef(Builder, ID);
5806193326Sed}
5807193326Sed
5808193326Sed/// Generates a message send where the super is the receiver.  This is
5809193326Sed/// a message send to self with special delivery semantics indicating
5810193326Sed/// which class's method should be called.
5811193326SedCodeGen::RValue
5812193326SedCGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
5813208600Srdivacky                                                 ReturnValueSlot Return,
5814198092Srdivacky                                                 QualType ResultType,
5815198092Srdivacky                                                 Selector Sel,
5816198092Srdivacky                                                 const ObjCInterfaceDecl *Class,
5817198092Srdivacky                                                 bool isCategoryImpl,
5818198092Srdivacky                                                 llvm::Value *Receiver,
5819198092Srdivacky                                                 bool IsClassMessage,
5820198092Srdivacky                                                 const CodeGen::CallArgList &CallArgs,
5821198092Srdivacky                                                 const ObjCMethodDecl *Method) {
5822193326Sed  // ...
5823193326Sed  // Create and init a super structure; this is a (receiver, class)
5824193326Sed  // pair we will pass to objc_msgSendSuper.
5825193326Sed  llvm::Value *ObjCSuper =
5826193326Sed    CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
5827198092Srdivacky
5828193326Sed  llvm::Value *ReceiverAsObject =
5829193326Sed    CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
5830193326Sed  CGF.Builder.CreateStore(ReceiverAsObject,
5831193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 0));
5832198092Srdivacky
5833193326Sed  // If this is a class message the metaclass is passed as the target.
5834193326Sed  llvm::Value *Target;
5835193326Sed  if (IsClassMessage) {
5836193326Sed    if (isCategoryImpl) {
5837193326Sed      // Message sent to "super' in a class method defined in
5838193326Sed      // a category implementation.
5839193326Sed      Target = EmitClassRef(CGF.Builder, Class);
5840193326Sed      Target = CGF.Builder.CreateStructGEP(Target, 0);
5841193326Sed      Target = CGF.Builder.CreateLoad(Target);
5842198092Srdivacky    } else
5843193326Sed      Target = EmitMetaClassRef(CGF.Builder, Class);
5844198092Srdivacky  } else
5845193326Sed    Target = EmitSuperClassRef(CGF.Builder, Class);
5846198092Srdivacky
5847193326Sed  // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5848193326Sed  // ObjCTypes types.
5849193326Sed  const llvm::Type *ClassTy =
5850193326Sed    CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
5851193326Sed  Target = CGF.Builder.CreateBitCast(Target, ClassTy);
5852193326Sed  CGF.Builder.CreateStore(Target,
5853193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 1));
5854198092Srdivacky
5855193326Sed  return (LegacyDispatchedSelector(Sel))
5856208600Srdivacky    ? EmitLegacyMessageSend(CGF, Return, ResultType,
5857208600Srdivacky                            EmitSelector(CGF.Builder, Sel),
5858198092Srdivacky                            ObjCSuper, ObjCTypes.SuperPtrCTy,
5859198092Srdivacky                            true, CallArgs, Method, ObjCTypes)
5860208600Srdivacky    : EmitMessageSend(CGF, Return, ResultType, Sel,
5861198092Srdivacky                      ObjCSuper, ObjCTypes.SuperPtrCTy,
5862198092Srdivacky                      true, CallArgs);
5863193326Sed}
5864193326Sed
5865198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
5866210299Sed                                                  Selector Sel, bool lval) {
5867193326Sed  llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5868198092Srdivacky
5869193326Sed  if (!Entry) {
5870198092Srdivacky    llvm::Constant *Casted =
5871198092Srdivacky      llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
5872198092Srdivacky                                     ObjCTypes.SelectorPtrTy);
5873198092Srdivacky    Entry =
5874198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
5875198092Srdivacky                               llvm::GlobalValue::InternalLinkage,
5876198092Srdivacky                               Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
5877193326Sed    Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
5878198092Srdivacky    CGM.AddUsedGlobal(Entry);
5879193326Sed  }
5880198092Srdivacky
5881210299Sed  if (lval)
5882210299Sed    return Entry;
5883199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
5884193326Sed}
5885193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
5886198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
5887193326Sed///
5888193326Sedvoid CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
5889198092Srdivacky                                                llvm::Value *src,
5890198092Srdivacky                                                llvm::Value *dst,
5891198092Srdivacky                                                llvm::Value *ivarOffset) {
5892193326Sed  const llvm::Type * SrcTy = src->getType();
5893193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5894193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5895193326Sed    assert(Size <= 8 && "does not support size > 8");
5896193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5897193326Sed           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5898193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5899193326Sed  }
5900193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5901193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5902198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5903198092Srdivacky                          src, dst, ivarOffset);
5904193326Sed  return;
5905193326Sed}
5906193326Sed
5907193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5908193326Sed/// objc_assign_strongCast (id src, id *dst)
5909193326Sed///
5910193326Sedvoid CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
5911198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5912198092Srdivacky  llvm::Value *src, llvm::Value *dst) {
5913193326Sed  const llvm::Type * SrcTy = src->getType();
5914193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5915193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5916193326Sed    assert(Size <= 8 && "does not support size > 8");
5917193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5918198092Srdivacky           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5919193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5920193326Sed  }
5921193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5922193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5923193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
5924193326Sed                          src, dst, "weakassign");
5925193326Sed  return;
5926193326Sed}
5927193326Sed
5928198092Srdivackyvoid CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
5929198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5930198092Srdivacky  llvm::Value *DestPtr,
5931198092Srdivacky  llvm::Value *SrcPtr,
5932210299Sed  llvm::Value *Size) {
5933198092Srdivacky  SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5934198092Srdivacky  DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
5935198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
5936210299Sed                          DestPtr, SrcPtr, Size);
5937198092Srdivacky  return;
5938198092Srdivacky}
5939198092Srdivacky
5940193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak
5941193326Sed/// object: objc_read_weak (id *src)
5942193326Sed///
5943193326Sedllvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
5944198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5945198092Srdivacky  llvm::Value *AddrWeakObj) {
5946193326Sed  const llvm::Type* DestTy =
5947198092Srdivacky    cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5948198092Srdivacky  AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
5949193326Sed  llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
5950193326Sed                                                  AddrWeakObj, "weakread");
5951193326Sed  read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
5952193326Sed  return read_weak;
5953193326Sed}
5954193326Sed
5955193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
5956193326Sed/// objc_assign_weak (id src, id *dst)
5957193326Sed///
5958193326Sedvoid CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
5959198092Srdivacky                                                llvm::Value *src, llvm::Value *dst) {
5960193326Sed  const llvm::Type * SrcTy = src->getType();
5961193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5962193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5963193326Sed    assert(Size <= 8 && "does not support size > 8");
5964193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5965193326Sed           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5966193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5967193326Sed  }
5968193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5969193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5970193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
5971193326Sed                          src, dst, "weakassign");
5972193326Sed  return;
5973193326Sed}
5974193326Sed
5975193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
5976193326Sed/// objc_assign_global (id src, id *dst)
5977193326Sed///
5978193326Sedvoid CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
5979212904Sdim                                          llvm::Value *src, llvm::Value *dst,
5980212904Sdim                                          bool threadlocal) {
5981193326Sed  const llvm::Type * SrcTy = src->getType();
5982193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5983193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5984193326Sed    assert(Size <= 8 && "does not support size > 8");
5985193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5986193326Sed           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5987193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5988193326Sed  }
5989193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5990193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5991212904Sdim  if (!threadlocal)
5992212904Sdim    CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
5993212904Sdim                            src, dst, "globalassign");
5994212904Sdim  else
5995212904Sdim    CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
5996212904Sdim                            src, dst, "threadlocalassign");
5997193326Sed  return;
5998193326Sed}
5999193326Sed
6000212904Sdimnamespace {
6001212904Sdim  struct CallSyncExit : EHScopeStack::Cleanup {
6002212904Sdim    llvm::Value *SyncExitFn;
6003212904Sdim    llvm::Value *SyncArg;
6004212904Sdim    CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg)
6005212904Sdim      : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {}
6006212904Sdim
6007212904Sdim    void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
6008212904Sdim      CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow();
6009212904Sdim    }
6010212904Sdim  };
6011212904Sdim}
6012212904Sdim
6013198092Srdivackyvoid
6014210299SedCGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6015210299Sed                                             const ObjCAtSynchronizedStmt &S) {
6016210299Sed  // Evaluate the lock operand.  This should dominate the cleanup.
6017210299Sed  llvm::Value *SyncArg = CGF.EmitScalarExpr(S.getSynchExpr());
6018193326Sed
6019210299Sed  // Acquire the lock.
6020210299Sed  SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
6021210299Sed  CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
6022210299Sed    ->setDoesNotThrow();
6023210299Sed
6024210299Sed  // Register an all-paths cleanup to release the lock.
6025212904Sdim  CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup,
6026212904Sdim                                        ObjCTypes.getSyncExitFn(),
6027212904Sdim                                        SyncArg);
6028210299Sed
6029210299Sed  // Emit the body of the statement.
6030210299Sed  CGF.EmitStmt(S.getSynchBody());
6031193326Sed
6032210299Sed  // Pop the lock-release cleanup.
6033210299Sed  CGF.PopCleanupBlock();
6034210299Sed}
6035193326Sed
6036210299Sednamespace {
6037210299Sed  struct CatchHandler {
6038210299Sed    const VarDecl *Variable;
6039210299Sed    const Stmt *Body;
6040210299Sed    llvm::BasicBlock *Block;
6041210299Sed    llvm::Value *TypeInfo;
6042210299Sed  };
6043198092Srdivacky
6044212904Sdim  struct CallObjCEndCatch : EHScopeStack::Cleanup {
6045210299Sed    CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) :
6046210299Sed      MightThrow(MightThrow), Fn(Fn) {}
6047210299Sed    bool MightThrow;
6048210299Sed    llvm::Value *Fn;
6049193326Sed
6050210299Sed    void Emit(CodeGenFunction &CGF, bool IsForEH) {
6051210299Sed      if (!MightThrow) {
6052210299Sed        CGF.Builder.CreateCall(Fn)->setDoesNotThrow();
6053210299Sed        return;
6054210299Sed      }
6055193326Sed
6056210299Sed      CGF.EmitCallOrInvoke(Fn, 0, 0);
6057210299Sed    }
6058210299Sed  };
6059210299Sed}
6060193326Sed
6061212904Sdimllvm::Constant *
6062212904SdimCGObjCNonFragileABIMac::GetEHType(QualType T) {
6063212904Sdim  // There's a particular fixed type info for 'id'.
6064212904Sdim  if (T->isObjCIdType() ||
6065212904Sdim      T->isObjCQualifiedIdType()) {
6066212904Sdim    llvm::Constant *IDEHType =
6067212904Sdim      CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6068212904Sdim    if (!IDEHType)
6069212904Sdim      IDEHType =
6070212904Sdim        new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6071212904Sdim                                 false,
6072212904Sdim                                 llvm::GlobalValue::ExternalLinkage,
6073212904Sdim                                 0, "OBJC_EHTYPE_id");
6074212904Sdim    return IDEHType;
6075212904Sdim  }
6076212904Sdim
6077212904Sdim  // All other types should be Objective-C interface pointer types.
6078212904Sdim  const ObjCObjectPointerType *PT =
6079212904Sdim    T->getAs<ObjCObjectPointerType>();
6080212904Sdim  assert(PT && "Invalid @catch type.");
6081212904Sdim  const ObjCInterfaceType *IT = PT->getInterfaceType();
6082212904Sdim  assert(IT && "Invalid @catch type.");
6083212904Sdim  return GetInterfaceEHType(IT->getDecl(), false);
6084212904Sdim}
6085212904Sdim
6086210299Sedvoid CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6087210299Sed                                         const ObjCAtTryStmt &S) {
6088210299Sed  // Jump destination for falling out of catch bodies.
6089210299Sed  CodeGenFunction::JumpDest Cont;
6090210299Sed  if (S.getNumCatchStmts())
6091210299Sed    Cont = CGF.getJumpDestInCurrentScope("eh.cont");
6092193326Sed
6093210299Sed  CodeGenFunction::FinallyInfo FinallyInfo;
6094210299Sed  if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
6095210299Sed    FinallyInfo = CGF.EnterFinallyBlock(Finally->getFinallyBody(),
6096210299Sed                                        ObjCTypes.getObjCBeginCatchFn(),
6097210299Sed                                        ObjCTypes.getObjCEndCatchFn(),
6098210299Sed                                        ObjCTypes.getExceptionRethrowFn());
6099210299Sed
6100210299Sed  llvm::SmallVector<CatchHandler, 8> Handlers;
6101210299Sed
6102210299Sed  // Enter the catch, if there is one.
6103210299Sed  if (S.getNumCatchStmts()) {
6104210299Sed    for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) {
6105210299Sed      const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I);
6106207619Srdivacky      const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
6107193326Sed
6108210299Sed      Handlers.push_back(CatchHandler());
6109210299Sed      CatchHandler &Handler = Handlers.back();
6110210299Sed      Handler.Variable = CatchDecl;
6111210299Sed      Handler.Body = CatchStmt->getCatchBody();
6112210299Sed      Handler.Block = CGF.createBasicBlock("catch");
6113210299Sed
6114210299Sed      // @catch(...) always matches.
6115207619Srdivacky      if (!CatchDecl) {
6116210299Sed        Handler.TypeInfo = 0; // catch-all
6117210299Sed        // Don't consider any other catches.
6118207619Srdivacky        break;
6119207619Srdivacky      }
6120193326Sed
6121212904Sdim      Handler.TypeInfo = GetEHType(CatchDecl->getType());
6122193326Sed    }
6123193326Sed
6124210299Sed    EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
6125210299Sed    for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
6126210299Sed      Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block);
6127193326Sed  }
6128210299Sed
6129210299Sed  // Emit the try body.
6130210299Sed  CGF.EmitStmt(S.getTryBody());
6131198092Srdivacky
6132210299Sed  // Leave the try.
6133210299Sed  if (S.getNumCatchStmts())
6134210299Sed    CGF.EHStack.popCatch();
6135193326Sed
6136210299Sed  // Remember where we were.
6137210299Sed  CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
6138193326Sed
6139210299Sed  // Emit the handlers.
6140210299Sed  for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
6141210299Sed    CatchHandler &Handler = Handlers[I];
6142193326Sed
6143210299Sed    CGF.EmitBlock(Handler.Block);
6144210299Sed    llvm::Value *RawExn = CGF.Builder.CreateLoad(CGF.getExceptionSlot());
6145193326Sed
6146210299Sed    // Enter the catch.
6147210299Sed    llvm::CallInst *Exn =
6148210299Sed      CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), RawExn,
6149210299Sed                             "exn.adjusted");
6150210299Sed    Exn->setDoesNotThrow();
6151198092Srdivacky
6152210299Sed    // Add a cleanup to leave the catch.
6153210299Sed    bool EndCatchMightThrow = (Handler.Variable == 0);
6154212904Sdim    CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup,
6155212904Sdim                                              EndCatchMightThrow,
6156212904Sdim                                              ObjCTypes.getObjCEndCatchFn());
6157193326Sed
6158210299Sed    // Bind the catch parameter if it exists.
6159210299Sed    if (const VarDecl *CatchParam = Handler.Variable) {
6160210299Sed      const llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType());
6161210299Sed      llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType);
6162198092Srdivacky
6163218893Sdim      CGF.EmitAutoVarDecl(*CatchParam);
6164210299Sed      CGF.Builder.CreateStore(CastExn, CGF.GetAddrOfLocalVar(CatchParam));
6165193326Sed    }
6166193326Sed
6167210299Sed    CGF.ObjCEHValueStack.push_back(Exn);
6168210299Sed    CGF.EmitStmt(Handler.Body);
6169210299Sed    CGF.ObjCEHValueStack.pop_back();
6170193326Sed
6171210299Sed    // Leave the earlier cleanup.
6172210299Sed    CGF.PopCleanupBlock();
6173193326Sed
6174210299Sed    CGF.EmitBranchThroughCleanup(Cont);
6175210299Sed  }
6176193326Sed
6177210299Sed  // Go back to the try-statement fallthrough.
6178210299Sed  CGF.Builder.restoreIP(SavedIP);
6179193326Sed
6180210299Sed  // Pop out of the normal cleanup on the finally.
6181210299Sed  if (S.getFinallyStmt())
6182210299Sed    CGF.ExitFinallyBlock(FinallyInfo);
6183193326Sed
6184212904Sdim  if (Cont.isValid())
6185212904Sdim    CGF.EmitBlock(Cont.getBlock());
6186193326Sed}
6187193326Sed
6188193326Sed/// EmitThrowStmt - Generate code for a throw statement.
6189193326Sedvoid CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6190193326Sed                                           const ObjCAtThrowStmt &S) {
6191193326Sed  if (const Expr *ThrowExpr = S.getThrowExpr()) {
6192218893Sdim    llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
6193218893Sdim    Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy,
6194218893Sdim                                          "tmp");
6195218893Sdim    llvm::Value *Args[] = { Exception };
6196218893Sdim    CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(),
6197218893Sdim                         Args, Args+1)
6198218893Sdim      .setDoesNotReturn();
6199193326Sed  } else {
6200218893Sdim    CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn(), 0, 0)
6201218893Sdim      .setDoesNotReturn();
6202193326Sed  }
6203193326Sed
6204218893Sdim  CGF.Builder.CreateUnreachable();
6205193326Sed  CGF.Builder.ClearInsertionPoint();
6206193326Sed}
6207193326Sed
6208212904Sdimllvm::Constant *
6209198092SrdivackyCGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
6210193326Sed                                           bool ForDefinition) {
6211193326Sed  llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
6212193326Sed
6213193326Sed  // If we don't need a definition, return the entry if found or check
6214193326Sed  // if we use an external reference.
6215193326Sed  if (!ForDefinition) {
6216193326Sed    if (Entry)
6217193326Sed      return Entry;
6218193326Sed
6219193326Sed    // If this type (or a super class) has the __objc_exception__
6220193326Sed    // attribute, emit an external reference.
6221194613Sed    if (hasObjCExceptionAttribute(CGM.getContext(), ID))
6222198092Srdivacky      return Entry =
6223198092Srdivacky        new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
6224193326Sed                                 llvm::GlobalValue::ExternalLinkage,
6225198092Srdivacky                                 0,
6226198398Srdivacky                                 ("OBJC_EHTYPE_$_" +
6227198092Srdivacky                                  ID->getIdentifier()->getName()));
6228193326Sed  }
6229198092Srdivacky
6230193326Sed  // Otherwise we need to either make a new entry or fill in the
6231193326Sed  // initializer.
6232193326Sed  assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
6233193326Sed  std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6234193326Sed  std::string VTableName = "objc_ehtype_vtable";
6235198092Srdivacky  llvm::GlobalVariable *VTableGV =
6236193326Sed    CGM.getModule().getGlobalVariable(VTableName);
6237193326Sed  if (!VTableGV)
6238198092Srdivacky    VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6239198092Srdivacky                                        false,
6240193326Sed                                        llvm::GlobalValue::ExternalLinkage,
6241198092Srdivacky                                        0, VTableName);
6242193326Sed
6243210299Sed  llvm::Value *VTableIdx =
6244210299Sed    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
6245193326Sed
6246193326Sed  std::vector<llvm::Constant*> Values(3);
6247193326Sed  Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
6248193326Sed  Values[1] = GetClassName(ID->getIdentifier());
6249193326Sed  Values[2] = GetClassGlobal(ClassName);
6250198092Srdivacky  llvm::Constant *Init =
6251198092Srdivacky    llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
6252193326Sed
6253193326Sed  if (Entry) {
6254193326Sed    Entry->setInitializer(Init);
6255193326Sed  } else {
6256198092Srdivacky    Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
6257193326Sed                                     llvm::GlobalValue::WeakAnyLinkage,
6258198092Srdivacky                                     Init,
6259198398Srdivacky                                     ("OBJC_EHTYPE_$_" +
6260198092Srdivacky                                      ID->getIdentifier()->getName()));
6261193326Sed  }
6262193326Sed
6263218893Sdim  if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
6264193326Sed    Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
6265207619Srdivacky  Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
6266207619Srdivacky      ObjCTypes.EHTypeTy));
6267193326Sed
6268193326Sed  if (ForDefinition) {
6269193326Sed    Entry->setSection("__DATA,__objc_const");
6270193326Sed    Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6271193326Sed  } else {
6272193326Sed    Entry->setSection("__DATA,__datacoal_nt,coalesced");
6273193326Sed  }
6274193326Sed
6275193326Sed  return Entry;
6276193326Sed}
6277198092Srdivacky
6278193326Sed/* *** */
6279193326Sed
6280193326SedCodeGen::CGObjCRuntime *
6281193326SedCodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
6282193326Sed  return new CGObjCMac(CGM);
6283193326Sed}
6284193326Sed
6285193326SedCodeGen::CGObjCRuntime *
6286193326SedCodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) {
6287193326Sed  return new CGObjCNonFragileABIMac(CGM);
6288193326Sed}
6289