CGObjCMac.cpp revision 203955
1193326Sed//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed// This provides Objective-C code generation targetting the Apple runtime.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#include "CGObjCRuntime.h"
15193326Sed
16193326Sed#include "CodeGenModule.h"
17193326Sed#include "CodeGenFunction.h"
18193326Sed#include "clang/AST/ASTContext.h"
19193326Sed#include "clang/AST/Decl.h"
20193326Sed#include "clang/AST/DeclObjC.h"
21193326Sed#include "clang/AST/RecordLayout.h"
22193326Sed#include "clang/AST/StmtObjC.h"
23193326Sed#include "clang/Basic/LangOptions.h"
24203955Srdivacky#include "clang/CodeGen/CodeGenOptions.h"
25193326Sed
26193326Sed#include "llvm/Intrinsics.h"
27198092Srdivacky#include "llvm/LLVMContext.h"
28193326Sed#include "llvm/Module.h"
29193326Sed#include "llvm/ADT/DenseSet.h"
30198092Srdivacky#include "llvm/ADT/SetVector.h"
31198092Srdivacky#include "llvm/ADT/SmallString.h"
32200583Srdivacky#include "llvm/ADT/SmallPtrSet.h"
33198092Srdivacky#include "llvm/Support/raw_ostream.h"
34193326Sed#include "llvm/Target/TargetData.h"
35198092Srdivacky#include <cstdio>
36193326Sed
37193326Sedusing namespace clang;
38193326Sedusing namespace CodeGen;
39193326Sed
40193326Sed// Common CGObjCRuntime functions, these don't belong here, but they
41193326Sed// don't belong in CGObjCRuntime either so we will live with it for
42193326Sed// now.
43193326Sed
44198092Srdivacky/// FindIvarInterface - Find the interface containing the ivar.
45193326Sed///
46193326Sed/// FIXME: We shouldn't need to do this, the containing context should
47193326Sed/// be fixed.
48193326Sedstatic const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
49193326Sed                                                  const ObjCInterfaceDecl *OID,
50193326Sed                                                  const ObjCIvarDecl *OIVD,
51193326Sed                                                  unsigned &Index) {
52193326Sed  // FIXME: The index here is closely tied to how
53193326Sed  // ASTContext::getObjCLayout is implemented. This should be fixed to
54193326Sed  // get the information from the layout directly.
55193326Sed  Index = 0;
56193326Sed  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
57193576Sed  Context.ShallowCollectObjCIvars(OID, Ivars);
58193326Sed  for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
59193326Sed    if (OIVD == Ivars[k])
60193326Sed      return OID;
61193326Sed    ++Index;
62193326Sed  }
63198092Srdivacky
64193326Sed  // Otherwise check in the super class.
65193326Sed  if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
66193326Sed    return FindIvarInterface(Context, Super, OIVD, Index);
67198092Srdivacky
68193326Sed  return 0;
69193326Sed}
70193326Sed
71193326Sedstatic uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
72193326Sed                                     const ObjCInterfaceDecl *OID,
73193326Sed                                     const ObjCImplementationDecl *ID,
74193326Sed                                     const ObjCIvarDecl *Ivar) {
75193326Sed  unsigned Index;
76198092Srdivacky  const ObjCInterfaceDecl *Container =
77193326Sed    FindIvarInterface(CGM.getContext(), OID, Ivar, Index);
78193326Sed  assert(Container && "Unable to find ivar container");
79193326Sed
80193326Sed  // If we know have an implementation (and the ivar is in it) then
81193326Sed  // look up in the implementation layout.
82198092Srdivacky  const ASTRecordLayout *RL;
83193326Sed  if (ID && ID->getClassInterface() == Container)
84193326Sed    RL = &CGM.getContext().getASTObjCImplementationLayout(ID);
85193326Sed  else
86193326Sed    RL = &CGM.getContext().getASTObjCInterfaceLayout(Container);
87193326Sed  return RL->getFieldOffset(Index);
88193326Sed}
89193326Sed
90193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
91193326Sed                                              const ObjCInterfaceDecl *OID,
92193326Sed                                              const ObjCIvarDecl *Ivar) {
93193326Sed  return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 8;
94193326Sed}
95193326Sed
96193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
97193326Sed                                              const ObjCImplementationDecl *OID,
98193326Sed                                              const ObjCIvarDecl *Ivar) {
99193326Sed  return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 8;
100193326Sed}
101193326Sed
102193326SedLValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
103193326Sed                                               const ObjCInterfaceDecl *OID,
104193326Sed                                               llvm::Value *BaseValue,
105193326Sed                                               const ObjCIvarDecl *Ivar,
106193326Sed                                               unsigned CVRQualifiers,
107193326Sed                                               llvm::Value *Offset) {
108193326Sed  // Compute (type*) ( (char *) BaseValue + Offset)
109198092Srdivacky  const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
110193326Sed  QualType IvarTy = Ivar->getType();
111193326Sed  const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
112193326Sed  llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr);
113193326Sed  V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
114193326Sed  V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
115198092Srdivacky
116198092Srdivacky  Qualifiers Quals = CGF.MakeQualifiers(IvarTy);
117198092Srdivacky  Quals.addCVRQualifiers(CVRQualifiers);
118198092Srdivacky
119193326Sed  if (Ivar->isBitField()) {
120193326Sed    // We need to compute the bit offset for the bit-field, the offset
121193326Sed    // is to the byte. Note, there is a subtle invariant here: we can
122193326Sed    // only call this routine on non-sythesized ivars but we may be
123193326Sed    // called for synthesized ivars. However, a synthesized ivar can
124193326Sed    // never be a bit-field so this is safe.
125193326Sed    uint64_t BitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar) % 8;
126193326Sed
127193326Sed    uint64_t BitFieldSize =
128193326Sed      Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue();
129193326Sed    return LValue::MakeBitfield(V, BitOffset, BitFieldSize,
130193326Sed                                IvarTy->isSignedIntegerType(),
131198092Srdivacky                                Quals.getCVRQualifiers());
132193326Sed  }
133193326Sed
134198092Srdivacky
135198092Srdivacky  LValue LV = LValue::MakeAddr(V, Quals);
136193326Sed  return LV;
137193326Sed}
138193326Sed
139193326Sed///
140193326Sed
141193326Sednamespace {
142193326Sed
143198092Srdivackytypedef std::vector<llvm::Constant*> ConstantVector;
144193326Sed
145198092Srdivacky// FIXME: We should find a nicer way to make the labels for metadata, string
146198092Srdivacky// concatenation is lame.
147193326Sed
148193326Sedclass ObjCCommonTypesHelper {
149198092Srdivackyprotected:
150198092Srdivacky  llvm::LLVMContext &VMContext;
151198092Srdivacky
152193326Sedprivate:
153193326Sed  llvm::Constant *getMessageSendFn() const {
154193326Sed    // id objc_msgSend (id, SEL, ...)
155193326Sed    std::vector<const llvm::Type*> Params;
156193326Sed    Params.push_back(ObjectPtrTy);
157193326Sed    Params.push_back(SelectorPtrTy);
158193326Sed    return
159198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
160198092Srdivacky                                                        Params, true),
161198092Srdivacky                                "objc_msgSend");
162193326Sed  }
163198092Srdivacky
164193326Sed  llvm::Constant *getMessageSendStretFn() const {
165193326Sed    // id objc_msgSend_stret (id, SEL, ...)
166193326Sed    std::vector<const llvm::Type*> Params;
167193326Sed    Params.push_back(ObjectPtrTy);
168193326Sed    Params.push_back(SelectorPtrTy);
169193326Sed    return
170198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
171198092Srdivacky                                                        Params, true),
172198092Srdivacky                                "objc_msgSend_stret");
173198092Srdivacky
174193326Sed  }
175198092Srdivacky
176193326Sed  llvm::Constant *getMessageSendFpretFn() const {
177193326Sed    // FIXME: This should be long double on x86_64?
178193326Sed    // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
179193326Sed    std::vector<const llvm::Type*> Params;
180193326Sed    Params.push_back(ObjectPtrTy);
181193326Sed    Params.push_back(SelectorPtrTy);
182193326Sed    return
183198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(
184198092Srdivacky                                             llvm::Type::getDoubleTy(VMContext),
185198092Srdivacky                                                        Params,
186198092Srdivacky                                                        true),
187198092Srdivacky                                "objc_msgSend_fpret");
188198092Srdivacky
189193326Sed  }
190198092Srdivacky
191193326Sed  llvm::Constant *getMessageSendSuperFn() const {
192193326Sed    // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
193193326Sed    const char *SuperName = "objc_msgSendSuper";
194193326Sed    std::vector<const llvm::Type*> Params;
195193326Sed    Params.push_back(SuperPtrTy);
196193326Sed    Params.push_back(SelectorPtrTy);
197193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
198193326Sed                                                             Params, true),
199193326Sed                                     SuperName);
200193326Sed  }
201198092Srdivacky
202193326Sed  llvm::Constant *getMessageSendSuperFn2() const {
203193326Sed    // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
204193326Sed    const char *SuperName = "objc_msgSendSuper2";
205193326Sed    std::vector<const llvm::Type*> Params;
206193326Sed    Params.push_back(SuperPtrTy);
207193326Sed    Params.push_back(SelectorPtrTy);
208193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
209193326Sed                                                             Params, true),
210193326Sed                                     SuperName);
211193326Sed  }
212198092Srdivacky
213193326Sed  llvm::Constant *getMessageSendSuperStretFn() const {
214193326Sed    // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
215193326Sed    //                              SEL op, ...)
216193326Sed    std::vector<const llvm::Type*> Params;
217193326Sed    Params.push_back(Int8PtrTy);
218193326Sed    Params.push_back(SuperPtrTy);
219193326Sed    Params.push_back(SelectorPtrTy);
220198092Srdivacky    return CGM.CreateRuntimeFunction(
221198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
222198092Srdivacky                              Params, true),
223198092Srdivacky      "objc_msgSendSuper_stret");
224193326Sed  }
225198092Srdivacky
226193326Sed  llvm::Constant *getMessageSendSuperStretFn2() const {
227193326Sed    // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
228193326Sed    //                               SEL op, ...)
229193326Sed    std::vector<const llvm::Type*> Params;
230193326Sed    Params.push_back(Int8PtrTy);
231193326Sed    Params.push_back(SuperPtrTy);
232193326Sed    Params.push_back(SelectorPtrTy);
233198092Srdivacky    return CGM.CreateRuntimeFunction(
234198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
235198092Srdivacky                              Params, true),
236198092Srdivacky      "objc_msgSendSuper2_stret");
237193326Sed  }
238198092Srdivacky
239193326Sed  llvm::Constant *getMessageSendSuperFpretFn() const {
240193326Sed    // There is no objc_msgSendSuper_fpret? How can that work?
241193326Sed    return getMessageSendSuperFn();
242193326Sed  }
243198092Srdivacky
244193326Sed  llvm::Constant *getMessageSendSuperFpretFn2() const {
245193326Sed    // There is no objc_msgSendSuper_fpret? How can that work?
246193326Sed    return getMessageSendSuperFn2();
247193326Sed  }
248198092Srdivacky
249193326Sedprotected:
250193326Sed  CodeGen::CodeGenModule &CGM;
251198092Srdivacky
252193326Sedpublic:
253193326Sed  const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
254193326Sed  const llvm::Type *Int8PtrTy;
255198092Srdivacky
256193326Sed  /// ObjectPtrTy - LLVM type for object handles (typeof(id))
257193326Sed  const llvm::Type *ObjectPtrTy;
258198092Srdivacky
259193326Sed  /// PtrObjectPtrTy - LLVM type for id *
260193326Sed  const llvm::Type *PtrObjectPtrTy;
261198092Srdivacky
262193326Sed  /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
263193326Sed  const llvm::Type *SelectorPtrTy;
264193326Sed  /// ProtocolPtrTy - LLVM type for external protocol handles
265193326Sed  /// (typeof(Protocol))
266193326Sed  const llvm::Type *ExternalProtocolPtrTy;
267198092Srdivacky
268193326Sed  // SuperCTy - clang type for struct objc_super.
269193326Sed  QualType SuperCTy;
270193326Sed  // SuperPtrCTy - clang type for struct objc_super *.
271193326Sed  QualType SuperPtrCTy;
272198092Srdivacky
273193326Sed  /// SuperTy - LLVM type for struct objc_super.
274193326Sed  const llvm::StructType *SuperTy;
275193326Sed  /// SuperPtrTy - LLVM type for struct objc_super *.
276193326Sed  const llvm::Type *SuperPtrTy;
277198092Srdivacky
278193326Sed  /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
279193326Sed  /// in GCC parlance).
280193326Sed  const llvm::StructType *PropertyTy;
281198092Srdivacky
282193326Sed  /// PropertyListTy - LLVM type for struct objc_property_list
283193326Sed  /// (_prop_list_t in GCC parlance).
284193326Sed  const llvm::StructType *PropertyListTy;
285193326Sed  /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
286193326Sed  const llvm::Type *PropertyListPtrTy;
287198092Srdivacky
288193326Sed  // MethodTy - LLVM type for struct objc_method.
289193326Sed  const llvm::StructType *MethodTy;
290198092Srdivacky
291193326Sed  /// CacheTy - LLVM type for struct objc_cache.
292193326Sed  const llvm::Type *CacheTy;
293193326Sed  /// CachePtrTy - LLVM type for struct objc_cache *.
294193326Sed  const llvm::Type *CachePtrTy;
295198092Srdivacky
296193326Sed  llvm::Constant *getGetPropertyFn() {
297193326Sed    CodeGen::CodeGenTypes &Types = CGM.getTypes();
298193326Sed    ASTContext &Ctx = CGM.getContext();
299193326Sed    // id objc_getProperty (id, SEL, ptrdiff_t, bool)
300193326Sed    llvm::SmallVector<QualType,16> Params;
301193326Sed    QualType IdType = Ctx.getObjCIdType();
302193326Sed    QualType SelType = Ctx.getObjCSelType();
303193326Sed    Params.push_back(IdType);
304193326Sed    Params.push_back(SelType);
305193326Sed    Params.push_back(Ctx.LongTy);
306193326Sed    Params.push_back(Ctx.BoolTy);
307193326Sed    const llvm::FunctionType *FTy =
308203955Srdivacky      Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
309203955Srdivacky                                                  CC_Default, false), false);
310193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
311193326Sed  }
312198092Srdivacky
313193326Sed  llvm::Constant *getSetPropertyFn() {
314193326Sed    CodeGen::CodeGenTypes &Types = CGM.getTypes();
315193326Sed    ASTContext &Ctx = CGM.getContext();
316193326Sed    // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
317193326Sed    llvm::SmallVector<QualType,16> Params;
318193326Sed    QualType IdType = Ctx.getObjCIdType();
319193326Sed    QualType SelType = Ctx.getObjCSelType();
320193326Sed    Params.push_back(IdType);
321193326Sed    Params.push_back(SelType);
322193326Sed    Params.push_back(Ctx.LongTy);
323193326Sed    Params.push_back(IdType);
324193326Sed    Params.push_back(Ctx.BoolTy);
325193326Sed    Params.push_back(Ctx.BoolTy);
326193326Sed    const llvm::FunctionType *FTy =
327203955Srdivacky      Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
328203955Srdivacky                                                  CC_Default, false), false);
329193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
330193326Sed  }
331198092Srdivacky
332193326Sed  llvm::Constant *getEnumerationMutationFn() {
333198092Srdivacky    CodeGen::CodeGenTypes &Types = CGM.getTypes();
334198092Srdivacky    ASTContext &Ctx = CGM.getContext();
335193326Sed    // void objc_enumerationMutation (id)
336198092Srdivacky    llvm::SmallVector<QualType,16> Params;
337198092Srdivacky    Params.push_back(Ctx.getObjCIdType());
338198092Srdivacky    const llvm::FunctionType *FTy =
339203955Srdivacky      Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
340203955Srdivacky                                                  CC_Default, false), false);
341193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
342193326Sed  }
343198092Srdivacky
344193326Sed  /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
345193326Sed  llvm::Constant *getGcReadWeakFn() {
346193326Sed    // id objc_read_weak (id *)
347193326Sed    std::vector<const llvm::Type*> Args;
348193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
349198092Srdivacky    llvm::FunctionType *FTy =
350198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
351193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
352198092Srdivacky  }
353198092Srdivacky
354193326Sed  /// GcAssignWeakFn -- LLVM objc_assign_weak function.
355193326Sed  llvm::Constant *getGcAssignWeakFn() {
356193326Sed    // id objc_assign_weak (id, id *)
357193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
358193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
359193326Sed    llvm::FunctionType *FTy =
360193326Sed      llvm::FunctionType::get(ObjectPtrTy, Args, false);
361193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
362193326Sed  }
363198092Srdivacky
364193326Sed  /// GcAssignGlobalFn -- LLVM objc_assign_global function.
365193326Sed  llvm::Constant *getGcAssignGlobalFn() {
366193326Sed    // id objc_assign_global(id, id *)
367193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
368193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
369198092Srdivacky    llvm::FunctionType *FTy =
370198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
371193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
372193326Sed  }
373198092Srdivacky
374193326Sed  /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
375193326Sed  llvm::Constant *getGcAssignIvarFn() {
376198092Srdivacky    // id objc_assign_ivar(id, id *, ptrdiff_t)
377193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
378193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
379198092Srdivacky    Args.push_back(LongTy);
380198092Srdivacky    llvm::FunctionType *FTy =
381198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
382193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
383193326Sed  }
384198092Srdivacky
385198092Srdivacky  /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
386198092Srdivacky  llvm::Constant *GcMemmoveCollectableFn() {
387198092Srdivacky    // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
388198092Srdivacky    std::vector<const llvm::Type*> Args(1, Int8PtrTy);
389198092Srdivacky    Args.push_back(Int8PtrTy);
390198092Srdivacky    Args.push_back(LongTy);
391198092Srdivacky    llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
392198092Srdivacky    return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
393198092Srdivacky  }
394198092Srdivacky
395193326Sed  /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
396193326Sed  llvm::Constant *getGcAssignStrongCastFn() {
397193326Sed    // id objc_assign_global(id, id *)
398193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
399193326Sed    Args.push_back(ObjectPtrTy->getPointerTo());
400198092Srdivacky    llvm::FunctionType *FTy =
401198092Srdivacky      llvm::FunctionType::get(ObjectPtrTy, Args, false);
402193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
403193326Sed  }
404193326Sed
405193326Sed  /// ExceptionThrowFn - LLVM objc_exception_throw function.
406193326Sed  llvm::Constant *getExceptionThrowFn() {
407193326Sed    // void objc_exception_throw(id)
408193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
409193326Sed    llvm::FunctionType *FTy =
410198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
411193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
412193326Sed  }
413198092Srdivacky
414193326Sed  /// SyncEnterFn - LLVM object_sync_enter function.
415193326Sed  llvm::Constant *getSyncEnterFn() {
416193326Sed    // void objc_sync_enter (id)
417193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
418193326Sed    llvm::FunctionType *FTy =
419198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
420193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
421193326Sed  }
422198092Srdivacky
423193326Sed  /// SyncExitFn - LLVM object_sync_exit function.
424193326Sed  llvm::Constant *getSyncExitFn() {
425193326Sed    // void objc_sync_exit (id)
426193326Sed    std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
427193326Sed    llvm::FunctionType *FTy =
428198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
429193326Sed    return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
430193326Sed  }
431198092Srdivacky
432193326Sed  llvm::Constant *getSendFn(bool IsSuper) const {
433193326Sed    return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
434193326Sed  }
435198092Srdivacky
436193326Sed  llvm::Constant *getSendFn2(bool IsSuper) const {
437193326Sed    return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
438193326Sed  }
439198092Srdivacky
440193326Sed  llvm::Constant *getSendStretFn(bool IsSuper) const {
441193326Sed    return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
442193326Sed  }
443198092Srdivacky
444193326Sed  llvm::Constant *getSendStretFn2(bool IsSuper) const {
445193326Sed    return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
446193326Sed  }
447198092Srdivacky
448193326Sed  llvm::Constant *getSendFpretFn(bool IsSuper) const {
449193326Sed    return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
450193326Sed  }
451198092Srdivacky
452193326Sed  llvm::Constant *getSendFpretFn2(bool IsSuper) const {
453193326Sed    return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
454193326Sed  }
455198092Srdivacky
456193326Sed  ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
457193326Sed  ~ObjCCommonTypesHelper(){}
458193326Sed};
459193326Sed
460193326Sed/// ObjCTypesHelper - Helper class that encapsulates lazy
461193326Sed/// construction of varies types used during ObjC generation.
462193326Sedclass ObjCTypesHelper : public ObjCCommonTypesHelper {
463193326Sedpublic:
464193326Sed  /// SymtabTy - LLVM type for struct objc_symtab.
465193326Sed  const llvm::StructType *SymtabTy;
466193326Sed  /// SymtabPtrTy - LLVM type for struct objc_symtab *.
467193326Sed  const llvm::Type *SymtabPtrTy;
468193326Sed  /// ModuleTy - LLVM type for struct objc_module.
469193326Sed  const llvm::StructType *ModuleTy;
470193326Sed
471193326Sed  /// ProtocolTy - LLVM type for struct objc_protocol.
472193326Sed  const llvm::StructType *ProtocolTy;
473193326Sed  /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
474193326Sed  const llvm::Type *ProtocolPtrTy;
475193326Sed  /// ProtocolExtensionTy - LLVM type for struct
476193326Sed  /// objc_protocol_extension.
477193326Sed  const llvm::StructType *ProtocolExtensionTy;
478193326Sed  /// ProtocolExtensionTy - LLVM type for struct
479193326Sed  /// objc_protocol_extension *.
480193326Sed  const llvm::Type *ProtocolExtensionPtrTy;
481193326Sed  /// MethodDescriptionTy - LLVM type for struct
482193326Sed  /// objc_method_description.
483193326Sed  const llvm::StructType *MethodDescriptionTy;
484193326Sed  /// MethodDescriptionListTy - LLVM type for struct
485193326Sed  /// objc_method_description_list.
486193326Sed  const llvm::StructType *MethodDescriptionListTy;
487193326Sed  /// MethodDescriptionListPtrTy - LLVM type for struct
488193326Sed  /// objc_method_description_list *.
489193326Sed  const llvm::Type *MethodDescriptionListPtrTy;
490193326Sed  /// ProtocolListTy - LLVM type for struct objc_property_list.
491193326Sed  const llvm::Type *ProtocolListTy;
492193326Sed  /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
493193326Sed  const llvm::Type *ProtocolListPtrTy;
494193326Sed  /// CategoryTy - LLVM type for struct objc_category.
495193326Sed  const llvm::StructType *CategoryTy;
496193326Sed  /// ClassTy - LLVM type for struct objc_class.
497193326Sed  const llvm::StructType *ClassTy;
498193326Sed  /// ClassPtrTy - LLVM type for struct objc_class *.
499193326Sed  const llvm::Type *ClassPtrTy;
500193326Sed  /// ClassExtensionTy - LLVM type for struct objc_class_ext.
501193326Sed  const llvm::StructType *ClassExtensionTy;
502193326Sed  /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
503193326Sed  const llvm::Type *ClassExtensionPtrTy;
504193326Sed  // IvarTy - LLVM type for struct objc_ivar.
505193326Sed  const llvm::StructType *IvarTy;
506193326Sed  /// IvarListTy - LLVM type for struct objc_ivar_list.
507193326Sed  const llvm::Type *IvarListTy;
508193326Sed  /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
509193326Sed  const llvm::Type *IvarListPtrTy;
510193326Sed  /// MethodListTy - LLVM type for struct objc_method_list.
511193326Sed  const llvm::Type *MethodListTy;
512193326Sed  /// MethodListPtrTy - LLVM type for struct objc_method_list *.
513193326Sed  const llvm::Type *MethodListPtrTy;
514198092Srdivacky
515193326Sed  /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
516193326Sed  const llvm::Type *ExceptionDataTy;
517198092Srdivacky
518193326Sed  /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
519193326Sed  llvm::Constant *getExceptionTryEnterFn() {
520193326Sed    std::vector<const llvm::Type*> Params;
521193326Sed    Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
522198092Srdivacky    return CGM.CreateRuntimeFunction(
523198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
524198092Srdivacky                              Params, false),
525198092Srdivacky      "objc_exception_try_enter");
526193326Sed  }
527193326Sed
528193326Sed  /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
529193326Sed  llvm::Constant *getExceptionTryExitFn() {
530193326Sed    std::vector<const llvm::Type*> Params;
531193326Sed    Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
532198092Srdivacky    return CGM.CreateRuntimeFunction(
533198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
534198092Srdivacky                              Params, false),
535198092Srdivacky      "objc_exception_try_exit");
536193326Sed  }
537193326Sed
538193326Sed  /// ExceptionExtractFn - LLVM objc_exception_extract function.
539193326Sed  llvm::Constant *getExceptionExtractFn() {
540193326Sed    std::vector<const llvm::Type*> Params;
541193326Sed    Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
542193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
543193326Sed                                                             Params, false),
544193326Sed                                     "objc_exception_extract");
545198092Srdivacky
546193326Sed  }
547198092Srdivacky
548193326Sed  /// ExceptionMatchFn - LLVM objc_exception_match function.
549193326Sed  llvm::Constant *getExceptionMatchFn() {
550193326Sed    std::vector<const llvm::Type*> Params;
551193326Sed    Params.push_back(ClassPtrTy);
552193326Sed    Params.push_back(ObjectPtrTy);
553198092Srdivacky    return CGM.CreateRuntimeFunction(
554198092Srdivacky      llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
555198092Srdivacky                              Params, false),
556198092Srdivacky      "objc_exception_match");
557198092Srdivacky
558193326Sed  }
559198092Srdivacky
560193326Sed  /// SetJmpFn - LLVM _setjmp function.
561193326Sed  llvm::Constant *getSetJmpFn() {
562193326Sed    std::vector<const llvm::Type*> Params;
563198092Srdivacky    Params.push_back(llvm::Type::getInt32PtrTy(VMContext));
564193326Sed    return
565198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
566193326Sed                                                        Params, false),
567193326Sed                                "_setjmp");
568198092Srdivacky
569193326Sed  }
570198092Srdivacky
571193326Sedpublic:
572193326Sed  ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
573193326Sed  ~ObjCTypesHelper() {}
574193326Sed};
575193326Sed
576193326Sed/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
577193326Sed/// modern abi
578193326Sedclass ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
579193326Sedpublic:
580198092Srdivacky
581193326Sed  // MethodListnfABITy - LLVM for struct _method_list_t
582193326Sed  const llvm::StructType *MethodListnfABITy;
583198092Srdivacky
584193326Sed  // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
585193326Sed  const llvm::Type *MethodListnfABIPtrTy;
586198092Srdivacky
587193326Sed  // ProtocolnfABITy = LLVM for struct _protocol_t
588193326Sed  const llvm::StructType *ProtocolnfABITy;
589198092Srdivacky
590193326Sed  // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
591193326Sed  const llvm::Type *ProtocolnfABIPtrTy;
592193326Sed
593193326Sed  // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
594193326Sed  const llvm::StructType *ProtocolListnfABITy;
595198092Srdivacky
596193326Sed  // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
597193326Sed  const llvm::Type *ProtocolListnfABIPtrTy;
598198092Srdivacky
599193326Sed  // ClassnfABITy - LLVM for struct _class_t
600193326Sed  const llvm::StructType *ClassnfABITy;
601198092Srdivacky
602193326Sed  // ClassnfABIPtrTy - LLVM for struct _class_t*
603193326Sed  const llvm::Type *ClassnfABIPtrTy;
604198092Srdivacky
605193326Sed  // IvarnfABITy - LLVM for struct _ivar_t
606193326Sed  const llvm::StructType *IvarnfABITy;
607198092Srdivacky
608193326Sed  // IvarListnfABITy - LLVM for struct _ivar_list_t
609193326Sed  const llvm::StructType *IvarListnfABITy;
610198092Srdivacky
611193326Sed  // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
612193326Sed  const llvm::Type *IvarListnfABIPtrTy;
613198092Srdivacky
614193326Sed  // ClassRonfABITy - LLVM for struct _class_ro_t
615193326Sed  const llvm::StructType *ClassRonfABITy;
616198092Srdivacky
617193326Sed  // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
618193326Sed  const llvm::Type *ImpnfABITy;
619198092Srdivacky
620193326Sed  // CategorynfABITy - LLVM for struct _category_t
621193326Sed  const llvm::StructType *CategorynfABITy;
622198092Srdivacky
623193326Sed  // New types for nonfragile abi messaging.
624198092Srdivacky
625193326Sed  // MessageRefTy - LLVM for:
626193326Sed  // struct _message_ref_t {
627193326Sed  //   IMP messenger;
628193326Sed  //   SEL name;
629193326Sed  // };
630193326Sed  const llvm::StructType *MessageRefTy;
631193326Sed  // MessageRefCTy - clang type for struct _message_ref_t
632193326Sed  QualType MessageRefCTy;
633198092Srdivacky
634193326Sed  // MessageRefPtrTy - LLVM for struct _message_ref_t*
635193326Sed  const llvm::Type *MessageRefPtrTy;
636193326Sed  // MessageRefCPtrTy - clang type for struct _message_ref_t*
637193326Sed  QualType MessageRefCPtrTy;
638198092Srdivacky
639193326Sed  // MessengerTy - Type of the messenger (shown as IMP above)
640193326Sed  const llvm::FunctionType *MessengerTy;
641198092Srdivacky
642193326Sed  // SuperMessageRefTy - LLVM for:
643193326Sed  // struct _super_message_ref_t {
644193326Sed  //   SUPER_IMP messenger;
645193326Sed  //   SEL name;
646193326Sed  // };
647193326Sed  const llvm::StructType *SuperMessageRefTy;
648198092Srdivacky
649193326Sed  // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
650193326Sed  const llvm::Type *SuperMessageRefPtrTy;
651193326Sed
652193326Sed  llvm::Constant *getMessageSendFixupFn() {
653193326Sed    // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
654193326Sed    std::vector<const llvm::Type*> Params;
655193326Sed    Params.push_back(ObjectPtrTy);
656193326Sed    Params.push_back(MessageRefPtrTy);
657193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
658193326Sed                                                             Params, true),
659193326Sed                                     "objc_msgSend_fixup");
660193326Sed  }
661198092Srdivacky
662193326Sed  llvm::Constant *getMessageSendFpretFixupFn() {
663193326Sed    // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
664193326Sed    std::vector<const llvm::Type*> Params;
665193326Sed    Params.push_back(ObjectPtrTy);
666193326Sed    Params.push_back(MessageRefPtrTy);
667193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
668193326Sed                                                             Params, true),
669193326Sed                                     "objc_msgSend_fpret_fixup");
670193326Sed  }
671198092Srdivacky
672193326Sed  llvm::Constant *getMessageSendStretFixupFn() {
673193326Sed    // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
674193326Sed    std::vector<const llvm::Type*> Params;
675193326Sed    Params.push_back(ObjectPtrTy);
676193326Sed    Params.push_back(MessageRefPtrTy);
677193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
678193326Sed                                                             Params, true),
679193326Sed                                     "objc_msgSend_stret_fixup");
680193326Sed  }
681198092Srdivacky
682193326Sed  llvm::Constant *getMessageSendIdFixupFn() {
683193326Sed    // id objc_msgSendId_fixup(id, struct message_ref_t*, ...)
684193326Sed    std::vector<const llvm::Type*> Params;
685193326Sed    Params.push_back(ObjectPtrTy);
686193326Sed    Params.push_back(MessageRefPtrTy);
687193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
688193326Sed                                                             Params, true),
689193326Sed                                     "objc_msgSendId_fixup");
690193326Sed  }
691198092Srdivacky
692193326Sed  llvm::Constant *getMessageSendIdStretFixupFn() {
693193326Sed    // id objc_msgSendId_stret_fixup(id, struct message_ref_t*, ...)
694193326Sed    std::vector<const llvm::Type*> Params;
695193326Sed    Params.push_back(ObjectPtrTy);
696193326Sed    Params.push_back(MessageRefPtrTy);
697193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
698193326Sed                                                             Params, true),
699193326Sed                                     "objc_msgSendId_stret_fixup");
700193326Sed  }
701193326Sed  llvm::Constant *getMessageSendSuper2FixupFn() {
702198092Srdivacky    // id objc_msgSendSuper2_fixup (struct objc_super *,
703193326Sed    //                              struct _super_message_ref_t*, ...)
704193326Sed    std::vector<const llvm::Type*> Params;
705193326Sed    Params.push_back(SuperPtrTy);
706193326Sed    Params.push_back(SuperMessageRefPtrTy);
707193326Sed    return  CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
708193326Sed                                                              Params, true),
709193326Sed                                      "objc_msgSendSuper2_fixup");
710193326Sed  }
711198092Srdivacky
712193326Sed  llvm::Constant *getMessageSendSuper2StretFixupFn() {
713198092Srdivacky    // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
714193326Sed    //                                   struct _super_message_ref_t*, ...)
715193326Sed    std::vector<const llvm::Type*> Params;
716193326Sed    Params.push_back(SuperPtrTy);
717193326Sed    Params.push_back(SuperMessageRefPtrTy);
718193326Sed    return  CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
719193326Sed                                                              Params, true),
720193326Sed                                      "objc_msgSendSuper2_stret_fixup");
721193326Sed  }
722198092Srdivacky
723198092Srdivacky
724198092Srdivacky
725193326Sed  /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C
726193326Sed  /// exception personality function.
727193326Sed  llvm::Value *getEHPersonalityPtr() {
728198092Srdivacky    llvm::Constant *Personality =
729198092Srdivacky      CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
730193326Sed                                                        true),
731198092Srdivacky                                "__objc_personality_v0");
732193326Sed    return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy);
733193326Sed  }
734193326Sed
735193326Sed  llvm::Constant *getUnwindResumeOrRethrowFn() {
736193326Sed    std::vector<const llvm::Type*> Params;
737193326Sed    Params.push_back(Int8PtrTy);
738198092Srdivacky    return CGM.CreateRuntimeFunction(
739198092Srdivacky      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
740198092Srdivacky                              Params, false),
741203955Srdivacky      (CGM.getLangOptions().SjLjExceptions ? "_Unwind_SjLj_Resume" :
742203955Srdivacky       "_Unwind_Resume_or_Rethrow"));
743193326Sed  }
744198092Srdivacky
745193326Sed  llvm::Constant *getObjCEndCatchFn() {
746198092Srdivacky    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
747195341Sed                                                             false),
748193326Sed                                     "objc_end_catch");
749198092Srdivacky
750193326Sed  }
751198092Srdivacky
752193326Sed  llvm::Constant *getObjCBeginCatchFn() {
753193326Sed    std::vector<const llvm::Type*> Params;
754193326Sed    Params.push_back(Int8PtrTy);
755193326Sed    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
756193326Sed                                                             Params, false),
757193326Sed                                     "objc_begin_catch");
758193326Sed  }
759193326Sed
760193326Sed  const llvm::StructType *EHTypeTy;
761193326Sed  const llvm::Type *EHTypePtrTy;
762193326Sed
763193326Sed  ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
764193326Sed  ~ObjCNonFragileABITypesHelper(){}
765193326Sed};
766198092Srdivacky
767193326Sedclass CGObjCCommonMac : public CodeGen::CGObjCRuntime {
768193326Sedpublic:
769193326Sed  // FIXME - accessibility
770193326Sed  class GC_IVAR {
771193326Sed  public:
772193326Sed    unsigned ivar_bytepos;
773193326Sed    unsigned ivar_size;
774193326Sed    GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
775198092Srdivacky      : ivar_bytepos(bytepos), ivar_size(size) {}
776193326Sed
777193326Sed    // Allow sorting based on byte pos.
778193326Sed    bool operator<(const GC_IVAR &b) const {
779193326Sed      return ivar_bytepos < b.ivar_bytepos;
780193326Sed    }
781193326Sed  };
782198092Srdivacky
783193326Sed  class SKIP_SCAN {
784193326Sed  public:
785193326Sed    unsigned skip;
786193326Sed    unsigned scan;
787198092Srdivacky    SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
788193326Sed      : skip(_skip), scan(_scan) {}
789193326Sed  };
790198092Srdivacky
791193326Sedprotected:
792193326Sed  CodeGen::CodeGenModule &CGM;
793198092Srdivacky  llvm::LLVMContext &VMContext;
794193326Sed  // FIXME! May not be needing this after all.
795193326Sed  unsigned ObjCABI;
796198092Srdivacky
797193326Sed  // gc ivar layout bitmap calculation helper caches.
798193326Sed  llvm::SmallVector<GC_IVAR, 16> SkipIvars;
799193326Sed  llvm::SmallVector<GC_IVAR, 16> IvarsInfo;
800198092Srdivacky
801193326Sed  /// LazySymbols - Symbols to generate a lazy reference for. See
802193326Sed  /// DefinedSymbols and FinishModule().
803198092Srdivacky  llvm::SetVector<IdentifierInfo*> LazySymbols;
804198092Srdivacky
805193326Sed  /// DefinedSymbols - External symbols which are defined by this
806193326Sed  /// module. The symbols in this list and LazySymbols are used to add
807193326Sed  /// special linker symbols which ensure that Objective-C modules are
808193326Sed  /// linked properly.
809198092Srdivacky  llvm::SetVector<IdentifierInfo*> DefinedSymbols;
810198092Srdivacky
811193326Sed  /// ClassNames - uniqued class names.
812193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
813198092Srdivacky
814193326Sed  /// MethodVarNames - uniqued method variable names.
815193326Sed  llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
816198092Srdivacky
817193326Sed  /// MethodVarTypes - uniqued method type signatures. We have to use
818193326Sed  /// a StringMap here because have no other unique reference.
819193326Sed  llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
820198092Srdivacky
821193326Sed  /// MethodDefinitions - map of methods which have been defined in
822193326Sed  /// this translation unit.
823193326Sed  llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
824198092Srdivacky
825193326Sed  /// PropertyNames - uniqued method variable names.
826193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
827198092Srdivacky
828193326Sed  /// ClassReferences - uniqued class references.
829193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
830198092Srdivacky
831193326Sed  /// SelectorReferences - uniqued selector references.
832193326Sed  llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
833198092Srdivacky
834193326Sed  /// Protocols - Protocols for which an objc_protocol structure has
835193326Sed  /// been emitted. Forward declarations are handled by creating an
836193326Sed  /// empty structure whose initializer is filled in when/if defined.
837193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
838198092Srdivacky
839193326Sed  /// DefinedProtocols - Protocols which have actually been
840193326Sed  /// defined. We should not need this, see FIXME in GenerateProtocol.
841193326Sed  llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
842198092Srdivacky
843193326Sed  /// DefinedClasses - List of defined classes.
844193326Sed  std::vector<llvm::GlobalValue*> DefinedClasses;
845193326Sed
846193326Sed  /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
847193326Sed  std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
848198092Srdivacky
849193326Sed  /// DefinedCategories - List of defined categories.
850193326Sed  std::vector<llvm::GlobalValue*> DefinedCategories;
851198092Srdivacky
852193326Sed  /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
853193326Sed  std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
854193326Sed
855193326Sed  /// GetNameForMethod - Return a name for the given method.
856193326Sed  /// \param[out] NameOut - The return value.
857193326Sed  void GetNameForMethod(const ObjCMethodDecl *OMD,
858193326Sed                        const ObjCContainerDecl *CD,
859198398Srdivacky                        llvm::SmallVectorImpl<char> &NameOut);
860198092Srdivacky
861193326Sed  /// GetMethodVarName - Return a unique constant for the given
862193326Sed  /// selector's name. The return value has type char *.
863193326Sed  llvm::Constant *GetMethodVarName(Selector Sel);
864193326Sed  llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
865193326Sed  llvm::Constant *GetMethodVarName(const std::string &Name);
866198092Srdivacky
867193326Sed  /// GetMethodVarType - Return a unique constant for the given
868193326Sed  /// selector's name. The return value has type char *.
869198092Srdivacky
870193326Sed  // FIXME: This is a horrible name.
871193326Sed  llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
872193326Sed  llvm::Constant *GetMethodVarType(const FieldDecl *D);
873198092Srdivacky
874193326Sed  /// GetPropertyName - Return a unique constant for the given
875193326Sed  /// name. The return value has type char *.
876193326Sed  llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
877198092Srdivacky
878193326Sed  // FIXME: This can be dropped once string functions are unified.
879193326Sed  llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
880193326Sed                                        const Decl *Container);
881198092Srdivacky
882193326Sed  /// GetClassName - Return a unique constant for the given selector's
883193326Sed  /// name. The return value has type char *.
884193326Sed  llvm::Constant *GetClassName(IdentifierInfo *Ident);
885198092Srdivacky
886193326Sed  /// BuildIvarLayout - Builds ivar layout bitmap for the class
887193326Sed  /// implementation for the __strong or __weak case.
888193326Sed  ///
889193326Sed  llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
890193326Sed                                  bool ForStrongLayout);
891198092Srdivacky
892193326Sed  void BuildAggrIvarRecordLayout(const RecordType *RT,
893198092Srdivacky                                 unsigned int BytePos, bool ForStrongLayout,
894198092Srdivacky                                 bool &HasUnion);
895193326Sed  void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
896193326Sed                           const llvm::StructLayout *Layout,
897193326Sed                           const RecordDecl *RD,
898193326Sed                           const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
899193326Sed                           unsigned int BytePos, bool ForStrongLayout,
900193326Sed                           bool &HasUnion);
901193326Sed
902193326Sed  /// GetIvarLayoutName - Returns a unique constant for the given
903193326Sed  /// ivar layout bitmap.
904193326Sed  llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
905193326Sed                                    const ObjCCommonTypesHelper &ObjCTypes);
906198092Srdivacky
907193326Sed  /// EmitPropertyList - Emit the given property list. The return
908193326Sed  /// value has type PropertyListPtrTy.
909198398Srdivacky  llvm::Constant *EmitPropertyList(llvm::Twine Name,
910198092Srdivacky                                   const Decl *Container,
911193326Sed                                   const ObjCContainerDecl *OCD,
912193326Sed                                   const ObjCCommonTypesHelper &ObjCTypes);
913198092Srdivacky
914200583Srdivacky  /// PushProtocolProperties - Push protocol's property on the input stack.
915200583Srdivacky  void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
916200583Srdivacky                              std::vector<llvm::Constant*> &Properties,
917200583Srdivacky                                   const Decl *Container,
918200583Srdivacky                                   const ObjCProtocolDecl *PROTO,
919200583Srdivacky                                   const ObjCCommonTypesHelper &ObjCTypes);
920200583Srdivacky
921193326Sed  /// GetProtocolRef - Return a reference to the internal protocol
922193326Sed  /// description, creating an empty one if it has not been
923193326Sed  /// defined. The return value has type ProtocolPtrTy.
924193326Sed  llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
925193326Sed
926193326Sed  /// CreateMetadataVar - Create a global variable with internal
927193326Sed  /// linkage for use by the Objective-C runtime.
928193326Sed  ///
929193326Sed  /// This is a convenience wrapper which not only creates the
930193326Sed  /// variable, but also sets the section and alignment and adds the
931198092Srdivacky  /// global to the "llvm.used" list.
932193326Sed  ///
933193326Sed  /// \param Name - The variable name.
934193326Sed  /// \param Init - The variable initializer; this is also used to
935193326Sed  /// define the type of the variable.
936193326Sed  /// \param Section - The section the variable should go into, or 0.
937193326Sed  /// \param Align - The alignment for the variable, or 0.
938193326Sed  /// \param AddToUsed - Whether the variable should be added to
939193326Sed  /// "llvm.used".
940198398Srdivacky  llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
941193326Sed                                          llvm::Constant *Init,
942193326Sed                                          const char *Section,
943193326Sed                                          unsigned Align,
944193326Sed                                          bool AddToUsed);
945193326Sed
946193326Sed  CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
947193326Sed                                        QualType ResultType,
948193326Sed                                        llvm::Value *Sel,
949193326Sed                                        llvm::Value *Arg0,
950193326Sed                                        QualType Arg0Ty,
951193326Sed                                        bool IsSuper,
952193326Sed                                        const CallArgList &CallArgs,
953198092Srdivacky                                        const ObjCMethodDecl *OMD,
954193326Sed                                        const ObjCCommonTypesHelper &ObjCTypes);
955193326Sed
956198092Srdivackypublic:
957198092Srdivacky  CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
958198092Srdivacky    CGM(cgm), VMContext(cgm.getLLVMContext()) { }
959195099Sed
960202879Srdivacky  virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
961198092Srdivacky
962193326Sed  virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
963193326Sed                                         const ObjCContainerDecl *CD=0);
964198092Srdivacky
965193326Sed  virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
966198092Srdivacky
967193326Sed  /// GetOrEmitProtocol - Get the protocol object for the given
968193326Sed  /// declaration, emitting it if necessary. The return value has type
969193326Sed  /// ProtocolPtrTy.
970193326Sed  virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
971198092Srdivacky
972193326Sed  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
973193326Sed  /// object for the given declaration, emitting it if needed. These
974193326Sed  /// forward references will be filled in with empty bodies if no
975193326Sed  /// definition is seen. The return value has type ProtocolPtrTy.
976193326Sed  virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
977193326Sed};
978198092Srdivacky
979193326Sedclass CGObjCMac : public CGObjCCommonMac {
980193326Sedprivate:
981193326Sed  ObjCTypesHelper ObjCTypes;
982193326Sed  /// EmitImageInfo - Emit the image info marker used to encode some module
983193326Sed  /// level information.
984193326Sed  void EmitImageInfo();
985193326Sed
986193326Sed  /// EmitModuleInfo - Another marker encoding module level
987198092Srdivacky  /// information.
988193326Sed  void EmitModuleInfo();
989193326Sed
990193326Sed  /// EmitModuleSymols - Emit module symbols, the list of defined
991193326Sed  /// classes and categories. The result has type SymtabPtrTy.
992193326Sed  llvm::Constant *EmitModuleSymbols();
993193326Sed
994193326Sed  /// FinishModule - Write out global data structures at the end of
995193326Sed  /// processing a translation unit.
996193326Sed  void FinishModule();
997193326Sed
998193326Sed  /// EmitClassExtension - Generate the class extension structure used
999193326Sed  /// to store the weak ivar layout and properties. The return value
1000193326Sed  /// has type ClassExtensionPtrTy.
1001193326Sed  llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
1002193326Sed
1003193326Sed  /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1004193326Sed  /// for the given class.
1005198092Srdivacky  llvm::Value *EmitClassRef(CGBuilderTy &Builder,
1006193326Sed                            const ObjCInterfaceDecl *ID);
1007199482Srdivacky
1008199482Srdivacky  /// EmitSuperClassRef - Emits reference to class's main metadata class.
1009199482Srdivacky  llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
1010193326Sed
1011193326Sed  CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1012193326Sed                                  QualType ResultType,
1013193326Sed                                  Selector Sel,
1014193326Sed                                  llvm::Value *Arg0,
1015193326Sed                                  QualType Arg0Ty,
1016193326Sed                                  bool IsSuper,
1017193326Sed                                  const CallArgList &CallArgs);
1018193326Sed
1019193326Sed  /// EmitIvarList - Emit the ivar list for the given
1020193326Sed  /// implementation. If ForClass is true the list of class ivars
1021193326Sed  /// (i.e. metaclass ivars) is emitted, otherwise the list of
1022193326Sed  /// interface ivars will be emitted. The return value has type
1023193326Sed  /// IvarListPtrTy.
1024193326Sed  llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
1025193326Sed                               bool ForClass);
1026198092Srdivacky
1027193326Sed  /// EmitMetaClass - Emit a forward reference to the class structure
1028193326Sed  /// for the metaclass of the given interface. The return value has
1029193326Sed  /// type ClassPtrTy.
1030193326Sed  llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1031193326Sed
1032193326Sed  /// EmitMetaClass - Emit a class structure for the metaclass of the
1033193326Sed  /// given implementation. The return value has type ClassPtrTy.
1034193326Sed  llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1035193326Sed                                llvm::Constant *Protocols,
1036193326Sed                                const ConstantVector &Methods);
1037198092Srdivacky
1038193326Sed  llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
1039198092Srdivacky
1040193326Sed  llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
1041193326Sed
1042193326Sed  /// EmitMethodList - Emit the method list for the given
1043193326Sed  /// implementation. The return value has type MethodListPtrTy.
1044198398Srdivacky  llvm::Constant *EmitMethodList(llvm::Twine Name,
1045193326Sed                                 const char *Section,
1046193326Sed                                 const ConstantVector &Methods);
1047193326Sed
1048193326Sed  /// EmitMethodDescList - Emit a method description list for a list of
1049198092Srdivacky  /// method declarations.
1050193326Sed  ///  - TypeName: The name for the type containing the methods.
1051193326Sed  ///  - IsProtocol: True iff these methods are for a protocol.
1052193326Sed  ///  - ClassMethds: True iff these are class methods.
1053193326Sed  ///  - Required: When true, only "required" methods are
1054193326Sed  ///    listed. Similarly, when false only "optional" methods are
1055193326Sed  ///    listed. For classes this should always be true.
1056193326Sed  ///  - begin, end: The method list to output.
1057193326Sed  ///
1058193326Sed  /// The return value has type MethodDescriptionListPtrTy.
1059198398Srdivacky  llvm::Constant *EmitMethodDescList(llvm::Twine Name,
1060193326Sed                                     const char *Section,
1061193326Sed                                     const ConstantVector &Methods);
1062193326Sed
1063193326Sed  /// GetOrEmitProtocol - Get the protocol object for the given
1064193326Sed  /// declaration, emitting it if necessary. The return value has type
1065193326Sed  /// ProtocolPtrTy.
1066193326Sed  virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
1067193326Sed
1068193326Sed  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1069193326Sed  /// object for the given declaration, emitting it if needed. These
1070193326Sed  /// forward references will be filled in with empty bodies if no
1071193326Sed  /// definition is seen. The return value has type ProtocolPtrTy.
1072193326Sed  virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
1073193326Sed
1074193326Sed  /// EmitProtocolExtension - Generate the protocol extension
1075193326Sed  /// structure used to store optional instance and class methods, and
1076193326Sed  /// protocol properties. The return value has type
1077193326Sed  /// ProtocolExtensionPtrTy.
1078193326Sed  llvm::Constant *
1079193326Sed  EmitProtocolExtension(const ObjCProtocolDecl *PD,
1080193326Sed                        const ConstantVector &OptInstanceMethods,
1081193326Sed                        const ConstantVector &OptClassMethods);
1082193326Sed
1083193326Sed  /// EmitProtocolList - Generate the list of referenced
1084193326Sed  /// protocols. The return value has type ProtocolListPtrTy.
1085198398Srdivacky  llvm::Constant *EmitProtocolList(llvm::Twine Name,
1086193326Sed                                   ObjCProtocolDecl::protocol_iterator begin,
1087193326Sed                                   ObjCProtocolDecl::protocol_iterator end);
1088193326Sed
1089193326Sed  /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1090193326Sed  /// for the given selector.
1091193326Sed  llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
1092198092Srdivacky
1093198092Srdivackypublic:
1094193326Sed  CGObjCMac(CodeGen::CodeGenModule &cgm);
1095193326Sed
1096193326Sed  virtual llvm::Function *ModuleInitFunction();
1097198092Srdivacky
1098193326Sed  virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1099193326Sed                                              QualType ResultType,
1100193326Sed                                              Selector Sel,
1101193326Sed                                              llvm::Value *Receiver,
1102193326Sed                                              bool IsClassMessage,
1103193326Sed                                              const CallArgList &CallArgs,
1104193326Sed                                              const ObjCMethodDecl *Method);
1105193326Sed
1106198092Srdivacky  virtual CodeGen::RValue
1107193326Sed  GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1108193326Sed                           QualType ResultType,
1109193326Sed                           Selector Sel,
1110193326Sed                           const ObjCInterfaceDecl *Class,
1111193326Sed                           bool isCategoryImpl,
1112193326Sed                           llvm::Value *Receiver,
1113193326Sed                           bool IsClassMessage,
1114198092Srdivacky                           const CallArgList &CallArgs,
1115198092Srdivacky                           const ObjCMethodDecl *Method);
1116198092Srdivacky
1117193326Sed  virtual llvm::Value *GetClass(CGBuilderTy &Builder,
1118193326Sed                                const ObjCInterfaceDecl *ID);
1119193326Sed
1120193326Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel);
1121193326Sed
1122193326Sed  /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1123193326Sed  /// untyped one.
1124193326Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1125193326Sed                                   const ObjCMethodDecl *Method);
1126193326Sed
1127193326Sed  virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
1128193326Sed
1129193326Sed  virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
1130193326Sed
1131193326Sed  virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
1132193326Sed                                           const ObjCProtocolDecl *PD);
1133198092Srdivacky
1134193326Sed  virtual llvm::Constant *GetPropertyGetFunction();
1135193326Sed  virtual llvm::Constant *GetPropertySetFunction();
1136193326Sed  virtual llvm::Constant *EnumerationMutationFunction();
1137198092Srdivacky
1138193326Sed  virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1139193326Sed                                         const Stmt &S);
1140193326Sed  virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1141193326Sed                             const ObjCAtThrowStmt &S);
1142193326Sed  virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1143198092Srdivacky                                         llvm::Value *AddrWeakObj);
1144193326Sed  virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1145198092Srdivacky                                  llvm::Value *src, llvm::Value *dst);
1146193326Sed  virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1147193326Sed                                    llvm::Value *src, llvm::Value *dest);
1148193326Sed  virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1149198092Srdivacky                                  llvm::Value *src, llvm::Value *dest,
1150198092Srdivacky                                  llvm::Value *ivarOffset);
1151193326Sed  virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1152193326Sed                                        llvm::Value *src, llvm::Value *dest);
1153198092Srdivacky  virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1154198092Srdivacky                                        llvm::Value *dest, llvm::Value *src,
1155198092Srdivacky                                        QualType Ty);
1156198092Srdivacky
1157193326Sed  virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1158193326Sed                                      QualType ObjectTy,
1159193326Sed                                      llvm::Value *BaseValue,
1160193326Sed                                      const ObjCIvarDecl *Ivar,
1161193326Sed                                      unsigned CVRQualifiers);
1162193326Sed  virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1163193326Sed                                      const ObjCInterfaceDecl *Interface,
1164193326Sed                                      const ObjCIvarDecl *Ivar);
1165193326Sed};
1166198092Srdivacky
1167193326Sedclass CGObjCNonFragileABIMac : public CGObjCCommonMac {
1168193326Sedprivate:
1169193326Sed  ObjCNonFragileABITypesHelper ObjCTypes;
1170193326Sed  llvm::GlobalVariable* ObjCEmptyCacheVar;
1171193326Sed  llvm::GlobalVariable* ObjCEmptyVtableVar;
1172198092Srdivacky
1173193326Sed  /// SuperClassReferences - uniqued super class references.
1174193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
1175198092Srdivacky
1176193326Sed  /// MetaClassReferences - uniqued meta class references.
1177193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
1178193326Sed
1179193326Sed  /// EHTypeReferences - uniqued class ehtype references.
1180193326Sed  llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
1181198092Srdivacky
1182193326Sed  /// NonLegacyDispatchMethods - List of methods for which we do *not* generate
1183193326Sed  /// legacy messaging dispatch.
1184193326Sed  llvm::DenseSet<Selector> NonLegacyDispatchMethods;
1185198092Srdivacky
1186199482Srdivacky  /// DefinedMetaClasses - List of defined meta-classes.
1187199482Srdivacky  std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1188199482Srdivacky
1189193326Sed  /// LegacyDispatchedSelector - Returns true if SEL is not in the list of
1190193326Sed  /// NonLegacyDispatchMethods; false otherwise.
1191193326Sed  bool LegacyDispatchedSelector(Selector Sel);
1192198092Srdivacky
1193193326Sed  /// FinishNonFragileABIModule - Write out global data structures at the end of
1194193326Sed  /// processing a translation unit.
1195193326Sed  void FinishNonFragileABIModule();
1196193326Sed
1197193326Sed  /// AddModuleClassList - Add the given list of class pointers to the
1198193326Sed  /// module with the provided symbol and section names.
1199193326Sed  void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container,
1200193326Sed                          const char *SymbolName,
1201193326Sed                          const char *SectionName);
1202193326Sed
1203198092Srdivacky  llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1204198092Srdivacky                                              unsigned InstanceStart,
1205198092Srdivacky                                              unsigned InstanceSize,
1206198092Srdivacky                                              const ObjCImplementationDecl *ID);
1207193326Sed  llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
1208198092Srdivacky                                            llvm::Constant *IsAGV,
1209193326Sed                                            llvm::Constant *SuperClassGV,
1210193326Sed                                            llvm::Constant *ClassRoGV,
1211193326Sed                                            bool HiddenVisibility);
1212198092Srdivacky
1213193326Sed  llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
1214198092Srdivacky
1215193326Sed  llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
1216198092Srdivacky
1217193326Sed  /// EmitMethodList - Emit the method list for the given
1218193326Sed  /// implementation. The return value has type MethodListnfABITy.
1219198398Srdivacky  llvm::Constant *EmitMethodList(llvm::Twine Name,
1220193326Sed                                 const char *Section,
1221193326Sed                                 const ConstantVector &Methods);
1222193326Sed  /// EmitIvarList - Emit the ivar list for the given
1223193326Sed  /// implementation. If ForClass is true the list of class ivars
1224193326Sed  /// (i.e. metaclass ivars) is emitted, otherwise the list of
1225193326Sed  /// interface ivars will be emitted. The return value has type
1226193326Sed  /// IvarListnfABIPtrTy.
1227193326Sed  llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
1228198092Srdivacky
1229193326Sed  llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
1230193326Sed                                    const ObjCIvarDecl *Ivar,
1231193326Sed                                    unsigned long int offset);
1232198092Srdivacky
1233193326Sed  /// GetOrEmitProtocol - Get the protocol object for the given
1234193326Sed  /// declaration, emitting it if necessary. The return value has type
1235193326Sed  /// ProtocolPtrTy.
1236193326Sed  virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
1237198092Srdivacky
1238193326Sed  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1239193326Sed  /// object for the given declaration, emitting it if needed. These
1240193326Sed  /// forward references will be filled in with empty bodies if no
1241193326Sed  /// definition is seen. The return value has type ProtocolPtrTy.
1242193326Sed  virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
1243198092Srdivacky
1244193326Sed  /// EmitProtocolList - Generate the list of referenced
1245193326Sed  /// protocols. The return value has type ProtocolListPtrTy.
1246198398Srdivacky  llvm::Constant *EmitProtocolList(llvm::Twine Name,
1247193326Sed                                   ObjCProtocolDecl::protocol_iterator begin,
1248193326Sed                                   ObjCProtocolDecl::protocol_iterator end);
1249198092Srdivacky
1250193326Sed  CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1251193326Sed                                  QualType ResultType,
1252193326Sed                                  Selector Sel,
1253193326Sed                                  llvm::Value *Receiver,
1254193326Sed                                  QualType Arg0Ty,
1255193326Sed                                  bool IsSuper,
1256193326Sed                                  const CallArgList &CallArgs);
1257193326Sed
1258193326Sed  /// GetClassGlobal - Return the global variable for the Objective-C
1259193326Sed  /// class of the given name.
1260193326Sed  llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
1261198092Srdivacky
1262193326Sed  /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1263193326Sed  /// for the given class reference.
1264198092Srdivacky  llvm::Value *EmitClassRef(CGBuilderTy &Builder,
1265193326Sed                            const ObjCInterfaceDecl *ID);
1266198092Srdivacky
1267193326Sed  /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1268193326Sed  /// for the given super class reference.
1269198092Srdivacky  llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1270198092Srdivacky                                 const ObjCInterfaceDecl *ID);
1271198092Srdivacky
1272193326Sed  /// EmitMetaClassRef - Return a Value * of the address of _class_t
1273193326Sed  /// meta-data
1274198092Srdivacky  llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
1275193326Sed                                const ObjCInterfaceDecl *ID);
1276193326Sed
1277193326Sed  /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1278193326Sed  /// the given ivar.
1279193326Sed  ///
1280193326Sed  llvm::GlobalVariable * ObjCIvarOffsetVariable(
1281198092Srdivacky    const ObjCInterfaceDecl *ID,
1282198092Srdivacky    const ObjCIvarDecl *Ivar);
1283198092Srdivacky
1284193326Sed  /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1285193326Sed  /// for the given selector.
1286193326Sed  llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
1287193326Sed
1288193326Sed  /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
1289193326Sed  /// interface. The return value has type EHTypePtrTy.
1290193326Sed  llvm::Value *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
1291193326Sed                                  bool ForDefinition);
1292193326Sed
1293198092Srdivacky  const char *getMetaclassSymbolPrefix() const {
1294193326Sed    return "OBJC_METACLASS_$_";
1295193326Sed  }
1296198092Srdivacky
1297193326Sed  const char *getClassSymbolPrefix() const {
1298193326Sed    return "OBJC_CLASS_$_";
1299193326Sed  }
1300193326Sed
1301193326Sed  void GetClassSizeInfo(const ObjCImplementationDecl *OID,
1302193326Sed                        uint32_t &InstanceStart,
1303193326Sed                        uint32_t &InstanceSize);
1304198092Srdivacky
1305193326Sed  // Shamelessly stolen from Analysis/CFRefCount.cpp
1306193326Sed  Selector GetNullarySelector(const char* name) const {
1307193326Sed    IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1308193326Sed    return CGM.getContext().Selectors.getSelector(0, &II);
1309193326Sed  }
1310198092Srdivacky
1311193326Sed  Selector GetUnarySelector(const char* name) const {
1312193326Sed    IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1313193326Sed    return CGM.getContext().Selectors.getSelector(1, &II);
1314193326Sed  }
1315193326Sed
1316193326Sed  /// ImplementationIsNonLazy - Check whether the given category or
1317193326Sed  /// class implementation is "non-lazy".
1318193326Sed  bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
1319193326Sed
1320193326Sedpublic:
1321193326Sed  CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
1322193326Sed  // FIXME. All stubs for now!
1323193326Sed  virtual llvm::Function *ModuleInitFunction();
1324198092Srdivacky
1325193326Sed  virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1326193326Sed                                              QualType ResultType,
1327193326Sed                                              Selector Sel,
1328193326Sed                                              llvm::Value *Receiver,
1329193326Sed                                              bool IsClassMessage,
1330193326Sed                                              const CallArgList &CallArgs,
1331193326Sed                                              const ObjCMethodDecl *Method);
1332198092Srdivacky
1333198092Srdivacky  virtual CodeGen::RValue
1334193326Sed  GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1335193326Sed                           QualType ResultType,
1336193326Sed                           Selector Sel,
1337193326Sed                           const ObjCInterfaceDecl *Class,
1338193326Sed                           bool isCategoryImpl,
1339193326Sed                           llvm::Value *Receiver,
1340193326Sed                           bool IsClassMessage,
1341198092Srdivacky                           const CallArgList &CallArgs,
1342198092Srdivacky                           const ObjCMethodDecl *Method);
1343198092Srdivacky
1344193326Sed  virtual llvm::Value *GetClass(CGBuilderTy &Builder,
1345193326Sed                                const ObjCInterfaceDecl *ID);
1346198092Srdivacky
1347193326Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel)
1348193326Sed    { return EmitSelector(Builder, Sel); }
1349193326Sed
1350193326Sed  /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1351193326Sed  /// untyped one.
1352193326Sed  virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1353193326Sed                                   const ObjCMethodDecl *Method)
1354193326Sed    { return EmitSelector(Builder, Method->getSelector()); }
1355198092Srdivacky
1356193326Sed  virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
1357198092Srdivacky
1358193326Sed  virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
1359193326Sed  virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
1360193326Sed                                           const ObjCProtocolDecl *PD);
1361198092Srdivacky
1362198092Srdivacky  virtual llvm::Constant *GetPropertyGetFunction() {
1363193326Sed    return ObjCTypes.getGetPropertyFn();
1364193326Sed  }
1365198092Srdivacky  virtual llvm::Constant *GetPropertySetFunction() {
1366198092Srdivacky    return ObjCTypes.getSetPropertyFn();
1367193326Sed  }
1368193326Sed  virtual llvm::Constant *EnumerationMutationFunction() {
1369193326Sed    return ObjCTypes.getEnumerationMutationFn();
1370193326Sed  }
1371198092Srdivacky
1372193326Sed  virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1373193326Sed                                         const Stmt &S);
1374193326Sed  virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1375193326Sed                             const ObjCAtThrowStmt &S);
1376193326Sed  virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1377193326Sed                                         llvm::Value *AddrWeakObj);
1378193326Sed  virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1379193326Sed                                  llvm::Value *src, llvm::Value *dst);
1380193326Sed  virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1381193326Sed                                    llvm::Value *src, llvm::Value *dest);
1382193326Sed  virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1383198092Srdivacky                                  llvm::Value *src, llvm::Value *dest,
1384198092Srdivacky                                  llvm::Value *ivarOffset);
1385193326Sed  virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1386193326Sed                                        llvm::Value *src, llvm::Value *dest);
1387198092Srdivacky  virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1388198092Srdivacky                                        llvm::Value *dest, llvm::Value *src,
1389198092Srdivacky                                        QualType Ty);
1390193326Sed  virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1391193326Sed                                      QualType ObjectTy,
1392193326Sed                                      llvm::Value *BaseValue,
1393193326Sed                                      const ObjCIvarDecl *Ivar,
1394193326Sed                                      unsigned CVRQualifiers);
1395193326Sed  virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1396193326Sed                                      const ObjCInterfaceDecl *Interface,
1397193326Sed                                      const ObjCIvarDecl *Ivar);
1398193326Sed};
1399198092Srdivacky
1400193326Sed} // end anonymous namespace
1401193326Sed
1402193326Sed/* *** Helper Functions *** */
1403193326Sed
1404193326Sed/// getConstantGEP() - Help routine to construct simple GEPs.
1405198092Srdivackystatic llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
1406198092Srdivacky                                      llvm::Constant *C,
1407193326Sed                                      unsigned idx0,
1408193326Sed                                      unsigned idx1) {
1409193326Sed  llvm::Value *Idxs[] = {
1410198092Srdivacky    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1411198092Srdivacky    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
1412193326Sed  };
1413193326Sed  return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
1414193326Sed}
1415193326Sed
1416193326Sed/// hasObjCExceptionAttribute - Return true if this class or any super
1417193326Sed/// class has the __objc_exception__ attribute.
1418198092Srdivackystatic bool hasObjCExceptionAttribute(ASTContext &Context,
1419194613Sed                                      const ObjCInterfaceDecl *OID) {
1420195341Sed  if (OID->hasAttr<ObjCExceptionAttr>())
1421193326Sed    return true;
1422193326Sed  if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
1423194613Sed    return hasObjCExceptionAttribute(Context, Super);
1424193326Sed  return false;
1425193326Sed}
1426193326Sed
1427193326Sed/* *** CGObjCMac Public Interface *** */
1428198092Srdivacky
1429193326SedCGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
1430198092Srdivacky                                                    ObjCTypes(cgm) {
1431193326Sed  ObjCABI = 1;
1432198092Srdivacky  EmitImageInfo();
1433193326Sed}
1434193326Sed
1435193326Sed/// GetClass - Return a reference to the class for the given interface
1436193326Sed/// decl.
1437193326Sedllvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
1438193326Sed                                 const ObjCInterfaceDecl *ID) {
1439193326Sed  return EmitClassRef(Builder, ID);
1440193326Sed}
1441193326Sed
1442193326Sed/// GetSelector - Return the pointer to the unique'd string for this selector.
1443193326Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) {
1444193326Sed  return EmitSelector(Builder, Sel);
1445193326Sed}
1446193326Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
1447198092Srdivacky                                    *Method) {
1448193326Sed  return EmitSelector(Builder, Method->getSelector());
1449193326Sed}
1450193326Sed
1451193326Sed/// Generate a constant CFString object.
1452198092Srdivacky/*
1453198092Srdivacky  struct __builtin_CFString {
1454198092Srdivacky  const int *isa; // point to __CFConstantStringClassReference
1455198092Srdivacky  int flags;
1456198092Srdivacky  const char *str;
1457198092Srdivacky  long length;
1458198092Srdivacky  };
1459193326Sed*/
1460193326Sed
1461193326Sedllvm::Constant *CGObjCCommonMac::GenerateConstantString(
1462202879Srdivacky  const StringLiteral *SL) {
1463202879Srdivacky  return CGM.GetAddrOfConstantCFString(SL);
1464193326Sed}
1465193326Sed
1466193326Sed/// Generates a message send where the super is the receiver.  This is
1467193326Sed/// a message send to self with special delivery semantics indicating
1468193326Sed/// which class's method should be called.
1469193326SedCodeGen::RValue
1470193326SedCGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1471193326Sed                                    QualType ResultType,
1472193326Sed                                    Selector Sel,
1473193326Sed                                    const ObjCInterfaceDecl *Class,
1474193326Sed                                    bool isCategoryImpl,
1475193326Sed                                    llvm::Value *Receiver,
1476193326Sed                                    bool IsClassMessage,
1477198092Srdivacky                                    const CodeGen::CallArgList &CallArgs,
1478198092Srdivacky                                    const ObjCMethodDecl *Method) {
1479193326Sed  // Create and init a super structure; this is a (receiver, class)
1480193326Sed  // pair we will pass to objc_msgSendSuper.
1481198092Srdivacky  llvm::Value *ObjCSuper =
1482193326Sed    CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
1483198092Srdivacky  llvm::Value *ReceiverAsObject =
1484193326Sed    CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
1485198092Srdivacky  CGF.Builder.CreateStore(ReceiverAsObject,
1486193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 0));
1487193326Sed
1488193326Sed  // If this is a class message the metaclass is passed as the target.
1489193326Sed  llvm::Value *Target;
1490193326Sed  if (IsClassMessage) {
1491193326Sed    if (isCategoryImpl) {
1492193326Sed      // Message sent to 'super' in a class method defined in a category
1493193326Sed      // implementation requires an odd treatment.
1494193326Sed      // If we are in a class method, we must retrieve the
1495193326Sed      // _metaclass_ for the current class, pointed at by
1496193326Sed      // the class's "isa" pointer.  The following assumes that
1497193326Sed      // isa" is the first ivar in a class (which it must be).
1498193326Sed      Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1499193326Sed      Target = CGF.Builder.CreateStructGEP(Target, 0);
1500193326Sed      Target = CGF.Builder.CreateLoad(Target);
1501198092Srdivacky    } else {
1502193326Sed      llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1503193326Sed      llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1504193326Sed      llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1505193326Sed      Target = Super;
1506198092Srdivacky    }
1507199482Srdivacky  }
1508199482Srdivacky  else if (isCategoryImpl)
1509193326Sed    Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1510199482Srdivacky  else {
1511199482Srdivacky    llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1512199482Srdivacky    ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1513199482Srdivacky    Target = CGF.Builder.CreateLoad(ClassPtr);
1514193326Sed  }
1515193326Sed  // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1516193326Sed  // ObjCTypes types.
1517198092Srdivacky  const llvm::Type *ClassTy =
1518193326Sed    CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
1519193326Sed  Target = CGF.Builder.CreateBitCast(Target, ClassTy);
1520198092Srdivacky  CGF.Builder.CreateStore(Target,
1521193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 1));
1522198092Srdivacky  return EmitLegacyMessageSend(CGF, ResultType,
1523193326Sed                               EmitSelector(CGF.Builder, Sel),
1524193326Sed                               ObjCSuper, ObjCTypes.SuperPtrCTy,
1525198092Srdivacky                               true, CallArgs, Method, ObjCTypes);
1526193326Sed}
1527198092Srdivacky
1528198092Srdivacky/// Generate code for a message send expression.
1529193326SedCodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1530193326Sed                                               QualType ResultType,
1531193326Sed                                               Selector Sel,
1532193326Sed                                               llvm::Value *Receiver,
1533193326Sed                                               bool IsClassMessage,
1534193326Sed                                               const CallArgList &CallArgs,
1535193326Sed                                               const ObjCMethodDecl *Method) {
1536193326Sed  return EmitLegacyMessageSend(CGF, ResultType,
1537193326Sed                               EmitSelector(CGF.Builder, Sel),
1538193326Sed                               Receiver, CGF.getContext().getObjCIdType(),
1539198092Srdivacky                               false, CallArgs, Method, ObjCTypes);
1540193326Sed}
1541193326Sed
1542198092SrdivackyCodeGen::RValue
1543198092SrdivackyCGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
1544198092Srdivacky                                       QualType ResultType,
1545198092Srdivacky                                       llvm::Value *Sel,
1546198092Srdivacky                                       llvm::Value *Arg0,
1547198092Srdivacky                                       QualType Arg0Ty,
1548198092Srdivacky                                       bool IsSuper,
1549198092Srdivacky                                       const CallArgList &CallArgs,
1550198092Srdivacky                                       const ObjCMethodDecl *Method,
1551198092Srdivacky                                       const ObjCCommonTypesHelper &ObjCTypes) {
1552193326Sed  CallArgList ActualArgs;
1553193326Sed  if (!IsSuper)
1554193326Sed    Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
1555193326Sed  ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
1556193326Sed  ActualArgs.push_back(std::make_pair(RValue::get(Sel),
1557193326Sed                                      CGF.getContext().getObjCSelType()));
1558193326Sed  ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
1559198092Srdivacky
1560193326Sed  CodeGenTypes &Types = CGM.getTypes();
1561203955Srdivacky  const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
1562203955Srdivacky                                                       CC_Default, false);
1563198092Srdivacky  const llvm::FunctionType *FTy =
1564198092Srdivacky    Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
1565198092Srdivacky
1566193326Sed  llvm::Constant *Fn = NULL;
1567193326Sed  if (CGM.ReturnTypeUsesSret(FnInfo)) {
1568193326Sed    Fn = (ObjCABI == 2) ?  ObjCTypes.getSendStretFn2(IsSuper)
1569198092Srdivacky      : ObjCTypes.getSendStretFn(IsSuper);
1570193326Sed  } else if (ResultType->isFloatingType()) {
1571193326Sed    if (ObjCABI == 2) {
1572198092Srdivacky      if (const BuiltinType *BT = ResultType->getAs<BuiltinType>()) {
1573193326Sed        BuiltinType::Kind k = BT->getKind();
1574193326Sed        Fn = (k == BuiltinType::LongDouble) ? ObjCTypes.getSendFpretFn2(IsSuper)
1575198092Srdivacky          : ObjCTypes.getSendFn2(IsSuper);
1576194179Sed      } else {
1577194179Sed        Fn = ObjCTypes.getSendFn2(IsSuper);
1578193326Sed      }
1579198092Srdivacky    } else
1580193326Sed      // FIXME. This currently matches gcc's API for x86-32. May need to change
1581193326Sed      // for others if we have their API.
1582193326Sed      Fn = ObjCTypes.getSendFpretFn(IsSuper);
1583193326Sed  } else {
1584193326Sed    Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
1585198092Srdivacky      : ObjCTypes.getSendFn(IsSuper);
1586193326Sed  }
1587193326Sed  assert(Fn && "EmitLegacyMessageSend - unknown API");
1588198092Srdivacky  Fn = llvm::ConstantExpr::getBitCast(Fn,
1589198092Srdivacky                                      llvm::PointerType::getUnqual(FTy));
1590201361Srdivacky  return CGF.EmitCall(FnInfo, Fn, ReturnValueSlot(), ActualArgs);
1591193326Sed}
1592193326Sed
1593198092Srdivackyllvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
1594193326Sed                                            const ObjCProtocolDecl *PD) {
1595193326Sed  // FIXME: I don't understand why gcc generates this, or where it is
1596193326Sed  // resolved. Investigate. Its also wasteful to look this up over and over.
1597193326Sed  LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1598193326Sed
1599193326Sed  return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
1600193326Sed                                        ObjCTypes.ExternalProtocolPtrTy);
1601193326Sed}
1602193326Sed
1603193326Sedvoid CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
1604193326Sed  // FIXME: We shouldn't need this, the protocol decl should contain enough
1605193326Sed  // information to tell us whether this was a declaration or a definition.
1606193326Sed  DefinedProtocols.insert(PD->getIdentifier());
1607193326Sed
1608193326Sed  // If we have generated a forward reference to this protocol, emit
1609193326Sed  // it now. Otherwise do nothing, the protocol objects are lazily
1610193326Sed  // emitted.
1611198092Srdivacky  if (Protocols.count(PD->getIdentifier()))
1612193326Sed    GetOrEmitProtocol(PD);
1613193326Sed}
1614193326Sed
1615193326Sedllvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
1616193326Sed  if (DefinedProtocols.count(PD->getIdentifier()))
1617193326Sed    return GetOrEmitProtocol(PD);
1618193326Sed  return GetOrEmitProtocolRef(PD);
1619193326Sed}
1620193326Sed
1621193326Sed/*
1622198092Srdivacky// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1623198092Srdivackystruct _objc_protocol {
1624198092Srdivackystruct _objc_protocol_extension *isa;
1625198092Srdivackychar *protocol_name;
1626198092Srdivackystruct _objc_protocol_list *protocol_list;
1627198092Srdivackystruct _objc__method_prototype_list *instance_methods;
1628198092Srdivackystruct _objc__method_prototype_list *class_methods
1629198092Srdivacky};
1630193326Sed
1631198092SrdivackySee EmitProtocolExtension().
1632193326Sed*/
1633193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1634193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1635193326Sed
1636193326Sed  // Early exit if a defining object has already been generated.
1637193326Sed  if (Entry && Entry->hasInitializer())
1638193326Sed    return Entry;
1639193326Sed
1640193326Sed  // FIXME: I don't understand why gcc generates this, or where it is
1641193326Sed  // resolved. Investigate. Its also wasteful to look this up over and over.
1642193326Sed  LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1643193326Sed
1644193326Sed  // Construct method lists.
1645193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1646193326Sed  std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
1647198092Srdivacky  for (ObjCProtocolDecl::instmeth_iterator
1648195341Sed         i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
1649193326Sed    ObjCMethodDecl *MD = *i;
1650193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
1651193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1652193326Sed      OptInstanceMethods.push_back(C);
1653193326Sed    } else {
1654193326Sed      InstanceMethods.push_back(C);
1655198092Srdivacky    }
1656193326Sed  }
1657193326Sed
1658198092Srdivacky  for (ObjCProtocolDecl::classmeth_iterator
1659195341Sed         i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
1660193326Sed    ObjCMethodDecl *MD = *i;
1661193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
1662193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1663193326Sed      OptClassMethods.push_back(C);
1664193326Sed    } else {
1665193326Sed      ClassMethods.push_back(C);
1666198092Srdivacky    }
1667193326Sed  }
1668193326Sed
1669193326Sed  std::vector<llvm::Constant*> Values(5);
1670193326Sed  Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
1671193326Sed  Values[1] = GetClassName(PD->getIdentifier());
1672198092Srdivacky  Values[2] =
1673198398Srdivacky    EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
1674193326Sed                     PD->protocol_begin(),
1675193326Sed                     PD->protocol_end());
1676198092Srdivacky  Values[3] =
1677198398Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
1678193326Sed                       "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1679193326Sed                       InstanceMethods);
1680198092Srdivacky  Values[4] =
1681198398Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
1682193326Sed                       "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1683193326Sed                       ClassMethods);
1684193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
1685193326Sed                                                   Values);
1686198092Srdivacky
1687193326Sed  if (Entry) {
1688193326Sed    // Already created, fix the linkage and update the initializer.
1689193326Sed    Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
1690193326Sed    Entry->setInitializer(Init);
1691193326Sed  } else {
1692198092Srdivacky    Entry =
1693198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
1694193326Sed                               llvm::GlobalValue::InternalLinkage,
1695198092Srdivacky                               Init,
1696198398Srdivacky                               "\01L_OBJC_PROTOCOL_" + PD->getName());
1697193326Sed    Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
1698193326Sed    Entry->setAlignment(4);
1699193326Sed    // FIXME: Is this necessary? Why only for protocol?
1700193326Sed    Entry->setAlignment(4);
1701193326Sed  }
1702198092Srdivacky  CGM.AddUsedGlobal(Entry);
1703193326Sed
1704193326Sed  return Entry;
1705193326Sed}
1706193326Sed
1707193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
1708193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1709193326Sed
1710193326Sed  if (!Entry) {
1711193326Sed    // We use the initializer as a marker of whether this is a forward
1712193326Sed    // reference or not. At module finalization we add the empty
1713193326Sed    // contents for protocols which were referenced but never defined.
1714198092Srdivacky    Entry =
1715198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
1716193326Sed                               llvm::GlobalValue::ExternalLinkage,
1717193326Sed                               0,
1718198398Srdivacky                               "\01L_OBJC_PROTOCOL_" + PD->getName());
1719193326Sed    Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
1720193326Sed    Entry->setAlignment(4);
1721193326Sed    // FIXME: Is this necessary? Why only for protocol?
1722193326Sed    Entry->setAlignment(4);
1723193326Sed  }
1724198092Srdivacky
1725193326Sed  return Entry;
1726193326Sed}
1727193326Sed
1728193326Sed/*
1729193326Sed  struct _objc_protocol_extension {
1730198092Srdivacky  uint32_t size;
1731198092Srdivacky  struct objc_method_description_list *optional_instance_methods;
1732198092Srdivacky  struct objc_method_description_list *optional_class_methods;
1733198092Srdivacky  struct objc_property_list *instance_properties;
1734193326Sed  };
1735193326Sed*/
1736193326Sedllvm::Constant *
1737193326SedCGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1738193326Sed                                 const ConstantVector &OptInstanceMethods,
1739193326Sed                                 const ConstantVector &OptClassMethods) {
1740198092Srdivacky  uint64_t Size =
1741193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
1742193326Sed  std::vector<llvm::Constant*> Values(4);
1743193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
1744198092Srdivacky  Values[1] =
1745198092Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
1746198398Srdivacky                       + PD->getName(),
1747193326Sed                       "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1748193326Sed                       OptInstanceMethods);
1749198092Srdivacky  Values[2] =
1750198398Srdivacky    EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
1751193326Sed                       "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1752193326Sed                       OptClassMethods);
1753198398Srdivacky  Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
1754193326Sed                               0, PD, ObjCTypes);
1755193326Sed
1756193326Sed  // Return null if no extension bits are used.
1757198092Srdivacky  if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
1758193326Sed      Values[3]->isNullValue())
1759193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
1760193326Sed
1761198092Srdivacky  llvm::Constant *Init =
1762193326Sed    llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
1763193326Sed
1764193326Sed  // No special section, but goes in llvm.used
1765198398Srdivacky  return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
1766198092Srdivacky                           Init,
1767193326Sed                           0, 0, true);
1768193326Sed}
1769193326Sed
1770193326Sed/*
1771193326Sed  struct objc_protocol_list {
1772198092Srdivacky  struct objc_protocol_list *next;
1773198092Srdivacky  long count;
1774198092Srdivacky  Protocol *list[];
1775193326Sed  };
1776193326Sed*/
1777193326Sedllvm::Constant *
1778198398SrdivackyCGObjCMac::EmitProtocolList(llvm::Twine Name,
1779193326Sed                            ObjCProtocolDecl::protocol_iterator begin,
1780193326Sed                            ObjCProtocolDecl::protocol_iterator end) {
1781193326Sed  std::vector<llvm::Constant*> ProtocolRefs;
1782193326Sed
1783193326Sed  for (; begin != end; ++begin)
1784193326Sed    ProtocolRefs.push_back(GetProtocolRef(*begin));
1785193326Sed
1786193326Sed  // Just return null for empty protocol lists
1787198092Srdivacky  if (ProtocolRefs.empty())
1788193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1789193326Sed
1790193326Sed  // This list is null terminated.
1791193326Sed  ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
1792193326Sed
1793193326Sed  std::vector<llvm::Constant*> Values(3);
1794193326Sed  // This field is only used by the runtime.
1795193326Sed  Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1796198092Srdivacky  Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
1797198092Srdivacky                                     ProtocolRefs.size() - 1);
1798198092Srdivacky  Values[2] =
1799198092Srdivacky    llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1800198092Srdivacky                                                  ProtocolRefs.size()),
1801193326Sed                             ProtocolRefs);
1802198092Srdivacky
1803198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
1804198092Srdivacky  llvm::GlobalVariable *GV =
1805193326Sed    CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1806193326Sed                      4, false);
1807193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
1808193326Sed}
1809193326Sed
1810200583Srdivackyvoid CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
1811200583Srdivacky                                   std::vector<llvm::Constant*> &Properties,
1812200583Srdivacky                                   const Decl *Container,
1813200583Srdivacky                                   const ObjCProtocolDecl *PROTO,
1814200583Srdivacky                                   const ObjCCommonTypesHelper &ObjCTypes) {
1815200583Srdivacky  std::vector<llvm::Constant*> Prop(2);
1816200583Srdivacky  for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
1817200583Srdivacky         E = PROTO->protocol_end(); P != E; ++P)
1818200583Srdivacky    PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
1819200583Srdivacky  for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
1820200583Srdivacky       E = PROTO->prop_end(); I != E; ++I) {
1821200583Srdivacky    const ObjCPropertyDecl *PD = *I;
1822200583Srdivacky    if (!PropertySet.insert(PD->getIdentifier()))
1823200583Srdivacky      continue;
1824200583Srdivacky    Prop[0] = GetPropertyName(PD->getIdentifier());
1825200583Srdivacky    Prop[1] = GetPropertyTypeString(PD, Container);
1826200583Srdivacky    Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
1827200583Srdivacky  }
1828200583Srdivacky}
1829200583Srdivacky
1830193326Sed/*
1831193326Sed  struct _objc_property {
1832198092Srdivacky  const char * const name;
1833198092Srdivacky  const char * const attributes;
1834193326Sed  };
1835193326Sed
1836193326Sed  struct _objc_property_list {
1837198092Srdivacky  uint32_t entsize; // sizeof (struct _objc_property)
1838198092Srdivacky  uint32_t prop_count;
1839198092Srdivacky  struct _objc_property[prop_count];
1840193326Sed  };
1841193326Sed*/
1842198398Srdivackyllvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
1843198092Srdivacky                                       const Decl *Container,
1844198092Srdivacky                                       const ObjCContainerDecl *OCD,
1845198092Srdivacky                                       const ObjCCommonTypesHelper &ObjCTypes) {
1846193326Sed  std::vector<llvm::Constant*> Properties, Prop(2);
1847200583Srdivacky  llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
1848198092Srdivacky  for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
1849198092Srdivacky         E = OCD->prop_end(); I != E; ++I) {
1850193326Sed    const ObjCPropertyDecl *PD = *I;
1851200583Srdivacky    PropertySet.insert(PD->getIdentifier());
1852193326Sed    Prop[0] = GetPropertyName(PD->getIdentifier());
1853193326Sed    Prop[1] = GetPropertyTypeString(PD, Container);
1854193326Sed    Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
1855193326Sed                                                   Prop));
1856193326Sed  }
1857200583Srdivacky  if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
1858200583Srdivacky    for (ObjCInterfaceDecl::protocol_iterator P = OID->protocol_begin(),
1859200583Srdivacky         E = OID->protocol_end(); P != E; ++P)
1860200583Srdivacky      PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
1861193326Sed
1862193326Sed  // Return null for empty list.
1863193326Sed  if (Properties.empty())
1864193326Sed    return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
1865193326Sed
1866198092Srdivacky  unsigned PropertySize =
1867193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
1868193326Sed  std::vector<llvm::Constant*> Values(3);
1869193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
1870193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
1871198092Srdivacky  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
1872193326Sed                                             Properties.size());
1873193326Sed  Values[2] = llvm::ConstantArray::get(AT, Properties);
1874198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
1875193326Sed
1876198092Srdivacky  llvm::GlobalVariable *GV =
1877198092Srdivacky    CreateMetadataVar(Name, Init,
1878198092Srdivacky                      (ObjCABI == 2) ? "__DATA, __objc_const" :
1879193326Sed                      "__OBJC,__property,regular,no_dead_strip",
1880198092Srdivacky                      (ObjCABI == 2) ? 8 : 4,
1881193326Sed                      true);
1882193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
1883193326Sed}
1884193326Sed
1885193326Sed/*
1886193326Sed  struct objc_method_description_list {
1887198092Srdivacky  int count;
1888198092Srdivacky  struct objc_method_description list[];
1889193326Sed  };
1890193326Sed*/
1891193326Sedllvm::Constant *
1892193326SedCGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
1893193326Sed  std::vector<llvm::Constant*> Desc(2);
1894198092Srdivacky  Desc[0] =
1895198092Srdivacky    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1896198092Srdivacky                                   ObjCTypes.SelectorPtrTy);
1897193326Sed  Desc[1] = GetMethodVarType(MD);
1898193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
1899193326Sed                                   Desc);
1900193326Sed}
1901193326Sed
1902198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
1903193326Sed                                              const char *Section,
1904193326Sed                                              const ConstantVector &Methods) {
1905193326Sed  // Return null for empty list.
1906193326Sed  if (Methods.empty())
1907193326Sed    return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
1908193326Sed
1909193326Sed  std::vector<llvm::Constant*> Values(2);
1910193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
1911198092Srdivacky  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
1912193326Sed                                             Methods.size());
1913193326Sed  Values[1] = llvm::ConstantArray::get(AT, Methods);
1914198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
1915193326Sed
1916193326Sed  llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
1917198092Srdivacky  return llvm::ConstantExpr::getBitCast(GV,
1918193326Sed                                        ObjCTypes.MethodDescriptionListPtrTy);
1919193326Sed}
1920193326Sed
1921193326Sed/*
1922193326Sed  struct _objc_category {
1923198092Srdivacky  char *category_name;
1924198092Srdivacky  char *class_name;
1925198092Srdivacky  struct _objc_method_list *instance_methods;
1926198092Srdivacky  struct _objc_method_list *class_methods;
1927198092Srdivacky  struct _objc_protocol_list *protocols;
1928198092Srdivacky  uint32_t size; // <rdar://4585769>
1929198092Srdivacky  struct _objc_property_list *instance_properties;
1930193326Sed  };
1931198092Srdivacky*/
1932193326Sedvoid CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
1933193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
1934193326Sed
1935193326Sed  // FIXME: This is poor design, the OCD should have a pointer to the category
1936193326Sed  // decl. Additionally, note that Category can be null for the @implementation
1937193326Sed  // w/o an @interface case. Sema should just create one for us as it does for
1938193326Sed  // @implementation so everyone else can live life under a clear blue sky.
1939193326Sed  const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
1940198092Srdivacky  const ObjCCategoryDecl *Category =
1941193326Sed    Interface->FindCategoryDeclaration(OCD->getIdentifier());
1942193326Sed
1943198398Srdivacky  llvm::SmallString<256> ExtName;
1944198398Srdivacky  llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
1945198398Srdivacky                                     << OCD->getName();
1946198398Srdivacky
1947193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1948198092Srdivacky  for (ObjCCategoryImplDecl::instmeth_iterator
1949195341Sed         i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
1950193326Sed    // Instance methods should always be defined.
1951193326Sed    InstanceMethods.push_back(GetMethodConstant(*i));
1952193326Sed  }
1953198092Srdivacky  for (ObjCCategoryImplDecl::classmeth_iterator
1954195341Sed         i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
1955193326Sed    // Class methods should always be defined.
1956193326Sed    ClassMethods.push_back(GetMethodConstant(*i));
1957193326Sed  }
1958193326Sed
1959193326Sed  std::vector<llvm::Constant*> Values(7);
1960193326Sed  Values[0] = GetClassName(OCD->getIdentifier());
1961193326Sed  Values[1] = GetClassName(Interface->getIdentifier());
1962193326Sed  LazySymbols.insert(Interface->getIdentifier());
1963198092Srdivacky  Values[2] =
1964198398Srdivacky    EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
1965193326Sed                   "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1966193326Sed                   InstanceMethods);
1967198092Srdivacky  Values[3] =
1968198398Srdivacky    EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
1969193326Sed                   "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1970193326Sed                   ClassMethods);
1971193326Sed  if (Category) {
1972198092Srdivacky    Values[4] =
1973198398Srdivacky      EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
1974193326Sed                       Category->protocol_begin(),
1975193326Sed                       Category->protocol_end());
1976193326Sed  } else {
1977193326Sed    Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1978193326Sed  }
1979193326Sed  Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
1980193326Sed
1981193326Sed  // If there is no category @interface then there can be no properties.
1982193326Sed  if (Category) {
1983198398Srdivacky    Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
1984193326Sed                                 OCD, Category, ObjCTypes);
1985193326Sed  } else {
1986193326Sed    Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
1987193326Sed  }
1988198092Srdivacky
1989193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
1990193326Sed                                                   Values);
1991193326Sed
1992198092Srdivacky  llvm::GlobalVariable *GV =
1993198398Srdivacky    CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
1994193326Sed                      "__OBJC,__category,regular,no_dead_strip",
1995193326Sed                      4, true);
1996193326Sed  DefinedCategories.push_back(GV);
1997193326Sed}
1998193326Sed
1999193326Sed// FIXME: Get from somewhere?
2000193326Sedenum ClassFlags {
2001193326Sed  eClassFlags_Factory              = 0x00001,
2002193326Sed  eClassFlags_Meta                 = 0x00002,
2003193326Sed  // <rdr://5142207>
2004193326Sed  eClassFlags_HasCXXStructors      = 0x02000,
2005193326Sed  eClassFlags_Hidden               = 0x20000,
2006193326Sed  eClassFlags_ABI2_Hidden          = 0x00010,
2007193326Sed  eClassFlags_ABI2_HasCXXStructors = 0x00004   // <rdr://4923634>
2008193326Sed};
2009193326Sed
2010193326Sed/*
2011193326Sed  struct _objc_class {
2012198092Srdivacky  Class isa;
2013198092Srdivacky  Class super_class;
2014198092Srdivacky  const char *name;
2015198092Srdivacky  long version;
2016198092Srdivacky  long info;
2017198092Srdivacky  long instance_size;
2018198092Srdivacky  struct _objc_ivar_list *ivars;
2019198092Srdivacky  struct _objc_method_list *methods;
2020198092Srdivacky  struct _objc_cache *cache;
2021198092Srdivacky  struct _objc_protocol_list *protocols;
2022198092Srdivacky  // Objective-C 1.0 extensions (<rdr://4585769>)
2023198092Srdivacky  const char *ivar_layout;
2024198092Srdivacky  struct _objc_class_ext *ext;
2025193326Sed  };
2026193326Sed
2027193326Sed  See EmitClassExtension();
2028198092Srdivacky*/
2029193326Sedvoid CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
2030193326Sed  DefinedSymbols.insert(ID->getIdentifier());
2031193326Sed
2032193326Sed  std::string ClassName = ID->getNameAsString();
2033193326Sed  // FIXME: Gross
2034198092Srdivacky  ObjCInterfaceDecl *Interface =
2035193326Sed    const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
2036198092Srdivacky  llvm::Constant *Protocols =
2037198398Srdivacky    EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
2038193326Sed                     Interface->protocol_begin(),
2039193326Sed                     Interface->protocol_end());
2040193326Sed  unsigned Flags = eClassFlags_Factory;
2041198092Srdivacky  unsigned Size =
2042193326Sed    CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8;
2043193326Sed
2044193326Sed  // FIXME: Set CXX-structors flag.
2045193326Sed  if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
2046193326Sed    Flags |= eClassFlags_Hidden;
2047193326Sed
2048193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2049198092Srdivacky  for (ObjCImplementationDecl::instmeth_iterator
2050195341Sed         i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
2051193326Sed    // Instance methods should always be defined.
2052193326Sed    InstanceMethods.push_back(GetMethodConstant(*i));
2053193326Sed  }
2054198092Srdivacky  for (ObjCImplementationDecl::classmeth_iterator
2055195341Sed         i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
2056193326Sed    // Class methods should always be defined.
2057193326Sed    ClassMethods.push_back(GetMethodConstant(*i));
2058193326Sed  }
2059193326Sed
2060198092Srdivacky  for (ObjCImplementationDecl::propimpl_iterator
2061195341Sed         i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
2062193326Sed    ObjCPropertyImplDecl *PID = *i;
2063193326Sed
2064193326Sed    if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2065193326Sed      ObjCPropertyDecl *PD = PID->getPropertyDecl();
2066193326Sed
2067193326Sed      if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
2068193326Sed        if (llvm::Constant *C = GetMethodConstant(MD))
2069193326Sed          InstanceMethods.push_back(C);
2070193326Sed      if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
2071193326Sed        if (llvm::Constant *C = GetMethodConstant(MD))
2072193326Sed          InstanceMethods.push_back(C);
2073193326Sed    }
2074193326Sed  }
2075193326Sed
2076193326Sed  std::vector<llvm::Constant*> Values(12);
2077193326Sed  Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
2078193326Sed  if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
2079193326Sed    // Record a reference to the super class.
2080193326Sed    LazySymbols.insert(Super->getIdentifier());
2081193326Sed
2082198092Srdivacky    Values[ 1] =
2083193326Sed      llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
2084193326Sed                                     ObjCTypes.ClassPtrTy);
2085193326Sed  } else {
2086193326Sed    Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
2087193326Sed  }
2088193326Sed  Values[ 2] = GetClassName(ID->getIdentifier());
2089193326Sed  // Version is always 0.
2090193326Sed  Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2091193326Sed  Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2092193326Sed  Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
2093193326Sed  Values[ 6] = EmitIvarList(ID, false);
2094198092Srdivacky  Values[ 7] =
2095198398Srdivacky    EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
2096193326Sed                   "__OBJC,__inst_meth,regular,no_dead_strip",
2097193326Sed                   InstanceMethods);
2098193326Sed  // cache is always NULL.
2099193326Sed  Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
2100193326Sed  Values[ 9] = Protocols;
2101198092Srdivacky  Values[10] = BuildIvarLayout(ID, true);
2102193326Sed  Values[11] = EmitClassExtension(ID);
2103193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
2104193326Sed                                                   Values);
2105199482Srdivacky  std::string Name("\01L_OBJC_CLASS_");
2106199482Srdivacky  Name += ClassName;
2107199482Srdivacky  const char *Section = "__OBJC,__class,regular,no_dead_strip";
2108199482Srdivacky  // Check for a forward reference.
2109199482Srdivacky  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2110199482Srdivacky  if (GV) {
2111199482Srdivacky    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2112199482Srdivacky           "Forward metaclass reference has incorrect type.");
2113199482Srdivacky    GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2114199482Srdivacky    GV->setInitializer(Init);
2115199482Srdivacky    GV->setSection(Section);
2116199482Srdivacky    GV->setAlignment(4);
2117199482Srdivacky    CGM.AddUsedGlobal(GV);
2118199482Srdivacky  }
2119199482Srdivacky  else
2120199482Srdivacky    GV = CreateMetadataVar(Name, Init, Section, 4, true);
2121193326Sed  DefinedClasses.push_back(GV);
2122193326Sed}
2123193326Sed
2124193326Sedllvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2125193326Sed                                         llvm::Constant *Protocols,
2126193326Sed                                         const ConstantVector &Methods) {
2127193326Sed  unsigned Flags = eClassFlags_Meta;
2128193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
2129193326Sed
2130193326Sed  if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
2131193326Sed    Flags |= eClassFlags_Hidden;
2132198092Srdivacky
2133193326Sed  std::vector<llvm::Constant*> Values(12);
2134193326Sed  // The isa for the metaclass is the root of the hierarchy.
2135193326Sed  const ObjCInterfaceDecl *Root = ID->getClassInterface();
2136193326Sed  while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2137193326Sed    Root = Super;
2138198092Srdivacky  Values[ 0] =
2139193326Sed    llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
2140193326Sed                                   ObjCTypes.ClassPtrTy);
2141193326Sed  // The super class for the metaclass is emitted as the name of the
2142193326Sed  // super class. The runtime fixes this up to point to the
2143193326Sed  // *metaclass* for the super class.
2144193326Sed  if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
2145198092Srdivacky    Values[ 1] =
2146193326Sed      llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
2147193326Sed                                     ObjCTypes.ClassPtrTy);
2148193326Sed  } else {
2149193326Sed    Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
2150193326Sed  }
2151193326Sed  Values[ 2] = GetClassName(ID->getIdentifier());
2152193326Sed  // Version is always 0.
2153193326Sed  Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2154193326Sed  Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2155193326Sed  Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
2156193326Sed  Values[ 6] = EmitIvarList(ID, true);
2157198092Srdivacky  Values[ 7] =
2158193326Sed    EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
2159193326Sed                   "__OBJC,__cls_meth,regular,no_dead_strip",
2160193326Sed                   Methods);
2161193326Sed  // cache is always NULL.
2162193326Sed  Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
2163193326Sed  Values[ 9] = Protocols;
2164193326Sed  // ivar_layout for metaclass is always NULL.
2165193326Sed  Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
2166193326Sed  // The class extension is always unused for metaclasses.
2167193326Sed  Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
2168193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
2169193326Sed                                                   Values);
2170193326Sed
2171193326Sed  std::string Name("\01L_OBJC_METACLASS_");
2172193326Sed  Name += ID->getNameAsCString();
2173193326Sed
2174193326Sed  // Check for a forward reference.
2175193326Sed  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2176193326Sed  if (GV) {
2177193326Sed    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2178193326Sed           "Forward metaclass reference has incorrect type.");
2179193326Sed    GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2180193326Sed    GV->setInitializer(Init);
2181193326Sed  } else {
2182198092Srdivacky    GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2183193326Sed                                  llvm::GlobalValue::InternalLinkage,
2184198092Srdivacky                                  Init, Name);
2185193326Sed  }
2186193326Sed  GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
2187193326Sed  GV->setAlignment(4);
2188198092Srdivacky  CGM.AddUsedGlobal(GV);
2189193326Sed
2190193326Sed  return GV;
2191193326Sed}
2192193326Sed
2193198092Srdivackyllvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
2194193326Sed  std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
2195193326Sed
2196193326Sed  // FIXME: Should we look these up somewhere other than the module. Its a bit
2197193326Sed  // silly since we only generate these while processing an implementation, so
2198193326Sed  // exactly one pointer would work if know when we entered/exitted an
2199193326Sed  // implementation block.
2200193326Sed
2201193326Sed  // Check for an existing forward reference.
2202193326Sed  // Previously, metaclass with internal linkage may have been defined.
2203193326Sed  // pass 'true' as 2nd argument so it is returned.
2204198092Srdivacky  if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2205198092Srdivacky                                                                   true)) {
2206193326Sed    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2207193326Sed           "Forward metaclass reference has incorrect type.");
2208193326Sed    return GV;
2209193326Sed  } else {
2210193326Sed    // Generate as an external reference to keep a consistent
2211193326Sed    // module. This will be patched up when we emit the metaclass.
2212198092Srdivacky    return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2213193326Sed                                    llvm::GlobalValue::ExternalLinkage,
2214193326Sed                                    0,
2215198092Srdivacky                                    Name);
2216193326Sed  }
2217193326Sed}
2218193326Sed
2219199482Srdivackyllvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2220199482Srdivacky  std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2221199482Srdivacky
2222199482Srdivacky  if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2223199482Srdivacky                                                                   true)) {
2224199482Srdivacky    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2225199482Srdivacky           "Forward class metadata reference has incorrect type.");
2226199482Srdivacky    return GV;
2227199482Srdivacky  } else {
2228199482Srdivacky    return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2229199482Srdivacky                                    llvm::GlobalValue::ExternalLinkage,
2230199482Srdivacky                                    0,
2231199482Srdivacky                                    Name);
2232199482Srdivacky  }
2233199482Srdivacky}
2234199482Srdivacky
2235193326Sed/*
2236193326Sed  struct objc_class_ext {
2237198092Srdivacky  uint32_t size;
2238198092Srdivacky  const char *weak_ivar_layout;
2239198092Srdivacky  struct _objc_property_list *properties;
2240193326Sed  };
2241193326Sed*/
2242193326Sedllvm::Constant *
2243193326SedCGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
2244198092Srdivacky  uint64_t Size =
2245193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
2246193326Sed
2247193326Sed  std::vector<llvm::Constant*> Values(3);
2248193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
2249193326Sed  Values[1] = BuildIvarLayout(ID, false);
2250198398Srdivacky  Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
2251193326Sed                               ID, ID->getClassInterface(), ObjCTypes);
2252193326Sed
2253193326Sed  // Return null if no extension bits are used.
2254193326Sed  if (Values[1]->isNullValue() && Values[2]->isNullValue())
2255193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
2256193326Sed
2257198092Srdivacky  llvm::Constant *Init =
2258193326Sed    llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
2259198398Srdivacky  return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
2260198092Srdivacky                           Init, "__OBJC,__class_ext,regular,no_dead_strip",
2261193326Sed                           4, true);
2262193326Sed}
2263193326Sed
2264193326Sed/*
2265193326Sed  struct objc_ivar {
2266198092Srdivacky  char *ivar_name;
2267198092Srdivacky  char *ivar_type;
2268198092Srdivacky  int ivar_offset;
2269193326Sed  };
2270193326Sed
2271193326Sed  struct objc_ivar_list {
2272198092Srdivacky  int ivar_count;
2273198092Srdivacky  struct objc_ivar list[count];
2274193326Sed  };
2275198092Srdivacky*/
2276193326Sedllvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
2277193326Sed                                        bool ForClass) {
2278193326Sed  std::vector<llvm::Constant*> Ivars, Ivar(3);
2279193326Sed
2280193326Sed  // When emitting the root class GCC emits ivar entries for the
2281193326Sed  // actual class structure. It is not clear if we need to follow this
2282193326Sed  // behavior; for now lets try and get away with not doing it. If so,
2283193326Sed  // the cleanest solution would be to make up an ObjCInterfaceDecl
2284193326Sed  // for the class.
2285193326Sed  if (ForClass)
2286193326Sed    return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
2287198092Srdivacky
2288198092Srdivacky  ObjCInterfaceDecl *OID =
2289193326Sed    const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
2290198092Srdivacky
2291193326Sed  llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
2292193576Sed  CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
2293198092Srdivacky
2294193326Sed  for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2295193326Sed    ObjCIvarDecl *IVD = OIvars[i];
2296193576Sed    // Ignore unnamed bit-fields.
2297193576Sed    if (!IVD->getDeclName())
2298198092Srdivacky      continue;
2299193326Sed    Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2300193326Sed    Ivar[1] = GetMethodVarType(IVD);
2301198092Srdivacky    Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
2302193326Sed                                     ComputeIvarBaseOffset(CGM, OID, IVD));
2303193326Sed    Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
2304193326Sed  }
2305193326Sed
2306193326Sed  // Return null for empty list.
2307193326Sed  if (Ivars.empty())
2308193326Sed    return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
2309193326Sed
2310193326Sed  std::vector<llvm::Constant*> Values(2);
2311193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
2312193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
2313193326Sed                                             Ivars.size());
2314193326Sed  Values[1] = llvm::ConstantArray::get(AT, Ivars);
2315198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
2316193326Sed
2317193326Sed  llvm::GlobalVariable *GV;
2318193326Sed  if (ForClass)
2319198398Srdivacky    GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
2320198092Srdivacky                           Init, "__OBJC,__class_vars,regular,no_dead_strip",
2321193326Sed                           4, true);
2322193326Sed  else
2323198398Srdivacky    GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
2324193326Sed                           Init, "__OBJC,__instance_vars,regular,no_dead_strip",
2325193326Sed                           4, true);
2326193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
2327193326Sed}
2328193326Sed
2329193326Sed/*
2330193326Sed  struct objc_method {
2331198092Srdivacky  SEL method_name;
2332198092Srdivacky  char *method_types;
2333198092Srdivacky  void *method;
2334193326Sed  };
2335198092Srdivacky
2336193326Sed  struct objc_method_list {
2337198092Srdivacky  struct objc_method_list *obsolete;
2338198092Srdivacky  int count;
2339198092Srdivacky  struct objc_method methods_list[count];
2340193326Sed  };
2341193326Sed*/
2342193326Sed
2343193326Sed/// GetMethodConstant - Return a struct objc_method constant for the
2344193326Sed/// given method if it has been defined. The result is null if the
2345193326Sed/// method has not been defined. The return value has type MethodPtrTy.
2346193326Sedllvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
2347193326Sed  // FIXME: Use DenseMap::lookup
2348193326Sed  llvm::Function *Fn = MethodDefinitions[MD];
2349193326Sed  if (!Fn)
2350193326Sed    return 0;
2351198092Srdivacky
2352193326Sed  std::vector<llvm::Constant*> Method(3);
2353198092Srdivacky  Method[0] =
2354193326Sed    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
2355193326Sed                                   ObjCTypes.SelectorPtrTy);
2356193326Sed  Method[1] = GetMethodVarType(MD);
2357193326Sed  Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
2358193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
2359193326Sed}
2360193326Sed
2361198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
2362193326Sed                                          const char *Section,
2363193326Sed                                          const ConstantVector &Methods) {
2364193326Sed  // Return null for empty list.
2365193326Sed  if (Methods.empty())
2366193326Sed    return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
2367193326Sed
2368193326Sed  std::vector<llvm::Constant*> Values(3);
2369193326Sed  Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
2370193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
2371193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
2372193326Sed                                             Methods.size());
2373193326Sed  Values[2] = llvm::ConstantArray::get(AT, Methods);
2374198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
2375193326Sed
2376193326Sed  llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
2377193326Sed  return llvm::ConstantExpr::getBitCast(GV,
2378193326Sed                                        ObjCTypes.MethodListPtrTy);
2379193326Sed}
2380193326Sed
2381193326Sedllvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
2382198092Srdivacky                                                const ObjCContainerDecl *CD) {
2383198398Srdivacky  llvm::SmallString<256> Name;
2384193326Sed  GetNameForMethod(OMD, CD, Name);
2385193326Sed
2386193326Sed  CodeGenTypes &Types = CGM.getTypes();
2387193326Sed  const llvm::FunctionType *MethodTy =
2388193326Sed    Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
2389198092Srdivacky  llvm::Function *Method =
2390193326Sed    llvm::Function::Create(MethodTy,
2391193326Sed                           llvm::GlobalValue::InternalLinkage,
2392198398Srdivacky                           Name.str(),
2393193326Sed                           &CGM.getModule());
2394193326Sed  MethodDefinitions.insert(std::make_pair(OMD, Method));
2395193326Sed
2396193326Sed  return Method;
2397193326Sed}
2398193326Sed
2399193326Sedllvm::GlobalVariable *
2400198398SrdivackyCGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
2401193326Sed                                   llvm::Constant *Init,
2402193326Sed                                   const char *Section,
2403193326Sed                                   unsigned Align,
2404193326Sed                                   bool AddToUsed) {
2405193326Sed  const llvm::Type *Ty = Init->getType();
2406198092Srdivacky  llvm::GlobalVariable *GV =
2407198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Ty, false,
2408198092Srdivacky                             llvm::GlobalValue::InternalLinkage, Init, Name);
2409193326Sed  if (Section)
2410193326Sed    GV->setSection(Section);
2411193326Sed  if (Align)
2412193326Sed    GV->setAlignment(Align);
2413193326Sed  if (AddToUsed)
2414198092Srdivacky    CGM.AddUsedGlobal(GV);
2415193326Sed  return GV;
2416193326Sed}
2417193326Sed
2418198092Srdivackyllvm::Function *CGObjCMac::ModuleInitFunction() {
2419193326Sed  // Abuse this interface function as a place to finalize.
2420193326Sed  FinishModule();
2421193326Sed  return NULL;
2422193326Sed}
2423193326Sed
2424193326Sedllvm::Constant *CGObjCMac::GetPropertyGetFunction() {
2425193326Sed  return ObjCTypes.getGetPropertyFn();
2426193326Sed}
2427193326Sed
2428193326Sedllvm::Constant *CGObjCMac::GetPropertySetFunction() {
2429193326Sed  return ObjCTypes.getSetPropertyFn();
2430193326Sed}
2431193326Sed
2432193326Sedllvm::Constant *CGObjCMac::EnumerationMutationFunction() {
2433193326Sed  return ObjCTypes.getEnumerationMutationFn();
2434193326Sed}
2435193326Sed
2436198092Srdivacky/*
2437193326Sed
2438198092Srdivacky  Objective-C setjmp-longjmp (sjlj) Exception Handling
2439198092Srdivacky  --
2440193326Sed
2441198092Srdivacky  The basic framework for a @try-catch-finally is as follows:
2442198092Srdivacky  {
2443193326Sed  objc_exception_data d;
2444193326Sed  id _rethrow = null;
2445193326Sed  bool _call_try_exit = true;
2446198092Srdivacky
2447193326Sed  objc_exception_try_enter(&d);
2448193326Sed  if (!setjmp(d.jmp_buf)) {
2449198092Srdivacky  ... try body ...
2450193326Sed  } else {
2451198092Srdivacky  // exception path
2452198092Srdivacky  id _caught = objc_exception_extract(&d);
2453198092Srdivacky
2454198092Srdivacky  // enter new try scope for handlers
2455198092Srdivacky  if (!setjmp(d.jmp_buf)) {
2456198092Srdivacky  ... match exception and execute catch blocks ...
2457198092Srdivacky
2458198092Srdivacky  // fell off end, rethrow.
2459198092Srdivacky  _rethrow = _caught;
2460198092Srdivacky  ... jump-through-finally to finally_rethrow ...
2461198092Srdivacky  } else {
2462198092Srdivacky  // exception in catch block
2463198092Srdivacky  _rethrow = objc_exception_extract(&d);
2464198092Srdivacky  _call_try_exit = false;
2465198092Srdivacky  ... jump-through-finally to finally_rethrow ...
2466193326Sed  }
2467198092Srdivacky  }
2468193326Sed  ... jump-through-finally to finally_end ...
2469193326Sed
2470198092Srdivacky  finally:
2471193326Sed  if (_call_try_exit)
2472198092Srdivacky  objc_exception_try_exit(&d);
2473193326Sed
2474193326Sed  ... finally block ....
2475193326Sed  ... dispatch to finally destination ...
2476193326Sed
2477198092Srdivacky  finally_rethrow:
2478193326Sed  objc_exception_throw(_rethrow);
2479193326Sed
2480198092Srdivacky  finally_end:
2481198092Srdivacky  }
2482193326Sed
2483198092Srdivacky  This framework differs slightly from the one gcc uses, in that gcc
2484198092Srdivacky  uses _rethrow to determine if objc_exception_try_exit should be called
2485198092Srdivacky  and if the object should be rethrown. This breaks in the face of
2486198092Srdivacky  throwing nil and introduces unnecessary branches.
2487193326Sed
2488198092Srdivacky  We specialize this framework for a few particular circumstances:
2489193326Sed
2490198092Srdivacky  - If there are no catch blocks, then we avoid emitting the second
2491198092Srdivacky  exception handling context.
2492193326Sed
2493198092Srdivacky  - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
2494198092Srdivacky  e)) we avoid emitting the code to rethrow an uncaught exception.
2495193326Sed
2496198092Srdivacky  - FIXME: If there is no @finally block we can do a few more
2497198092Srdivacky  simplifications.
2498193326Sed
2499198092Srdivacky  Rethrows and Jumps-Through-Finally
2500198092Srdivacky  --
2501193326Sed
2502198092Srdivacky  Support for implicit rethrows and jumping through the finally block is
2503198092Srdivacky  handled by storing the current exception-handling context in
2504198092Srdivacky  ObjCEHStack.
2505193326Sed
2506198092Srdivacky  In order to implement proper @finally semantics, we support one basic
2507198092Srdivacky  mechanism for jumping through the finally block to an arbitrary
2508198092Srdivacky  destination. Constructs which generate exits from a @try or @catch
2509198092Srdivacky  block use this mechanism to implement the proper semantics by chaining
2510198092Srdivacky  jumps, as necessary.
2511193326Sed
2512198092Srdivacky  This mechanism works like the one used for indirect goto: we
2513198092Srdivacky  arbitrarily assign an ID to each destination and store the ID for the
2514198092Srdivacky  destination in a variable prior to entering the finally block. At the
2515198092Srdivacky  end of the finally block we simply create a switch to the proper
2516198092Srdivacky  destination.
2517198092Srdivacky
2518198092Srdivacky  Code gen for @synchronized(expr) stmt;
2519198092Srdivacky  Effectively generating code for:
2520198092Srdivacky  objc_sync_enter(expr);
2521198092Srdivacky  @try stmt @finally { objc_sync_exit(expr); }
2522193326Sed*/
2523193326Sed
2524193326Sedvoid CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2525193326Sed                                          const Stmt &S) {
2526193326Sed  bool isTry = isa<ObjCAtTryStmt>(S);
2527193326Sed  // Create various blocks we refer to for handling @finally.
2528193326Sed  llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
2529193326Sed  llvm::BasicBlock *FinallyExit = CGF.createBasicBlock("finally.exit");
2530193326Sed  llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit");
2531193326Sed  llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
2532193326Sed  llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
2533198092Srdivacky
2534193326Sed  // For @synchronized, call objc_sync_enter(sync.expr). The
2535193326Sed  // evaluation of the expression must occur before we enter the
2536193326Sed  // @synchronized. We can safely avoid a temp here because jumps into
2537193326Sed  // @synchronized are illegal & this will dominate uses.
2538193326Sed  llvm::Value *SyncArg = 0;
2539193326Sed  if (!isTry) {
2540198092Srdivacky    SyncArg =
2541193326Sed      CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2542193326Sed    SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
2543193326Sed    CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg);
2544193326Sed  }
2545193326Sed
2546193326Sed  // Push an EH context entry, used for handling rethrows and jumps
2547193326Sed  // through finally.
2548193326Sed  CGF.PushCleanupBlock(FinallyBlock);
2549193326Sed
2550200583Srdivacky  if (CGF.ObjCEHValueStack.empty())
2551200583Srdivacky    CGF.ObjCEHValueStack.push_back(0);
2552200583Srdivacky  // If This is a nested @try, caught exception is that of enclosing @try.
2553200583Srdivacky  else
2554200583Srdivacky    CGF.ObjCEHValueStack.push_back(CGF.ObjCEHValueStack.back());
2555193326Sed  // Allocate memory for the exception data and rethrow pointer.
2556193326Sed  llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2557193326Sed                                                    "exceptiondata.ptr");
2558198092Srdivacky  llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy,
2559193326Sed                                                 "_rethrow");
2560198092Srdivacky  llvm::Value *CallTryExitPtr = CGF.CreateTempAlloca(
2561198092Srdivacky                                               llvm::Type::getInt1Ty(VMContext),
2562193326Sed                                                     "_call_try_exit");
2563198092Srdivacky  CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext),
2564198092Srdivacky                          CallTryExitPtr);
2565198092Srdivacky
2566193326Sed  // Enter a new try block and call setjmp.
2567193326Sed  CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData);
2568198092Srdivacky  llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0,
2569193326Sed                                                       "jmpbufarray");
2570193326Sed  JmpBufPtr = CGF.Builder.CreateStructGEP(JmpBufPtr, 0, "tmp");
2571193326Sed  llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(),
2572193326Sed                                                     JmpBufPtr, "result");
2573193326Sed
2574193326Sed  llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
2575193326Sed  llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
2576198092Srdivacky  CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"),
2577193326Sed                           TryHandler, TryBlock);
2578193326Sed
2579193326Sed  // Emit the @try block.
2580193326Sed  CGF.EmitBlock(TryBlock);
2581198092Srdivacky  CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
2582198092Srdivacky               : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
2583193326Sed  CGF.EmitBranchThroughCleanup(FinallyEnd);
2584198092Srdivacky
2585193326Sed  // Emit the "exception in @try" block.
2586193326Sed  CGF.EmitBlock(TryHandler);
2587193326Sed
2588193326Sed  // Retrieve the exception object.  We may emit multiple blocks but
2589193326Sed  // nothing can cross this so the value is already in SSA form.
2590193326Sed  llvm::Value *Caught =
2591193326Sed    CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
2592193326Sed                           ExceptionData, "caught");
2593193326Sed  CGF.ObjCEHValueStack.back() = Caught;
2594198092Srdivacky  if (!isTry) {
2595193326Sed    CGF.Builder.CreateStore(Caught, RethrowPtr);
2596198092Srdivacky    CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext),
2597198092Srdivacky                            CallTryExitPtr);
2598193326Sed    CGF.EmitBranchThroughCleanup(FinallyRethrow);
2599198092Srdivacky  } else if (const ObjCAtCatchStmt* CatchStmt =
2600198092Srdivacky             cast<ObjCAtTryStmt>(S).getCatchStmts()) {
2601193326Sed    // Enter a new exception try block (in case a @catch block throws
2602193326Sed    // an exception).
2603193326Sed    CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData);
2604198092Srdivacky
2605193326Sed    llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(),
2606193326Sed                                                       JmpBufPtr, "result");
2607193326Sed    llvm::Value *Threw = CGF.Builder.CreateIsNotNull(SetJmpResult, "threw");
2608193326Sed
2609193326Sed    llvm::BasicBlock *CatchBlock = CGF.createBasicBlock("catch");
2610193326Sed    llvm::BasicBlock *CatchHandler = CGF.createBasicBlock("catch.handler");
2611193326Sed    CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
2612198092Srdivacky
2613193326Sed    CGF.EmitBlock(CatchBlock);
2614198092Srdivacky
2615193326Sed    // Handle catch list. As a special case we check if everything is
2616193326Sed    // matched and avoid generating code for falling off the end if
2617193326Sed    // so.
2618193326Sed    bool AllMatched = false;
2619193326Sed    for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
2620193326Sed      llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch");
2621193326Sed
2622193326Sed      const ParmVarDecl *CatchParam = CatchStmt->getCatchParamDecl();
2623198092Srdivacky      const ObjCObjectPointerType *OPT = 0;
2624193326Sed
2625193326Sed      // catch(...) always matches.
2626193326Sed      if (!CatchParam) {
2627193326Sed        AllMatched = true;
2628193326Sed      } else {
2629198092Srdivacky        OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
2630198092Srdivacky
2631198092Srdivacky        // catch(id e) always matches.
2632193326Sed        // FIXME: For the time being we also match id<X>; this should
2633193326Sed        // be rejected by Sema instead.
2634198092Srdivacky        if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
2635193326Sed          AllMatched = true;
2636193326Sed      }
2637198092Srdivacky
2638198092Srdivacky      if (AllMatched) {
2639193326Sed        if (CatchParam) {
2640193326Sed          CGF.EmitLocalBlockVarDecl(*CatchParam);
2641193326Sed          assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
2642193326Sed          CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
2643193326Sed        }
2644198092Srdivacky
2645193326Sed        CGF.EmitStmt(CatchStmt->getCatchBody());
2646193326Sed        CGF.EmitBranchThroughCleanup(FinallyEnd);
2647193326Sed        break;
2648193326Sed      }
2649198092Srdivacky
2650198092Srdivacky      assert(OPT && "Unexpected non-object pointer type in @catch");
2651198092Srdivacky      QualType T = OPT->getPointeeType();
2652198092Srdivacky      const ObjCInterfaceType *ObjCType = T->getAs<ObjCInterfaceType>();
2653193326Sed      assert(ObjCType && "Catch parameter must have Objective-C type!");
2654193326Sed
2655193326Sed      // Check if the @catch block matches the exception object.
2656193326Sed      llvm::Value *Class = EmitClassRef(CGF.Builder, ObjCType->getDecl());
2657198092Srdivacky
2658193326Sed      llvm::Value *Match =
2659193326Sed        CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
2660193326Sed                                Class, Caught, "match");
2661198092Srdivacky
2662193326Sed      llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("matched");
2663198092Srdivacky
2664198092Srdivacky      CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
2665193326Sed                               MatchedBlock, NextCatchBlock);
2666198092Srdivacky
2667193326Sed      // Emit the @catch block.
2668193326Sed      CGF.EmitBlock(MatchedBlock);
2669193326Sed      CGF.EmitLocalBlockVarDecl(*CatchParam);
2670193326Sed      assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
2671193326Sed
2672198092Srdivacky      llvm::Value *Tmp =
2673198092Srdivacky        CGF.Builder.CreateBitCast(Caught,
2674198092Srdivacky                                  CGF.ConvertType(CatchParam->getType()),
2675193326Sed                                  "tmp");
2676193326Sed      CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
2677198092Srdivacky
2678193326Sed      CGF.EmitStmt(CatchStmt->getCatchBody());
2679193326Sed      CGF.EmitBranchThroughCleanup(FinallyEnd);
2680198092Srdivacky
2681193326Sed      CGF.EmitBlock(NextCatchBlock);
2682193326Sed    }
2683193326Sed
2684193326Sed    if (!AllMatched) {
2685193326Sed      // None of the handlers caught the exception, so store it to be
2686193326Sed      // rethrown at the end of the @finally block.
2687193326Sed      CGF.Builder.CreateStore(Caught, RethrowPtr);
2688193326Sed      CGF.EmitBranchThroughCleanup(FinallyRethrow);
2689193326Sed    }
2690198092Srdivacky
2691193326Sed    // Emit the exception handler for the @catch blocks.
2692198092Srdivacky    CGF.EmitBlock(CatchHandler);
2693193326Sed    CGF.Builder.CreateStore(
2694198092Srdivacky      CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
2695198092Srdivacky                             ExceptionData),
2696198092Srdivacky      RethrowPtr);
2697198092Srdivacky    CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext),
2698198092Srdivacky                            CallTryExitPtr);
2699193326Sed    CGF.EmitBranchThroughCleanup(FinallyRethrow);
2700193326Sed  } else {
2701193326Sed    CGF.Builder.CreateStore(Caught, RethrowPtr);
2702198092Srdivacky    CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext),
2703198092Srdivacky                            CallTryExitPtr);
2704193326Sed    CGF.EmitBranchThroughCleanup(FinallyRethrow);
2705193326Sed  }
2706198092Srdivacky
2707193326Sed  // Pop the exception-handling stack entry. It is important to do
2708193326Sed  // this now, because the code in the @finally block is not in this
2709193326Sed  // context.
2710193326Sed  CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
2711193326Sed
2712193326Sed  CGF.ObjCEHValueStack.pop_back();
2713198092Srdivacky
2714193326Sed  // Emit the @finally block.
2715193326Sed  CGF.EmitBlock(FinallyBlock);
2716193326Sed  llvm::Value* CallTryExit = CGF.Builder.CreateLoad(CallTryExitPtr, "tmp");
2717198092Srdivacky
2718193326Sed  CGF.Builder.CreateCondBr(CallTryExit, FinallyExit, FinallyNoExit);
2719198092Srdivacky
2720193326Sed  CGF.EmitBlock(FinallyExit);
2721193326Sed  CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData);
2722193326Sed
2723193326Sed  CGF.EmitBlock(FinallyNoExit);
2724193326Sed  if (isTry) {
2725198092Srdivacky    if (const ObjCAtFinallyStmt* FinallyStmt =
2726198092Srdivacky        cast<ObjCAtTryStmt>(S).getFinallyStmt())
2727193326Sed      CGF.EmitStmt(FinallyStmt->getFinallyBody());
2728193326Sed  } else {
2729193326Sed    // Emit objc_sync_exit(expr); as finally's sole statement for
2730193326Sed    // @synchronized.
2731193326Sed    CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg);
2732193326Sed  }
2733193326Sed
2734193326Sed  // Emit the switch block
2735193326Sed  if (Info.SwitchBlock)
2736193326Sed    CGF.EmitBlock(Info.SwitchBlock);
2737193326Sed  if (Info.EndBlock)
2738193326Sed    CGF.EmitBlock(Info.EndBlock);
2739198092Srdivacky
2740193326Sed  CGF.EmitBlock(FinallyRethrow);
2741198092Srdivacky  CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(),
2742193326Sed                         CGF.Builder.CreateLoad(RethrowPtr));
2743193326Sed  CGF.Builder.CreateUnreachable();
2744198092Srdivacky
2745193326Sed  CGF.EmitBlock(FinallyEnd);
2746193326Sed}
2747193326Sed
2748193326Sedvoid CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
2749193326Sed                              const ObjCAtThrowStmt &S) {
2750193326Sed  llvm::Value *ExceptionAsObject;
2751198092Srdivacky
2752193326Sed  if (const Expr *ThrowExpr = S.getThrowExpr()) {
2753193326Sed    llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
2754198092Srdivacky    ExceptionAsObject =
2755193326Sed      CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
2756193326Sed  } else {
2757198092Srdivacky    assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
2758193326Sed           "Unexpected rethrow outside @catch block.");
2759193326Sed    ExceptionAsObject = CGF.ObjCEHValueStack.back();
2760193326Sed  }
2761198092Srdivacky
2762193326Sed  CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject);
2763193326Sed  CGF.Builder.CreateUnreachable();
2764193326Sed
2765193326Sed  // Clear the insertion point to indicate we are in unreachable code.
2766193326Sed  CGF.Builder.ClearInsertionPoint();
2767193326Sed}
2768193326Sed
2769193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak
2770193326Sed/// object: objc_read_weak (id *src)
2771193326Sed///
2772193326Sedllvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
2773198092Srdivacky                                          llvm::Value *AddrWeakObj) {
2774193326Sed  const llvm::Type* DestTy =
2775198092Srdivacky    cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
2776198092Srdivacky  AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
2777198092Srdivacky                                          ObjCTypes.PtrObjectPtrTy);
2778193326Sed  llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
2779193326Sed                                                  AddrWeakObj, "weakread");
2780193326Sed  read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
2781193326Sed  return read_weak;
2782193326Sed}
2783193326Sed
2784193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
2785193326Sed/// objc_assign_weak (id src, id *dst)
2786193326Sed///
2787193326Sedvoid CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
2788198092Srdivacky                                   llvm::Value *src, llvm::Value *dst) {
2789193326Sed  const llvm::Type * SrcTy = src->getType();
2790193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
2791193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
2792193326Sed    assert(Size <= 8 && "does not support size > 8");
2793193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2794198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2795193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2796193326Sed  }
2797193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2798193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2799193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
2800193326Sed                          src, dst, "weakassign");
2801193326Sed  return;
2802193326Sed}
2803193326Sed
2804193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
2805193326Sed/// objc_assign_global (id src, id *dst)
2806193326Sed///
2807193326Sedvoid CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
2808198092Srdivacky                                     llvm::Value *src, llvm::Value *dst) {
2809193326Sed  const llvm::Type * SrcTy = src->getType();
2810193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
2811193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
2812193326Sed    assert(Size <= 8 && "does not support size > 8");
2813193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2814198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2815193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2816193326Sed  }
2817193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2818193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2819193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
2820193326Sed                          src, dst, "globalassign");
2821193326Sed  return;
2822193326Sed}
2823193326Sed
2824193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
2825198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
2826193326Sed///
2827193326Sedvoid CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
2828198092Srdivacky                                   llvm::Value *src, llvm::Value *dst,
2829198092Srdivacky                                   llvm::Value *ivarOffset) {
2830198092Srdivacky  assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
2831193326Sed  const llvm::Type * SrcTy = src->getType();
2832193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
2833193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
2834193326Sed    assert(Size <= 8 && "does not support size > 8");
2835193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2836198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2837193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2838193326Sed  }
2839193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2840193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2841198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
2842198092Srdivacky                          src, dst, ivarOffset);
2843193326Sed  return;
2844193326Sed}
2845193326Sed
2846193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
2847193326Sed/// objc_assign_strongCast (id src, id *dst)
2848193326Sed///
2849193326Sedvoid CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
2850198092Srdivacky                                         llvm::Value *src, llvm::Value *dst) {
2851193326Sed  const llvm::Type * SrcTy = src->getType();
2852193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
2853193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
2854193326Sed    assert(Size <= 8 && "does not support size > 8");
2855193326Sed    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2856198092Srdivacky      : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
2857193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2858193326Sed  }
2859193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2860193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2861193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
2862193326Sed                          src, dst, "weakassign");
2863193326Sed  return;
2864193326Sed}
2865193326Sed
2866198092Srdivackyvoid CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
2867198092Srdivacky                                         llvm::Value *DestPtr,
2868198092Srdivacky                                         llvm::Value *SrcPtr,
2869198092Srdivacky                                         QualType Ty) {
2870198092Srdivacky  // Get size info for this aggregate.
2871198092Srdivacky  std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty);
2872198092Srdivacky  unsigned long size = TypeInfo.first/8;
2873198092Srdivacky  SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
2874198092Srdivacky  DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
2875198092Srdivacky  llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size);
2876198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
2877198092Srdivacky                          DestPtr, SrcPtr, N);
2878198092Srdivacky  return;
2879198092Srdivacky}
2880198092Srdivacky
2881193326Sed/// EmitObjCValueForIvar - Code Gen for ivar reference.
2882193326Sed///
2883193326SedLValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
2884193326Sed                                       QualType ObjectTy,
2885193326Sed                                       llvm::Value *BaseValue,
2886193326Sed                                       const ObjCIvarDecl *Ivar,
2887193326Sed                                       unsigned CVRQualifiers) {
2888198092Srdivacky  const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl();
2889193326Sed  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
2890193326Sed                                  EmitIvarOffset(CGF, ID, Ivar));
2891193326Sed}
2892193326Sed
2893193326Sedllvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
2894193326Sed                                       const ObjCInterfaceDecl *Interface,
2895193326Sed                                       const ObjCIvarDecl *Ivar) {
2896193326Sed  uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
2897193326Sed  return llvm::ConstantInt::get(
2898198092Srdivacky    CGM.getTypes().ConvertType(CGM.getContext().LongTy),
2899198092Srdivacky    Offset);
2900193326Sed}
2901193326Sed
2902193326Sed/* *** Private Interface *** */
2903193326Sed
2904193326Sed/// EmitImageInfo - Emit the image info marker used to encode some module
2905193326Sed/// level information.
2906193326Sed///
2907193326Sed/// See: <rdr://4810609&4810587&4810587>
2908193326Sed/// struct IMAGE_INFO {
2909193326Sed///   unsigned version;
2910193326Sed///   unsigned flags;
2911193326Sed/// };
2912193326Sedenum ImageInfoFlags {
2913193326Sed  eImageInfo_FixAndContinue      = (1 << 0), // FIXME: Not sure what
2914193326Sed                                             // this implies.
2915198092Srdivacky  eImageInfo_GarbageCollected    = (1 << 1),
2916198092Srdivacky  eImageInfo_GCOnly              = (1 << 2),
2917193326Sed  eImageInfo_OptimizedByDyld     = (1 << 3), // FIXME: When is this set.
2918193326Sed
2919193326Sed  // A flag indicating that the module has no instances of an
2920193326Sed  // @synthesize of a superclass variable. <rdar://problem/6803242>
2921193326Sed  eImageInfo_CorrectedSynthesize = (1 << 4)
2922193326Sed};
2923193326Sed
2924193326Sedvoid CGObjCMac::EmitImageInfo() {
2925193326Sed  unsigned version = 0; // Version is unused?
2926193326Sed  unsigned flags = 0;
2927193326Sed
2928193326Sed  // FIXME: Fix and continue?
2929193326Sed  if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
2930193326Sed    flags |= eImageInfo_GarbageCollected;
2931193326Sed  if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
2932193326Sed    flags |= eImageInfo_GCOnly;
2933198092Srdivacky
2934193326Sed  // We never allow @synthesize of a superclass property.
2935193326Sed  flags |= eImageInfo_CorrectedSynthesize;
2936193326Sed
2937193326Sed  // Emitted as int[2];
2938193326Sed  llvm::Constant *values[2] = {
2939198092Srdivacky    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), version),
2940198092Srdivacky    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), flags)
2941193326Sed  };
2942198092Srdivacky  llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext), 2);
2943193326Sed
2944193326Sed  const char *Section;
2945193326Sed  if (ObjCABI == 1)
2946193326Sed    Section = "__OBJC, __image_info,regular";
2947193326Sed  else
2948193326Sed    Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
2949198092Srdivacky  llvm::GlobalVariable *GV =
2950193326Sed    CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
2951193326Sed                      llvm::ConstantArray::get(AT, values, 2),
2952193326Sed                      Section,
2953193326Sed                      0,
2954193326Sed                      true);
2955193326Sed  GV->setConstant(true);
2956193326Sed}
2957193326Sed
2958193326Sed
2959193326Sed// struct objc_module {
2960193326Sed//   unsigned long version;
2961193326Sed//   unsigned long size;
2962193326Sed//   const char *name;
2963193326Sed//   Symtab symtab;
2964193326Sed// };
2965193326Sed
2966193326Sed// FIXME: Get from somewhere
2967193326Sedstatic const int ModuleVersion = 7;
2968193326Sed
2969193326Sedvoid CGObjCMac::EmitModuleInfo() {
2970193326Sed  uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
2971198092Srdivacky
2972193326Sed  std::vector<llvm::Constant*> Values(4);
2973193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
2974193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
2975193326Sed  // This used to be the filename, now it is unused. <rdr://4327263>
2976193326Sed  Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
2977193326Sed  Values[3] = EmitModuleSymbols();
2978198092Srdivacky  CreateMetadataVar("\01L_OBJC_MODULES",
2979193326Sed                    llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
2980193326Sed                    "__OBJC,__module_info,regular,no_dead_strip",
2981193326Sed                    4, true);
2982193326Sed}
2983193326Sed
2984193326Sedllvm::Constant *CGObjCMac::EmitModuleSymbols() {
2985193326Sed  unsigned NumClasses = DefinedClasses.size();
2986193326Sed  unsigned NumCategories = DefinedCategories.size();
2987193326Sed
2988193326Sed  // Return null if no symbols were defined.
2989193326Sed  if (!NumClasses && !NumCategories)
2990193326Sed    return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
2991193326Sed
2992193326Sed  std::vector<llvm::Constant*> Values(5);
2993193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2994193326Sed  Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
2995193326Sed  Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
2996193326Sed  Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
2997193326Sed
2998193326Sed  // The runtime expects exactly the list of defined classes followed
2999193326Sed  // by the list of defined categories, in a single array.
3000193326Sed  std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
3001193326Sed  for (unsigned i=0; i<NumClasses; i++)
3002193326Sed    Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
3003193326Sed                                                ObjCTypes.Int8PtrTy);
3004193326Sed  for (unsigned i=0; i<NumCategories; i++)
3005198092Srdivacky    Symbols[NumClasses + i] =
3006193326Sed      llvm::ConstantExpr::getBitCast(DefinedCategories[i],
3007193326Sed                                     ObjCTypes.Int8PtrTy);
3008193326Sed
3009198092Srdivacky  Values[4] =
3010193326Sed    llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3011193326Sed                                                  NumClasses + NumCategories),
3012193326Sed                             Symbols);
3013193326Sed
3014198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
3015193326Sed
3016193326Sed  llvm::GlobalVariable *GV =
3017193326Sed    CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3018193326Sed                      "__OBJC,__symbols,regular,no_dead_strip",
3019193326Sed                      4, true);
3020193326Sed  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
3021193326Sed}
3022193326Sed
3023198092Srdivackyllvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
3024193326Sed                                     const ObjCInterfaceDecl *ID) {
3025193326Sed  LazySymbols.insert(ID->getIdentifier());
3026193326Sed
3027193326Sed  llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
3028198092Srdivacky
3029193326Sed  if (!Entry) {
3030198092Srdivacky    llvm::Constant *Casted =
3031193326Sed      llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
3032193326Sed                                     ObjCTypes.ClassPtrTy);
3033198092Srdivacky    Entry =
3034193326Sed      CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3035193326Sed                        "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
3036193326Sed                        4, true);
3037193326Sed  }
3038193326Sed
3039199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
3040193326Sed}
3041193326Sed
3042193326Sedllvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) {
3043193326Sed  llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
3044198092Srdivacky
3045193326Sed  if (!Entry) {
3046198092Srdivacky    llvm::Constant *Casted =
3047193326Sed      llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
3048193326Sed                                     ObjCTypes.SelectorPtrTy);
3049198092Srdivacky    Entry =
3050193326Sed      CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3051193326Sed                        "__OBJC,__message_refs,literal_pointers,no_dead_strip",
3052193326Sed                        4, true);
3053193326Sed  }
3054193326Sed
3055199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
3056193326Sed}
3057193326Sed
3058193326Sedllvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
3059193326Sed  llvm::GlobalVariable *&Entry = ClassNames[Ident];
3060193326Sed
3061193326Sed  if (!Entry)
3062198092Srdivacky    Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3063198398Srdivacky                          llvm::ConstantArray::get(VMContext,
3064198398Srdivacky                                                   Ident->getNameStart()),
3065193326Sed                              "__TEXT,__cstring,cstring_literals",
3066193326Sed                              1, true);
3067193326Sed
3068198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3069193326Sed}
3070193326Sed
3071193326Sed/// GetIvarLayoutName - Returns a unique constant for the given
3072193326Sed/// ivar layout bitmap.
3073193326Sedllvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
3074198092Srdivacky                                       const ObjCCommonTypesHelper &ObjCTypes) {
3075193326Sed  return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
3076193326Sed}
3077193326Sed
3078198092Srdivackystatic Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
3079193326Sed  if (FQT.isObjCGCStrong())
3080198092Srdivacky    return Qualifiers::Strong;
3081193326Sed
3082193326Sed  if (FQT.isObjCGCWeak())
3083198092Srdivacky    return Qualifiers::Weak;
3084193326Sed
3085198092Srdivacky  if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
3086198092Srdivacky    return Qualifiers::Strong;
3087193326Sed
3088198092Srdivacky  if (const PointerType *PT = FQT->getAs<PointerType>())
3089193326Sed    return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
3090193326Sed
3091198092Srdivacky  return Qualifiers::GCNone;
3092193326Sed}
3093193326Sed
3094193326Sedvoid CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
3095198092Srdivacky                                                unsigned int BytePos,
3096193326Sed                                                bool ForStrongLayout,
3097193326Sed                                                bool &HasUnion) {
3098193326Sed  const RecordDecl *RD = RT->getDecl();
3099193326Sed  // FIXME - Use iterator.
3100195341Sed  llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
3101193326Sed  const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
3102198092Srdivacky  const llvm::StructLayout *RecLayout =
3103193326Sed    CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
3104198092Srdivacky
3105193326Sed  BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3106193326Sed                      ForStrongLayout, HasUnion);
3107193326Sed}
3108193326Sed
3109193326Sedvoid CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
3110198092Srdivacky                             const llvm::StructLayout *Layout,
3111198092Srdivacky                             const RecordDecl *RD,
3112193326Sed                             const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
3113198092Srdivacky                             unsigned int BytePos, bool ForStrongLayout,
3114198092Srdivacky                             bool &HasUnion) {
3115193326Sed  bool IsUnion = (RD && RD->isUnion());
3116193326Sed  uint64_t MaxUnionIvarSize = 0;
3117193326Sed  uint64_t MaxSkippedUnionIvarSize = 0;
3118193326Sed  FieldDecl *MaxField = 0;
3119193326Sed  FieldDecl *MaxSkippedField = 0;
3120193326Sed  FieldDecl *LastFieldBitfield = 0;
3121193326Sed  uint64_t MaxFieldOffset = 0;
3122193326Sed  uint64_t MaxSkippedFieldOffset = 0;
3123193326Sed  uint64_t LastBitfieldOffset = 0;
3124198092Srdivacky
3125193326Sed  if (RecFields.empty())
3126193326Sed    return;
3127193326Sed  unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3128193326Sed  unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3129193326Sed
3130193326Sed  for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
3131193326Sed    FieldDecl *Field = RecFields[i];
3132193326Sed    uint64_t FieldOffset;
3133198092Srdivacky    if (RD) {
3134198092Srdivacky      if (Field->isBitField()) {
3135198092Srdivacky        CodeGenTypes::BitFieldInfo Info = CGM.getTypes().getBitFieldInfo(Field);
3136198092Srdivacky
3137198092Srdivacky        const llvm::Type *Ty =
3138198092Srdivacky          CGM.getTypes().ConvertTypeForMemRecursive(Field->getType());
3139198092Srdivacky        uint64_t TypeSize =
3140198092Srdivacky          CGM.getTypes().getTargetData().getTypeAllocSize(Ty);
3141198092Srdivacky        FieldOffset = Info.FieldNo * TypeSize;
3142198092Srdivacky      } else
3143198092Srdivacky        FieldOffset =
3144198092Srdivacky          Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
3145198092Srdivacky    } else
3146193326Sed      FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
3147193326Sed
3148193326Sed    // Skip over unnamed or bitfields
3149193326Sed    if (!Field->getIdentifier() || Field->isBitField()) {
3150193326Sed      LastFieldBitfield = Field;
3151193326Sed      LastBitfieldOffset = FieldOffset;
3152193326Sed      continue;
3153193326Sed    }
3154193326Sed
3155193326Sed    LastFieldBitfield = 0;
3156193326Sed    QualType FQT = Field->getType();
3157193326Sed    if (FQT->isRecordType() || FQT->isUnionType()) {
3158193326Sed      if (FQT->isUnionType())
3159193326Sed        HasUnion = true;
3160193326Sed
3161198092Srdivacky      BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
3162193326Sed                                BytePos + FieldOffset,
3163193326Sed                                ForStrongLayout, HasUnion);
3164193326Sed      continue;
3165193326Sed    }
3166198092Srdivacky
3167193326Sed    if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3168198092Srdivacky      const ConstantArrayType *CArray =
3169193326Sed        dyn_cast_or_null<ConstantArrayType>(Array);
3170193326Sed      uint64_t ElCount = CArray->getSize().getZExtValue();
3171193326Sed      assert(CArray && "only array with known element size is supported");
3172193326Sed      FQT = CArray->getElementType();
3173193326Sed      while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3174193326Sed        const ConstantArrayType *CArray =
3175193326Sed          dyn_cast_or_null<ConstantArrayType>(Array);
3176193326Sed        ElCount *= CArray->getSize().getZExtValue();
3177193326Sed        FQT = CArray->getElementType();
3178193326Sed      }
3179198092Srdivacky
3180198092Srdivacky      assert(!FQT->isUnionType() &&
3181193326Sed             "layout for array of unions not supported");
3182193326Sed      if (FQT->isRecordType()) {
3183193326Sed        int OldIndex = IvarsInfo.size() - 1;
3184193326Sed        int OldSkIndex = SkipIvars.size() -1;
3185198092Srdivacky
3186198092Srdivacky        const RecordType *RT = FQT->getAs<RecordType>();
3187193326Sed        BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
3188193326Sed                                  ForStrongLayout, HasUnion);
3189198092Srdivacky
3190193326Sed        // Replicate layout information for each array element. Note that
3191193326Sed        // one element is already done.
3192193326Sed        uint64_t ElIx = 1;
3193198092Srdivacky        for (int FirstIndex = IvarsInfo.size() - 1,
3194198092Srdivacky               FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
3195193326Sed          uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
3196193326Sed          for (int i = OldIndex+1; i <= FirstIndex; ++i)
3197193326Sed            IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
3198193326Sed                                        IvarsInfo[i].ivar_size));
3199193326Sed          for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
3200193326Sed            SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
3201193326Sed                                        SkipIvars[i].ivar_size));
3202193326Sed        }
3203193326Sed        continue;
3204193326Sed      }
3205193326Sed    }
3206193326Sed    // At this point, we are done with Record/Union and array there of.
3207193326Sed    // For other arrays we are down to its element type.
3208198092Srdivacky    Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
3209193326Sed
3210193326Sed    unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
3211198092Srdivacky    if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3212198092Srdivacky        || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
3213193326Sed      if (IsUnion) {
3214193326Sed        uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
3215193326Sed        if (UnionIvarSize > MaxUnionIvarSize) {
3216193326Sed          MaxUnionIvarSize = UnionIvarSize;
3217193326Sed          MaxField = Field;
3218193326Sed          MaxFieldOffset = FieldOffset;
3219193326Sed        }
3220193326Sed      } else {
3221193326Sed        IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
3222193326Sed                                    FieldSize / WordSizeInBits));
3223193326Sed      }
3224198092Srdivacky    } else if ((ForStrongLayout &&
3225198092Srdivacky                (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3226198092Srdivacky               || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
3227193326Sed      if (IsUnion) {
3228193326Sed        // FIXME: Why the asymmetry? We divide by word size in bits on other
3229193326Sed        // side.
3230193326Sed        uint64_t UnionIvarSize = FieldSize;
3231193326Sed        if (UnionIvarSize > MaxSkippedUnionIvarSize) {
3232193326Sed          MaxSkippedUnionIvarSize = UnionIvarSize;
3233193326Sed          MaxSkippedField = Field;
3234193326Sed          MaxSkippedFieldOffset = FieldOffset;
3235193326Sed        }
3236193326Sed      } else {
3237193326Sed        // FIXME: Why the asymmetry, we divide by byte size in bits here?
3238193326Sed        SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
3239193326Sed                                    FieldSize / ByteSizeInBits));
3240193326Sed      }
3241193326Sed    }
3242193326Sed  }
3243193326Sed
3244193326Sed  if (LastFieldBitfield) {
3245193326Sed    // Last field was a bitfield. Must update skip info.
3246193326Sed    Expr *BitWidth = LastFieldBitfield->getBitWidth();
3247193326Sed    uint64_t BitFieldSize =
3248193326Sed      BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
3249193326Sed    GC_IVAR skivar;
3250193326Sed    skivar.ivar_bytepos = BytePos + LastBitfieldOffset;
3251198092Srdivacky    skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3252198092Srdivacky      + ((BitFieldSize % ByteSizeInBits) != 0);
3253198092Srdivacky    SkipIvars.push_back(skivar);
3254193326Sed  }
3255198092Srdivacky
3256193326Sed  if (MaxField)
3257198092Srdivacky    IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
3258193326Sed                                MaxUnionIvarSize));
3259193326Sed  if (MaxSkippedField)
3260193326Sed    SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
3261193326Sed                                MaxSkippedUnionIvarSize));
3262193326Sed}
3263193326Sed
3264193326Sed/// BuildIvarLayout - Builds ivar layout bitmap for the class
3265193326Sed/// implementation for the __strong or __weak case.
3266198092Srdivacky/// The layout map displays which words in ivar list must be skipped
3267198092Srdivacky/// and which must be scanned by GC (see below). String is built of bytes.
3268198092Srdivacky/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
3269193326Sed/// of words to skip and right nibble is count of words to scan. So, each
3270198092Srdivacky/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
3271193326Sed/// represented by a 0x00 byte which also ends the string.
3272193326Sed/// 1. when ForStrongLayout is true, following ivars are scanned:
3273193326Sed/// - id, Class
3274193326Sed/// - object *
3275193326Sed/// - __strong anything
3276198092Srdivacky///
3277193326Sed/// 2. When ForStrongLayout is false, following ivars are scanned:
3278193326Sed/// - __weak anything
3279193326Sed///
3280193326Sedllvm::Constant *CGObjCCommonMac::BuildIvarLayout(
3281198092Srdivacky  const ObjCImplementationDecl *OMD,
3282198092Srdivacky  bool ForStrongLayout) {
3283193326Sed  bool hasUnion = false;
3284198092Srdivacky
3285193326Sed  unsigned int WordsToScan, WordsToSkip;
3286198092Srdivacky  const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
3287193326Sed  if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
3288193326Sed    return llvm::Constant::getNullValue(PtrTy);
3289198092Srdivacky
3290193326Sed  llvm::SmallVector<FieldDecl*, 32> RecFields;
3291193326Sed  const ObjCInterfaceDecl *OI = OMD->getClassInterface();
3292193326Sed  CGM.getContext().CollectObjCIvars(OI, RecFields);
3293198092Srdivacky
3294193326Sed  // Add this implementations synthesized ivars.
3295193326Sed  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
3296193326Sed  CGM.getContext().CollectSynthesizedIvars(OI, Ivars);
3297193326Sed  for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
3298193326Sed    RecFields.push_back(cast<FieldDecl>(Ivars[k]));
3299198092Srdivacky
3300193326Sed  if (RecFields.empty())
3301193326Sed    return llvm::Constant::getNullValue(PtrTy);
3302198092Srdivacky
3303198092Srdivacky  SkipIvars.clear();
3304193326Sed  IvarsInfo.clear();
3305198092Srdivacky
3306193326Sed  BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
3307193326Sed  if (IvarsInfo.empty())
3308193326Sed    return llvm::Constant::getNullValue(PtrTy);
3309198092Srdivacky
3310193326Sed  // Sort on byte position in case we encounterred a union nested in
3311193326Sed  // the ivar list.
3312193326Sed  if (hasUnion && !IvarsInfo.empty())
3313193326Sed    std::sort(IvarsInfo.begin(), IvarsInfo.end());
3314193326Sed  if (hasUnion && !SkipIvars.empty())
3315193326Sed    std::sort(SkipIvars.begin(), SkipIvars.end());
3316198092Srdivacky
3317193326Sed  // Build the string of skip/scan nibbles
3318193326Sed  llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
3319198092Srdivacky  unsigned int WordSize =
3320193326Sed    CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
3321193326Sed  if (IvarsInfo[0].ivar_bytepos == 0) {
3322193326Sed    WordsToSkip = 0;
3323193326Sed    WordsToScan = IvarsInfo[0].ivar_size;
3324193326Sed  } else {
3325193326Sed    WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3326193326Sed    WordsToScan = IvarsInfo[0].ivar_size;
3327193326Sed  }
3328193326Sed  for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
3329198092Srdivacky    unsigned int TailPrevGCObjC =
3330193326Sed      IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
3331193326Sed    if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
3332193326Sed      // consecutive 'scanned' object pointers.
3333193326Sed      WordsToScan += IvarsInfo[i].ivar_size;
3334193326Sed    } else {
3335193326Sed      // Skip over 'gc'able object pointer which lay over each other.
3336193326Sed      if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
3337193326Sed        continue;
3338193326Sed      // Must skip over 1 or more words. We save current skip/scan values
3339193326Sed      //  and start a new pair.
3340193326Sed      SKIP_SCAN SkScan;
3341193326Sed      SkScan.skip = WordsToSkip;
3342193326Sed      SkScan.scan = WordsToScan;
3343193326Sed      SkipScanIvars.push_back(SkScan);
3344198092Srdivacky
3345193326Sed      // Skip the hole.
3346193326Sed      SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3347193326Sed      SkScan.scan = 0;
3348193326Sed      SkipScanIvars.push_back(SkScan);
3349193326Sed      WordsToSkip = 0;
3350193326Sed      WordsToScan = IvarsInfo[i].ivar_size;
3351193326Sed    }
3352193326Sed  }
3353193326Sed  if (WordsToScan > 0) {
3354193326Sed    SKIP_SCAN SkScan;
3355193326Sed    SkScan.skip = WordsToSkip;
3356193326Sed    SkScan.scan = WordsToScan;
3357193326Sed    SkipScanIvars.push_back(SkScan);
3358193326Sed  }
3359198092Srdivacky
3360193326Sed  if (!SkipIvars.empty()) {
3361193326Sed    unsigned int LastIndex = SkipIvars.size()-1;
3362198092Srdivacky    int LastByteSkipped =
3363198092Srdivacky      SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
3364193326Sed    LastIndex = IvarsInfo.size()-1;
3365198092Srdivacky    int LastByteScanned =
3366198092Srdivacky      IvarsInfo[LastIndex].ivar_bytepos +
3367198092Srdivacky      IvarsInfo[LastIndex].ivar_size * WordSize;
3368193326Sed    // Compute number of bytes to skip at the tail end of the last ivar scanned.
3369201361Srdivacky    if (LastByteSkipped > LastByteScanned) {
3370193326Sed      unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
3371193326Sed      SKIP_SCAN SkScan;
3372193326Sed      SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3373193326Sed      SkScan.scan = 0;
3374193326Sed      SkipScanIvars.push_back(SkScan);
3375193326Sed    }
3376193326Sed  }
3377193326Sed  // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3378193326Sed  // as 0xMN.
3379193326Sed  int SkipScan = SkipScanIvars.size()-1;
3380193326Sed  for (int i = 0; i <= SkipScan; i++) {
3381193326Sed    if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3382193326Sed        && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3383193326Sed      // 0xM0 followed by 0x0N detected.
3384193326Sed      SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
3385193326Sed      for (int j = i+1; j < SkipScan; j++)
3386193326Sed        SkipScanIvars[j] = SkipScanIvars[j+1];
3387193326Sed      --SkipScan;
3388193326Sed    }
3389193326Sed  }
3390198092Srdivacky
3391193326Sed  // Generate the string.
3392193326Sed  std::string BitMap;
3393193326Sed  for (int i = 0; i <= SkipScan; i++) {
3394193326Sed    unsigned char byte;
3395193326Sed    unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
3396193326Sed    unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
3397193326Sed    unsigned int skip_big  = SkipScanIvars[i].skip / 0xf;
3398193326Sed    unsigned int scan_big  = SkipScanIvars[i].scan / 0xf;
3399193326Sed
3400193326Sed    // first skip big.
3401193326Sed    for (unsigned int ix = 0; ix < skip_big; ix++)
3402193326Sed      BitMap += (unsigned char)(0xf0);
3403198092Srdivacky
3404193326Sed    // next (skip small, scan)
3405193326Sed    if (skip_small) {
3406193326Sed      byte = skip_small << 4;
3407193326Sed      if (scan_big > 0) {
3408193326Sed        byte |= 0xf;
3409193326Sed        --scan_big;
3410193326Sed      } else if (scan_small) {
3411193326Sed        byte |= scan_small;
3412193326Sed        scan_small = 0;
3413193326Sed      }
3414193326Sed      BitMap += byte;
3415193326Sed    }
3416193326Sed    // next scan big
3417193326Sed    for (unsigned int ix = 0; ix < scan_big; ix++)
3418193326Sed      BitMap += (unsigned char)(0x0f);
3419193326Sed    // last scan small
3420193326Sed    if (scan_small) {
3421193326Sed      byte = scan_small;
3422193326Sed      BitMap += byte;
3423193326Sed    }
3424193326Sed  }
3425193326Sed  // null terminate string.
3426193326Sed  unsigned char zero = 0;
3427193326Sed  BitMap += zero;
3428198092Srdivacky
3429193326Sed  if (CGM.getLangOptions().ObjCGCBitmapPrint) {
3430198092Srdivacky    printf("\n%s ivar layout for class '%s': ",
3431193326Sed           ForStrongLayout ? "strong" : "weak",
3432193326Sed           OMD->getClassInterface()->getNameAsCString());
3433193326Sed    const unsigned char *s = (unsigned char*)BitMap.c_str();
3434193326Sed    for (unsigned i = 0; i < BitMap.size(); i++)
3435193326Sed      if (!(s[i] & 0xf0))
3436193326Sed        printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
3437193326Sed      else
3438193326Sed        printf("0x%x%s",  s[i], s[i] != 0 ? ", " : "");
3439193326Sed    printf("\n");
3440193326Sed  }
3441198092Srdivacky  llvm::GlobalVariable * Entry =
3442198092Srdivacky    CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3443198092Srdivacky                      llvm::ConstantArray::get(VMContext, BitMap.c_str()),
3444198092Srdivacky                      "__TEXT,__cstring,cstring_literals",
3445198092Srdivacky                      1, true);
3446198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3447193326Sed}
3448193326Sed
3449193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
3450193326Sed  llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3451193326Sed
3452193326Sed  // FIXME: Avoid std::string copying.
3453193326Sed  if (!Entry)
3454198092Srdivacky    Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
3455198092Srdivacky                        llvm::ConstantArray::get(VMContext, Sel.getAsString()),
3456193326Sed                              "__TEXT,__cstring,cstring_literals",
3457193326Sed                              1, true);
3458193326Sed
3459198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3460193326Sed}
3461193326Sed
3462193326Sed// FIXME: Merge into a single cstring creation function.
3463193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
3464193326Sed  return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
3465193326Sed}
3466193326Sed
3467193326Sed// FIXME: Merge into a single cstring creation function.
3468193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) {
3469193326Sed  return GetMethodVarName(&CGM.getContext().Idents.get(Name));
3470193326Sed}
3471193326Sed
3472193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
3473193326Sed  std::string TypeStr;
3474193326Sed  CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
3475193326Sed
3476193326Sed  llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3477193326Sed
3478193326Sed  if (!Entry)
3479193326Sed    Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
3480198092Srdivacky                              llvm::ConstantArray::get(VMContext, TypeStr),
3481193326Sed                              "__TEXT,__cstring,cstring_literals",
3482193326Sed                              1, true);
3483198092Srdivacky
3484198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3485193326Sed}
3486193326Sed
3487193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
3488193326Sed  std::string TypeStr;
3489193326Sed  CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
3490193326Sed                                                TypeStr);
3491193326Sed
3492193326Sed  llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3493193326Sed
3494193326Sed  if (!Entry)
3495193326Sed    Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
3496198092Srdivacky                              llvm::ConstantArray::get(VMContext, TypeStr),
3497193326Sed                              "__TEXT,__cstring,cstring_literals",
3498193326Sed                              1, true);
3499193326Sed
3500198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3501193326Sed}
3502193326Sed
3503193326Sed// FIXME: Merge into a single cstring creation function.
3504193326Sedllvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
3505193326Sed  llvm::GlobalVariable *&Entry = PropertyNames[Ident];
3506198092Srdivacky
3507193326Sed  if (!Entry)
3508198092Srdivacky    Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
3509198398Srdivacky                          llvm::ConstantArray::get(VMContext,
3510198398Srdivacky                                                   Ident->getNameStart()),
3511193326Sed                              "__TEXT,__cstring,cstring_literals",
3512193326Sed                              1, true);
3513193326Sed
3514198092Srdivacky  return getConstantGEP(VMContext, Entry, 0, 0);
3515193326Sed}
3516193326Sed
3517193326Sed// FIXME: Merge into a single cstring creation function.
3518193326Sed// FIXME: This Decl should be more precise.
3519193326Sedllvm::Constant *
3520198092SrdivackyCGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
3521198092Srdivacky                                       const Decl *Container) {
3522193326Sed  std::string TypeStr;
3523193326Sed  CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
3524193326Sed  return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
3525193326Sed}
3526193326Sed
3527198092Srdivackyvoid CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
3528193326Sed                                       const ObjCContainerDecl *CD,
3529198398Srdivacky                                       llvm::SmallVectorImpl<char> &Name) {
3530198398Srdivacky  llvm::raw_svector_ostream OS(Name);
3531193326Sed  assert (CD && "Missing container decl in GetNameForMethod");
3532198398Srdivacky  OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
3533198398Srdivacky     << '[' << CD->getName();
3534198092Srdivacky  if (const ObjCCategoryImplDecl *CID =
3535198398Srdivacky      dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
3536198398Srdivacky    OS << '(' << CID->getNameAsString() << ')';
3537198398Srdivacky  OS << ' ' << D->getSelector().getAsString() << ']';
3538193326Sed}
3539193326Sed
3540193326Sedvoid CGObjCMac::FinishModule() {
3541193326Sed  EmitModuleInfo();
3542193326Sed
3543193326Sed  // Emit the dummy bodies for any protocols which were referenced but
3544193326Sed  // never defined.
3545198092Srdivacky  for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
3546198092Srdivacky         I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
3547198092Srdivacky    if (I->second->hasInitializer())
3548193326Sed      continue;
3549193326Sed
3550193326Sed    std::vector<llvm::Constant*> Values(5);
3551193326Sed    Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3552198092Srdivacky    Values[1] = GetClassName(I->first);
3553193326Sed    Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3554193326Sed    Values[3] = Values[4] =
3555193326Sed      llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
3556198092Srdivacky    I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
3557198092Srdivacky    I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
3558193326Sed                                                        Values));
3559198092Srdivacky    CGM.AddUsedGlobal(I->second);
3560193326Sed  }
3561193326Sed
3562193326Sed  // Add assembler directives to add lazy undefined symbol references
3563193326Sed  // for classes which are referenced but not defined. This is
3564193326Sed  // important for correct linker interaction.
3565198092Srdivacky  //
3566198092Srdivacky  // FIXME: It would be nice if we had an LLVM construct for this.
3567198092Srdivacky  if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
3568198092Srdivacky    llvm::SmallString<256> Asm;
3569198092Srdivacky    Asm += CGM.getModule().getModuleInlineAsm();
3570198092Srdivacky    if (!Asm.empty() && Asm.back() != '\n')
3571198092Srdivacky      Asm += '\n';
3572193326Sed
3573198092Srdivacky    llvm::raw_svector_ostream OS(Asm);
3574198092Srdivacky    for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
3575198092Srdivacky           e = LazySymbols.end(); I != e; ++I)
3576198092Srdivacky      OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
3577198092Srdivacky    for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
3578198092Srdivacky           e = DefinedSymbols.end(); I != e; ++I)
3579198092Srdivacky      OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
3580198092Srdivacky         << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
3581198092Srdivacky
3582198092Srdivacky    CGM.getModule().setModuleInlineAsm(OS.str());
3583193326Sed  }
3584193326Sed}
3585193326Sed
3586198092SrdivackyCGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
3587193326Sed  : CGObjCCommonMac(cgm),
3588198092Srdivacky    ObjCTypes(cgm) {
3589193326Sed  ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
3590193326Sed  ObjCABI = 2;
3591193326Sed}
3592193326Sed
3593193326Sed/* *** */
3594193326Sed
3595193326SedObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
3596198092Srdivacky  : VMContext(cgm.getLLVMContext()), CGM(cgm) {
3597193326Sed  CodeGen::CodeGenTypes &Types = CGM.getTypes();
3598193326Sed  ASTContext &Ctx = CGM.getContext();
3599198092Srdivacky
3600193326Sed  ShortTy = Types.ConvertType(Ctx.ShortTy);
3601193326Sed  IntTy = Types.ConvertType(Ctx.IntTy);
3602193326Sed  LongTy = Types.ConvertType(Ctx.LongTy);
3603193326Sed  LongLongTy = Types.ConvertType(Ctx.LongLongTy);
3604198092Srdivacky  Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
3605198092Srdivacky
3606193326Sed  ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
3607193326Sed  PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
3608193326Sed  SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
3609198092Srdivacky
3610193326Sed  // FIXME: It would be nice to unify this with the opaque type, so that the IR
3611193326Sed  // comes out a bit cleaner.
3612193326Sed  const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
3613193326Sed  ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
3614198092Srdivacky
3615193326Sed  // I'm not sure I like this. The implicit coordination is a bit
3616193326Sed  // gross. We should solve this in a reasonable fashion because this
3617193326Sed  // is a pretty common task (match some runtime data structure with
3618193326Sed  // an LLVM data structure).
3619198092Srdivacky
3620193326Sed  // FIXME: This is leaked.
3621193326Sed  // FIXME: Merge with rewriter code?
3622198092Srdivacky
3623193326Sed  // struct _objc_super {
3624193326Sed  //   id self;
3625193326Sed  //   Class cls;
3626193326Sed  // }
3627193326Sed  RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
3628193326Sed                                      SourceLocation(),
3629198092Srdivacky                                      &Ctx.Idents.get("_objc_super"));
3630195341Sed  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
3631198092Srdivacky                                Ctx.getObjCIdType(), 0, 0, false));
3632198092Srdivacky  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
3633198092Srdivacky                                Ctx.getObjCClassType(), 0, 0, false));
3634203955Srdivacky  RD->completeDefinition();
3635198092Srdivacky
3636193326Sed  SuperCTy = Ctx.getTagDeclType(RD);
3637193326Sed  SuperPtrCTy = Ctx.getPointerType(SuperCTy);
3638198092Srdivacky
3639193326Sed  SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
3640198092Srdivacky  SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
3641198092Srdivacky
3642193326Sed  // struct _prop_t {
3643193326Sed  //   char *name;
3644198092Srdivacky  //   char *attributes;
3645193326Sed  // }
3646198092Srdivacky  PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
3647198092Srdivacky  CGM.getModule().addTypeName("struct._prop_t",
3648193326Sed                              PropertyTy);
3649198092Srdivacky
3650193326Sed  // struct _prop_list_t {
3651193326Sed  //   uint32_t entsize;      // sizeof(struct _prop_t)
3652193326Sed  //   uint32_t count_of_properties;
3653193326Sed  //   struct _prop_t prop_list[count_of_properties];
3654193326Sed  // }
3655198092Srdivacky  PropertyListTy = llvm::StructType::get(VMContext, IntTy,
3656193326Sed                                         IntTy,
3657193326Sed                                         llvm::ArrayType::get(PropertyTy, 0),
3658193326Sed                                         NULL);
3659198092Srdivacky  CGM.getModule().addTypeName("struct._prop_list_t",
3660193326Sed                              PropertyListTy);
3661193326Sed  // struct _prop_list_t *
3662193326Sed  PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
3663198092Srdivacky
3664193326Sed  // struct _objc_method {
3665193326Sed  //   SEL _cmd;
3666193326Sed  //   char *method_type;
3667193326Sed  //   char *_imp;
3668193326Sed  // }
3669198092Srdivacky  MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
3670193326Sed                                   Int8PtrTy,
3671193326Sed                                   Int8PtrTy,
3672193326Sed                                   NULL);
3673193326Sed  CGM.getModule().addTypeName("struct._objc_method", MethodTy);
3674198092Srdivacky
3675193326Sed  // struct _objc_cache *
3676198092Srdivacky  CacheTy = llvm::OpaqueType::get(VMContext);
3677193326Sed  CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
3678193326Sed  CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
3679193326Sed}
3680193326Sed
3681198092SrdivackyObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
3682198092Srdivacky  : ObjCCommonTypesHelper(cgm) {
3683193326Sed  // struct _objc_method_description {
3684193326Sed  //   SEL name;
3685193326Sed  //   char *types;
3686193326Sed  // }
3687198092Srdivacky  MethodDescriptionTy =
3688198092Srdivacky    llvm::StructType::get(VMContext, SelectorPtrTy,
3689193326Sed                          Int8PtrTy,
3690193326Sed                          NULL);
3691198092Srdivacky  CGM.getModule().addTypeName("struct._objc_method_description",
3692193326Sed                              MethodDescriptionTy);
3693193326Sed
3694193326Sed  // struct _objc_method_description_list {
3695193326Sed  //   int count;
3696193326Sed  //   struct _objc_method_description[1];
3697193326Sed  // }
3698198092Srdivacky  MethodDescriptionListTy =
3699198092Srdivacky    llvm::StructType::get(VMContext, IntTy,
3700193326Sed                          llvm::ArrayType::get(MethodDescriptionTy, 0),
3701193326Sed                          NULL);
3702198092Srdivacky  CGM.getModule().addTypeName("struct._objc_method_description_list",
3703193326Sed                              MethodDescriptionListTy);
3704198092Srdivacky
3705193326Sed  // struct _objc_method_description_list *
3706198092Srdivacky  MethodDescriptionListPtrTy =
3707193326Sed    llvm::PointerType::getUnqual(MethodDescriptionListTy);
3708193326Sed
3709193326Sed  // Protocol description structures
3710193326Sed
3711193326Sed  // struct _objc_protocol_extension {
3712193326Sed  //   uint32_t size;  // sizeof(struct _objc_protocol_extension)
3713193326Sed  //   struct _objc_method_description_list *optional_instance_methods;
3714193326Sed  //   struct _objc_method_description_list *optional_class_methods;
3715193326Sed  //   struct _objc_property_list *instance_properties;
3716193326Sed  // }
3717198092Srdivacky  ProtocolExtensionTy =
3718198092Srdivacky    llvm::StructType::get(VMContext, IntTy,
3719193326Sed                          MethodDescriptionListPtrTy,
3720193326Sed                          MethodDescriptionListPtrTy,
3721193326Sed                          PropertyListPtrTy,
3722193326Sed                          NULL);
3723198092Srdivacky  CGM.getModule().addTypeName("struct._objc_protocol_extension",
3724193326Sed                              ProtocolExtensionTy);
3725198092Srdivacky
3726193326Sed  // struct _objc_protocol_extension *
3727193326Sed  ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
3728193326Sed
3729193326Sed  // Handle recursive construction of Protocol and ProtocolList types
3730193326Sed
3731198092Srdivacky  llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
3732198092Srdivacky  llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
3733193326Sed
3734198092Srdivacky  const llvm::Type *T =
3735198092Srdivacky    llvm::StructType::get(VMContext,
3736198092Srdivacky                          llvm::PointerType::getUnqual(ProtocolListTyHolder),
3737193326Sed                          LongTy,
3738193326Sed                          llvm::ArrayType::get(ProtocolTyHolder, 0),
3739193326Sed                          NULL);
3740193326Sed  cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
3741193326Sed
3742193326Sed  // struct _objc_protocol {
3743193326Sed  //   struct _objc_protocol_extension *isa;
3744193326Sed  //   char *protocol_name;
3745193326Sed  //   struct _objc_protocol **_objc_protocol_list;
3746193326Sed  //   struct _objc_method_description_list *instance_methods;
3747193326Sed  //   struct _objc_method_description_list *class_methods;
3748193326Sed  // }
3749198092Srdivacky  T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
3750193326Sed                            Int8PtrTy,
3751193326Sed                            llvm::PointerType::getUnqual(ProtocolListTyHolder),
3752193326Sed                            MethodDescriptionListPtrTy,
3753193326Sed                            MethodDescriptionListPtrTy,
3754193326Sed                            NULL);
3755193326Sed  cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
3756193326Sed
3757193326Sed  ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
3758198092Srdivacky  CGM.getModule().addTypeName("struct._objc_protocol_list",
3759193326Sed                              ProtocolListTy);
3760193326Sed  // struct _objc_protocol_list *
3761193326Sed  ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
3762193326Sed
3763193326Sed  ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
3764193326Sed  CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
3765193326Sed  ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
3766193326Sed
3767193326Sed  // Class description structures
3768193326Sed
3769193326Sed  // struct _objc_ivar {
3770193326Sed  //   char *ivar_name;
3771193326Sed  //   char *ivar_type;
3772193326Sed  //   int  ivar_offset;
3773193326Sed  // }
3774198092Srdivacky  IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
3775198092Srdivacky                                 Int8PtrTy,
3776198092Srdivacky                                 IntTy,
3777193326Sed                                 NULL);
3778193326Sed  CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
3779193326Sed
3780193326Sed  // struct _objc_ivar_list *
3781198092Srdivacky  IvarListTy = llvm::OpaqueType::get(VMContext);
3782193326Sed  CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
3783193326Sed  IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
3784193326Sed
3785193326Sed  // struct _objc_method_list *
3786198092Srdivacky  MethodListTy = llvm::OpaqueType::get(VMContext);
3787193326Sed  CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
3788193326Sed  MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
3789193326Sed
3790193326Sed  // struct _objc_class_extension *
3791198092Srdivacky  ClassExtensionTy =
3792198092Srdivacky    llvm::StructType::get(VMContext, IntTy,
3793193326Sed                          Int8PtrTy,
3794193326Sed                          PropertyListPtrTy,
3795193326Sed                          NULL);
3796193326Sed  CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
3797193326Sed  ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
3798193326Sed
3799198092Srdivacky  llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
3800193326Sed
3801193326Sed  // struct _objc_class {
3802193326Sed  //   Class isa;
3803193326Sed  //   Class super_class;
3804193326Sed  //   char *name;
3805193326Sed  //   long version;
3806193326Sed  //   long info;
3807193326Sed  //   long instance_size;
3808193326Sed  //   struct _objc_ivar_list *ivars;
3809193326Sed  //   struct _objc_method_list *methods;
3810193326Sed  //   struct _objc_cache *cache;
3811193326Sed  //   struct _objc_protocol_list *protocols;
3812193326Sed  //   char *ivar_layout;
3813193326Sed  //   struct _objc_class_ext *ext;
3814193326Sed  // };
3815198092Srdivacky  T = llvm::StructType::get(VMContext,
3816193326Sed                            llvm::PointerType::getUnqual(ClassTyHolder),
3817198092Srdivacky                            llvm::PointerType::getUnqual(ClassTyHolder),
3818193326Sed                            Int8PtrTy,
3819193326Sed                            LongTy,
3820193326Sed                            LongTy,
3821193326Sed                            LongTy,
3822193326Sed                            IvarListPtrTy,
3823193326Sed                            MethodListPtrTy,
3824193326Sed                            CachePtrTy,
3825193326Sed                            ProtocolListPtrTy,
3826193326Sed                            Int8PtrTy,
3827193326Sed                            ClassExtensionPtrTy,
3828193326Sed                            NULL);
3829193326Sed  cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
3830198092Srdivacky
3831193326Sed  ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
3832193326Sed  CGM.getModule().addTypeName("struct._objc_class", ClassTy);
3833193326Sed  ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
3834193326Sed
3835193326Sed  // struct _objc_category {
3836193326Sed  //   char *category_name;
3837193326Sed  //   char *class_name;
3838193326Sed  //   struct _objc_method_list *instance_method;
3839193326Sed  //   struct _objc_method_list *class_method;
3840193326Sed  //   uint32_t size;  // sizeof(struct _objc_category)
3841193326Sed  //   struct _objc_property_list *instance_properties;// category's @property
3842193326Sed  // }
3843198092Srdivacky  CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
3844193326Sed                                     Int8PtrTy,
3845193326Sed                                     MethodListPtrTy,
3846193326Sed                                     MethodListPtrTy,
3847193326Sed                                     ProtocolListPtrTy,
3848193326Sed                                     IntTy,
3849193326Sed                                     PropertyListPtrTy,
3850193326Sed                                     NULL);
3851193326Sed  CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
3852193326Sed
3853193326Sed  // Global metadata structures
3854193326Sed
3855193326Sed  // struct _objc_symtab {
3856193326Sed  //   long sel_ref_cnt;
3857193326Sed  //   SEL *refs;
3858193326Sed  //   short cls_def_cnt;
3859193326Sed  //   short cat_def_cnt;
3860193326Sed  //   char *defs[cls_def_cnt + cat_def_cnt];
3861193326Sed  // }
3862198092Srdivacky  SymtabTy = llvm::StructType::get(VMContext, LongTy,
3863193326Sed                                   SelectorPtrTy,
3864193326Sed                                   ShortTy,
3865193326Sed                                   ShortTy,
3866193326Sed                                   llvm::ArrayType::get(Int8PtrTy, 0),
3867193326Sed                                   NULL);
3868193326Sed  CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
3869193326Sed  SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
3870193326Sed
3871193326Sed  // struct _objc_module {
3872193326Sed  //   long version;
3873193326Sed  //   long size;   // sizeof(struct _objc_module)
3874193326Sed  //   char *name;
3875193326Sed  //   struct _objc_symtab* symtab;
3876193326Sed  //  }
3877198092Srdivacky  ModuleTy =
3878198092Srdivacky    llvm::StructType::get(VMContext, LongTy,
3879193326Sed                          LongTy,
3880193326Sed                          Int8PtrTy,
3881193326Sed                          SymtabPtrTy,
3882193326Sed                          NULL);
3883193326Sed  CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
3884193326Sed
3885198092Srdivacky
3886193326Sed  // FIXME: This is the size of the setjmp buffer and should be target
3887193326Sed  // specific. 18 is what's used on 32-bit X86.
3888193326Sed  uint64_t SetJmpBufferSize = 18;
3889198092Srdivacky
3890193326Sed  // Exceptions
3891198092Srdivacky  const llvm::Type *StackPtrTy = llvm::ArrayType::get(
3892198092Srdivacky    llvm::Type::getInt8PtrTy(VMContext), 4);
3893198092Srdivacky
3894198092Srdivacky  ExceptionDataTy =
3895198092Srdivacky    llvm::StructType::get(VMContext, llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
3896198092Srdivacky                                                          SetJmpBufferSize),
3897193326Sed                          StackPtrTy, NULL);
3898198092Srdivacky  CGM.getModule().addTypeName("struct._objc_exception_data",
3899193326Sed                              ExceptionDataTy);
3900193326Sed
3901193326Sed}
3902193326Sed
3903198092SrdivackyObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
3904198092Srdivacky  : ObjCCommonTypesHelper(cgm) {
3905193326Sed  // struct _method_list_t {
3906193326Sed  //   uint32_t entsize;  // sizeof(struct _objc_method)
3907193326Sed  //   uint32_t method_count;
3908193326Sed  //   struct _objc_method method_list[method_count];
3909193326Sed  // }
3910198092Srdivacky  MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
3911193326Sed                                            IntTy,
3912193326Sed                                            llvm::ArrayType::get(MethodTy, 0),
3913193326Sed                                            NULL);
3914193326Sed  CGM.getModule().addTypeName("struct.__method_list_t",
3915193326Sed                              MethodListnfABITy);
3916193326Sed  // struct method_list_t *
3917193326Sed  MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
3918198092Srdivacky
3919193326Sed  // struct _protocol_t {
3920193326Sed  //   id isa;  // NULL
3921193326Sed  //   const char * const protocol_name;
3922193326Sed  //   const struct _protocol_list_t * protocol_list; // super protocols
3923193326Sed  //   const struct method_list_t * const instance_methods;
3924193326Sed  //   const struct method_list_t * const class_methods;
3925193326Sed  //   const struct method_list_t *optionalInstanceMethods;
3926193326Sed  //   const struct method_list_t *optionalClassMethods;
3927193326Sed  //   const struct _prop_list_t * properties;
3928193326Sed  //   const uint32_t size;  // sizeof(struct _protocol_t)
3929193326Sed  //   const uint32_t flags;  // = 0
3930193326Sed  // }
3931198092Srdivacky
3932193326Sed  // Holder for struct _protocol_list_t *
3933198092Srdivacky  llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
3934198092Srdivacky
3935198092Srdivacky  ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
3936193326Sed                                          Int8PtrTy,
3937193326Sed                                          llvm::PointerType::getUnqual(
3938193326Sed                                            ProtocolListTyHolder),
3939193326Sed                                          MethodListnfABIPtrTy,
3940193326Sed                                          MethodListnfABIPtrTy,
3941193326Sed                                          MethodListnfABIPtrTy,
3942193326Sed                                          MethodListnfABIPtrTy,
3943193326Sed                                          PropertyListPtrTy,
3944193326Sed                                          IntTy,
3945193326Sed                                          IntTy,
3946193326Sed                                          NULL);
3947193326Sed  CGM.getModule().addTypeName("struct._protocol_t",
3948193326Sed                              ProtocolnfABITy);
3949193326Sed
3950193326Sed  // struct _protocol_t*
3951193326Sed  ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
3952198092Srdivacky
3953193326Sed  // struct _protocol_list_t {
3954193326Sed  //   long protocol_count;   // Note, this is 32/64 bit
3955193326Sed  //   struct _protocol_t *[protocol_count];
3956193326Sed  // }
3957198092Srdivacky  ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
3958193326Sed                                              llvm::ArrayType::get(
3959193326Sed                                                ProtocolnfABIPtrTy, 0),
3960193326Sed                                              NULL);
3961193326Sed  CGM.getModule().addTypeName("struct._objc_protocol_list",
3962193326Sed                              ProtocolListnfABITy);
3963193326Sed  cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
3964198092Srdivacky    ProtocolListnfABITy);
3965198092Srdivacky
3966193326Sed  // struct _objc_protocol_list*
3967193326Sed  ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
3968198092Srdivacky
3969193326Sed  // struct _ivar_t {
3970193326Sed  //   unsigned long int *offset;  // pointer to ivar offset location
3971193326Sed  //   char *name;
3972193326Sed  //   char *type;
3973193326Sed  //   uint32_t alignment;
3974193326Sed  //   uint32_t size;
3975193326Sed  // }
3976198092Srdivacky  IvarnfABITy = llvm::StructType::get(VMContext,
3977198092Srdivacky                                      llvm::PointerType::getUnqual(LongTy),
3978193326Sed                                      Int8PtrTy,
3979193326Sed                                      Int8PtrTy,
3980193326Sed                                      IntTy,
3981193326Sed                                      IntTy,
3982193326Sed                                      NULL);
3983193326Sed  CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
3984198092Srdivacky
3985193326Sed  // struct _ivar_list_t {
3986193326Sed  //   uint32 entsize;  // sizeof(struct _ivar_t)
3987193326Sed  //   uint32 count;
3988193326Sed  //   struct _iver_t list[count];
3989193326Sed  // }
3990198092Srdivacky  IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
3991193326Sed                                          IntTy,
3992193326Sed                                          llvm::ArrayType::get(
3993198092Srdivacky                                            IvarnfABITy, 0),
3994193326Sed                                          NULL);
3995193326Sed  CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
3996198092Srdivacky
3997193326Sed  IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
3998198092Srdivacky
3999193326Sed  // struct _class_ro_t {
4000193326Sed  //   uint32_t const flags;
4001193326Sed  //   uint32_t const instanceStart;
4002193326Sed  //   uint32_t const instanceSize;
4003193326Sed  //   uint32_t const reserved;  // only when building for 64bit targets
4004193326Sed  //   const uint8_t * const ivarLayout;
4005193326Sed  //   const char *const name;
4006193326Sed  //   const struct _method_list_t * const baseMethods;
4007193326Sed  //   const struct _objc_protocol_list *const baseProtocols;
4008193326Sed  //   const struct _ivar_list_t *const ivars;
4009193326Sed  //   const uint8_t * const weakIvarLayout;
4010193326Sed  //   const struct _prop_list_t * const properties;
4011193326Sed  // }
4012198092Srdivacky
4013193326Sed  // FIXME. Add 'reserved' field in 64bit abi mode!
4014198092Srdivacky  ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
4015193326Sed                                         IntTy,
4016193326Sed                                         IntTy,
4017193326Sed                                         Int8PtrTy,
4018193326Sed                                         Int8PtrTy,
4019193326Sed                                         MethodListnfABIPtrTy,
4020193326Sed                                         ProtocolListnfABIPtrTy,
4021193326Sed                                         IvarListnfABIPtrTy,
4022193326Sed                                         Int8PtrTy,
4023193326Sed                                         PropertyListPtrTy,
4024193326Sed                                         NULL);
4025193326Sed  CGM.getModule().addTypeName("struct._class_ro_t",
4026193326Sed                              ClassRonfABITy);
4027198092Srdivacky
4028193326Sed  // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
4029193326Sed  std::vector<const llvm::Type*> Params;
4030193326Sed  Params.push_back(ObjectPtrTy);
4031193326Sed  Params.push_back(SelectorPtrTy);
4032193326Sed  ImpnfABITy = llvm::PointerType::getUnqual(
4033198092Srdivacky    llvm::FunctionType::get(ObjectPtrTy, Params, false));
4034198092Srdivacky
4035193326Sed  // struct _class_t {
4036193326Sed  //   struct _class_t *isa;
4037193326Sed  //   struct _class_t * const superclass;
4038193326Sed  //   void *cache;
4039193326Sed  //   IMP *vtable;
4040193326Sed  //   struct class_ro_t *ro;
4041193326Sed  // }
4042198092Srdivacky
4043198092Srdivacky  llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
4044198092Srdivacky  ClassnfABITy =
4045198092Srdivacky    llvm::StructType::get(VMContext,
4046198092Srdivacky                          llvm::PointerType::getUnqual(ClassTyHolder),
4047198092Srdivacky                          llvm::PointerType::getUnqual(ClassTyHolder),
4048198092Srdivacky                          CachePtrTy,
4049198092Srdivacky                          llvm::PointerType::getUnqual(ImpnfABITy),
4050198092Srdivacky                          llvm::PointerType::getUnqual(ClassRonfABITy),
4051198092Srdivacky                          NULL);
4052193326Sed  CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
4053193326Sed
4054193326Sed  cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
4055198092Srdivacky    ClassnfABITy);
4056198092Srdivacky
4057193326Sed  // LLVM for struct _class_t *
4058193326Sed  ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
4059198092Srdivacky
4060193326Sed  // struct _category_t {
4061193326Sed  //   const char * const name;
4062193326Sed  //   struct _class_t *const cls;
4063193326Sed  //   const struct _method_list_t * const instance_methods;
4064193326Sed  //   const struct _method_list_t * const class_methods;
4065193326Sed  //   const struct _protocol_list_t * const protocols;
4066193326Sed  //   const struct _prop_list_t * const properties;
4067193326Sed  // }
4068198092Srdivacky  CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
4069193326Sed                                          ClassnfABIPtrTy,
4070193326Sed                                          MethodListnfABIPtrTy,
4071193326Sed                                          MethodListnfABIPtrTy,
4072193326Sed                                          ProtocolListnfABIPtrTy,
4073193326Sed                                          PropertyListPtrTy,
4074193326Sed                                          NULL);
4075193326Sed  CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
4076198092Srdivacky
4077193326Sed  // New types for nonfragile abi messaging.
4078193326Sed  CodeGen::CodeGenTypes &Types = CGM.getTypes();
4079193326Sed  ASTContext &Ctx = CGM.getContext();
4080198092Srdivacky
4081193326Sed  // MessageRefTy - LLVM for:
4082193326Sed  // struct _message_ref_t {
4083193326Sed  //   IMP messenger;
4084193326Sed  //   SEL name;
4085193326Sed  // };
4086198092Srdivacky
4087193326Sed  // First the clang type for struct _message_ref_t
4088193326Sed  RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
4089193326Sed                                      SourceLocation(),
4090193326Sed                                      &Ctx.Idents.get("_message_ref_t"));
4091195341Sed  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
4092198092Srdivacky                                Ctx.VoidPtrTy, 0, 0, false));
4093195341Sed  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
4094198092Srdivacky                                Ctx.getObjCSelType(), 0, 0, false));
4095203955Srdivacky  RD->completeDefinition();
4096198092Srdivacky
4097193326Sed  MessageRefCTy = Ctx.getTagDeclType(RD);
4098193326Sed  MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4099193326Sed  MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
4100198092Srdivacky
4101193326Sed  // MessageRefPtrTy - LLVM for struct _message_ref_t*
4102193326Sed  MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
4103198092Srdivacky
4104193326Sed  // SuperMessageRefTy - LLVM for:
4105193326Sed  // struct _super_message_ref_t {
4106193326Sed  //   SUPER_IMP messenger;
4107193326Sed  //   SEL name;
4108193326Sed  // };
4109198092Srdivacky  SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
4110193326Sed                                            SelectorPtrTy,
4111193326Sed                                            NULL);
4112193326Sed  CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
4113198092Srdivacky
4114193326Sed  // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
4115198092Srdivacky  SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
4116193326Sed
4117198092Srdivacky
4118193326Sed  // struct objc_typeinfo {
4119193326Sed  //   const void** vtable; // objc_ehtype_vtable + 2
4120193326Sed  //   const char*  name;    // c++ typeinfo string
4121193326Sed  //   Class        cls;
4122193326Sed  // };
4123198092Srdivacky  EHTypeTy = llvm::StructType::get(VMContext,
4124198092Srdivacky                                   llvm::PointerType::getUnqual(Int8PtrTy),
4125193326Sed                                   Int8PtrTy,
4126193326Sed                                   ClassnfABIPtrTy,
4127193326Sed                                   NULL);
4128193326Sed  CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
4129193326Sed  EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
4130193326Sed}
4131193326Sed
4132198092Srdivackyllvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
4133193326Sed  FinishNonFragileABIModule();
4134198092Srdivacky
4135193326Sed  return NULL;
4136193326Sed}
4137193326Sed
4138198092Srdivackyvoid CGObjCNonFragileABIMac::AddModuleClassList(const
4139198092Srdivacky                                                std::vector<llvm::GlobalValue*>
4140198092Srdivacky                                                &Container,
4141193326Sed                                                const char *SymbolName,
4142193326Sed                                                const char *SectionName) {
4143193326Sed  unsigned NumClasses = Container.size();
4144198092Srdivacky
4145193326Sed  if (!NumClasses)
4146193326Sed    return;
4147198092Srdivacky
4148193326Sed  std::vector<llvm::Constant*> Symbols(NumClasses);
4149193326Sed  for (unsigned i=0; i<NumClasses; i++)
4150193326Sed    Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
4151193326Sed                                                ObjCTypes.Int8PtrTy);
4152198092Srdivacky  llvm::Constant* Init =
4153193326Sed    llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
4154193326Sed                                                  NumClasses),
4155193326Sed                             Symbols);
4156198092Srdivacky
4157193326Sed  llvm::GlobalVariable *GV =
4158198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
4159193326Sed                             llvm::GlobalValue::InternalLinkage,
4160193326Sed                             Init,
4161198092Srdivacky                             SymbolName);
4162193326Sed  GV->setAlignment(8);
4163193326Sed  GV->setSection(SectionName);
4164198092Srdivacky  CGM.AddUsedGlobal(GV);
4165193326Sed}
4166198092Srdivacky
4167193326Sedvoid CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4168193326Sed  // nonfragile abi has no module definition.
4169198092Srdivacky
4170193326Sed  // Build list of all implemented class addresses in array
4171193326Sed  // L_OBJC_LABEL_CLASS_$.
4172198092Srdivacky  AddModuleClassList(DefinedClasses,
4173193326Sed                     "\01L_OBJC_LABEL_CLASS_$",
4174193326Sed                     "__DATA, __objc_classlist, regular, no_dead_strip");
4175199482Srdivacky
4176199482Srdivacky  for (unsigned i = 0; i < DefinedClasses.size(); i++) {
4177199482Srdivacky    llvm::GlobalValue *IMPLGV = DefinedClasses[i];
4178199482Srdivacky    if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4179199482Srdivacky      continue;
4180199482Srdivacky    IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4181199482Srdivacky  }
4182199482Srdivacky
4183200583Srdivacky  for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
4184200583Srdivacky    llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
4185200583Srdivacky    if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4186200583Srdivacky      continue;
4187200583Srdivacky    IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4188200583Srdivacky  }
4189199482Srdivacky
4190198092Srdivacky  AddModuleClassList(DefinedNonLazyClasses,
4191193326Sed                     "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4192193326Sed                     "__DATA, __objc_nlclslist, regular, no_dead_strip");
4193198092Srdivacky
4194193326Sed  // Build list of all implemented category addresses in array
4195193326Sed  // L_OBJC_LABEL_CATEGORY_$.
4196198092Srdivacky  AddModuleClassList(DefinedCategories,
4197193326Sed                     "\01L_OBJC_LABEL_CATEGORY_$",
4198193326Sed                     "__DATA, __objc_catlist, regular, no_dead_strip");
4199198092Srdivacky  AddModuleClassList(DefinedNonLazyCategories,
4200193326Sed                     "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4201193326Sed                     "__DATA, __objc_nlcatlist, regular, no_dead_strip");
4202198092Srdivacky
4203193326Sed  //  static int L_OBJC_IMAGE_INFO[2] = { 0, flags };
4204193326Sed  // FIXME. flags can be 0 | 1 | 2 | 6. For now just use 0
4205193326Sed  std::vector<llvm::Constant*> Values(2);
4206193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, 0);
4207193326Sed  unsigned int flags = 0;
4208193326Sed  // FIXME: Fix and continue?
4209193326Sed  if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
4210193326Sed    flags |= eImageInfo_GarbageCollected;
4211193326Sed  if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
4212193326Sed    flags |= eImageInfo_GCOnly;
4213193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4214193326Sed  llvm::Constant* Init = llvm::ConstantArray::get(
4215198092Srdivacky    llvm::ArrayType::get(ObjCTypes.IntTy, 2),
4216198092Srdivacky    Values);
4217193326Sed  llvm::GlobalVariable *IMGV =
4218198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
4219193326Sed                             llvm::GlobalValue::InternalLinkage,
4220193326Sed                             Init,
4221198092Srdivacky                             "\01L_OBJC_IMAGE_INFO");
4222193326Sed  IMGV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip");
4223193326Sed  IMGV->setConstant(true);
4224198092Srdivacky  CGM.AddUsedGlobal(IMGV);
4225193326Sed}
4226193326Sed
4227193326Sed/// LegacyDispatchedSelector - Returns true if SEL is not in the list of
4228193326Sed/// NonLegacyDispatchMethods; false otherwise. What this means is that
4229198092Srdivacky/// except for the 19 selectors in the list, we generate 32bit-style
4230193326Sed/// message dispatch call for all the rest.
4231193326Sed///
4232193326Sedbool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) {
4233203955Srdivacky  if (CGM.getCodeGenOpts().ObjCLegacyDispatch)
4234203955Srdivacky    return true;
4235203955Srdivacky
4236193326Sed  if (NonLegacyDispatchMethods.empty()) {
4237193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("alloc"));
4238193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("class"));
4239193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("self"));
4240193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("isFlipped"));
4241193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("length"));
4242193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("count"));
4243193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("retain"));
4244193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("release"));
4245193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("autorelease"));
4246193326Sed    NonLegacyDispatchMethods.insert(GetNullarySelector("hash"));
4247198092Srdivacky
4248193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("allocWithZone"));
4249193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
4250193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
4251193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("objectForKey"));
4252193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
4253193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("isEqualToString"));
4254193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("isEqual"));
4255193326Sed    NonLegacyDispatchMethods.insert(GetUnarySelector("addObject"));
4256198092Srdivacky    // "countByEnumeratingWithState:objects:count"
4257193326Sed    IdentifierInfo *KeyIdents[] = {
4258198092Srdivacky      &CGM.getContext().Idents.get("countByEnumeratingWithState"),
4259198092Srdivacky      &CGM.getContext().Idents.get("objects"),
4260198092Srdivacky      &CGM.getContext().Idents.get("count")
4261193326Sed    };
4262193326Sed    NonLegacyDispatchMethods.insert(
4263193326Sed      CGM.getContext().Selectors.getSelector(3, KeyIdents));
4264193326Sed  }
4265193326Sed  return (NonLegacyDispatchMethods.count(Sel) == 0);
4266193326Sed}
4267193326Sed
4268193326Sed// Metadata flags
4269193326Sedenum MetaDataDlags {
4270193326Sed  CLS = 0x0,
4271193326Sed  CLS_META = 0x1,
4272193326Sed  CLS_ROOT = 0x2,
4273193326Sed  OBJC2_CLS_HIDDEN = 0x10,
4274193326Sed  CLS_EXCEPTION = 0x20
4275193326Sed};
4276193326Sed/// BuildClassRoTInitializer - generate meta-data for:
4277193326Sed/// struct _class_ro_t {
4278193326Sed///   uint32_t const flags;
4279193326Sed///   uint32_t const instanceStart;
4280193326Sed///   uint32_t const instanceSize;
4281193326Sed///   uint32_t const reserved;  // only when building for 64bit targets
4282193326Sed///   const uint8_t * const ivarLayout;
4283193326Sed///   const char *const name;
4284193326Sed///   const struct _method_list_t * const baseMethods;
4285193326Sed///   const struct _protocol_list_t *const baseProtocols;
4286193326Sed///   const struct _ivar_list_t *const ivars;
4287193326Sed///   const uint8_t * const weakIvarLayout;
4288193326Sed///   const struct _prop_list_t * const properties;
4289193326Sed/// }
4290193326Sed///
4291193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
4292198092Srdivacky  unsigned flags,
4293198092Srdivacky  unsigned InstanceStart,
4294198092Srdivacky  unsigned InstanceSize,
4295198092Srdivacky  const ObjCImplementationDecl *ID) {
4296193326Sed  std::string ClassName = ID->getNameAsString();
4297193326Sed  std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
4298193326Sed  Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4299193326Sed  Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
4300193326Sed  Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
4301193326Sed  // FIXME. For 64bit targets add 0 here.
4302198092Srdivacky  Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4303198092Srdivacky    : BuildIvarLayout(ID, true);
4304193326Sed  Values[ 4] = GetClassName(ID->getIdentifier());
4305193326Sed  // const struct _method_list_t * const baseMethods;
4306193326Sed  std::vector<llvm::Constant*> Methods;
4307193326Sed  std::string MethodListName("\01l_OBJC_$_");
4308193326Sed  if (flags & CLS_META) {
4309193326Sed    MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
4310198092Srdivacky    for (ObjCImplementationDecl::classmeth_iterator
4311195341Sed           i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
4312193326Sed      // Class methods should always be defined.
4313193326Sed      Methods.push_back(GetMethodConstant(*i));
4314193326Sed    }
4315193326Sed  } else {
4316193326Sed    MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
4317198092Srdivacky    for (ObjCImplementationDecl::instmeth_iterator
4318195341Sed           i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
4319193326Sed      // Instance methods should always be defined.
4320193326Sed      Methods.push_back(GetMethodConstant(*i));
4321193326Sed    }
4322198092Srdivacky    for (ObjCImplementationDecl::propimpl_iterator
4323195341Sed           i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
4324193326Sed      ObjCPropertyImplDecl *PID = *i;
4325198092Srdivacky
4326193326Sed      if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4327193326Sed        ObjCPropertyDecl *PD = PID->getPropertyDecl();
4328198092Srdivacky
4329193326Sed        if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
4330193326Sed          if (llvm::Constant *C = GetMethodConstant(MD))
4331193326Sed            Methods.push_back(C);
4332193326Sed        if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
4333193326Sed          if (llvm::Constant *C = GetMethodConstant(MD))
4334193326Sed            Methods.push_back(C);
4335193326Sed      }
4336193326Sed    }
4337193326Sed  }
4338198092Srdivacky  Values[ 5] = EmitMethodList(MethodListName,
4339198092Srdivacky                              "__DATA, __objc_const", Methods);
4340198092Srdivacky
4341193326Sed  const ObjCInterfaceDecl *OID = ID->getClassInterface();
4342193326Sed  assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
4343198092Srdivacky  Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
4344198398Srdivacky                                + OID->getName(),
4345193326Sed                                OID->protocol_begin(),
4346193326Sed                                OID->protocol_end());
4347198092Srdivacky
4348193326Sed  if (flags & CLS_META)
4349193326Sed    Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
4350193326Sed  else
4351193326Sed    Values[ 7] = EmitIvarList(ID);
4352198092Srdivacky  Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4353198092Srdivacky    : BuildIvarLayout(ID, false);
4354193326Sed  if (flags & CLS_META)
4355193326Sed    Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
4356193326Sed  else
4357198398Srdivacky    Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4358198398Srdivacky                                  ID, ID->getClassInterface(), ObjCTypes);
4359193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
4360193326Sed                                                   Values);
4361193326Sed  llvm::GlobalVariable *CLASS_RO_GV =
4362198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
4363198092Srdivacky                             llvm::GlobalValue::InternalLinkage,
4364198092Srdivacky                             Init,
4365198092Srdivacky                             (flags & CLS_META) ?
4366198092Srdivacky                             std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
4367198092Srdivacky                             std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
4368193326Sed  CLASS_RO_GV->setAlignment(
4369193326Sed    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassRonfABITy));
4370193326Sed  CLASS_RO_GV->setSection("__DATA, __objc_const");
4371193326Sed  return CLASS_RO_GV;
4372193326Sed
4373193326Sed}
4374193326Sed
4375193326Sed/// BuildClassMetaData - This routine defines that to-level meta-data
4376193326Sed/// for the given ClassName for:
4377193326Sed/// struct _class_t {
4378193326Sed///   struct _class_t *isa;
4379193326Sed///   struct _class_t * const superclass;
4380193326Sed///   void *cache;
4381193326Sed///   IMP *vtable;
4382193326Sed///   struct class_ro_t *ro;
4383193326Sed/// }
4384193326Sed///
4385193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
4386198092Srdivacky  std::string &ClassName,
4387198092Srdivacky  llvm::Constant *IsAGV,
4388198092Srdivacky  llvm::Constant *SuperClassGV,
4389198092Srdivacky  llvm::Constant *ClassRoGV,
4390198092Srdivacky  bool HiddenVisibility) {
4391193326Sed  std::vector<llvm::Constant*> Values(5);
4392193326Sed  Values[0] = IsAGV;
4393198092Srdivacky  Values[1] = SuperClassGV;
4394198092Srdivacky  if (!Values[1])
4395198092Srdivacky    Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
4396193326Sed  Values[2] = ObjCEmptyCacheVar;  // &ObjCEmptyCacheVar
4397193326Sed  Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4398193326Sed  Values[4] = ClassRoGV;                 // &CLASS_RO_GV
4399198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
4400193326Sed                                                   Values);
4401193326Sed  llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4402193326Sed  GV->setInitializer(Init);
4403193326Sed  GV->setSection("__DATA, __objc_data");
4404193326Sed  GV->setAlignment(
4405193326Sed    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassnfABITy));
4406193326Sed  if (HiddenVisibility)
4407193326Sed    GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4408193326Sed  return GV;
4409193326Sed}
4410193326Sed
4411198092Srdivackybool
4412193326SedCGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
4413195341Sed  return OD->getClassMethod(GetNullarySelector("load")) != 0;
4414193326Sed}
4415193326Sed
4416193326Sedvoid CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
4417193326Sed                                              uint32_t &InstanceStart,
4418193326Sed                                              uint32_t &InstanceSize) {
4419198092Srdivacky  const ASTRecordLayout &RL =
4420193326Sed    CGM.getContext().getASTObjCImplementationLayout(OID);
4421198092Srdivacky
4422193326Sed  // InstanceSize is really instance end.
4423198092Srdivacky  InstanceSize = llvm::RoundUpToAlignment(RL.getDataSize(), 8) / 8;
4424193326Sed
4425193326Sed  // If there are no fields, the start is the same as the end.
4426193326Sed  if (!RL.getFieldCount())
4427193326Sed    InstanceStart = InstanceSize;
4428193326Sed  else
4429193326Sed    InstanceStart = RL.getFieldOffset(0) / 8;
4430193326Sed}
4431193326Sed
4432193326Sedvoid CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
4433193326Sed  std::string ClassName = ID->getNameAsString();
4434193326Sed  if (!ObjCEmptyCacheVar) {
4435193326Sed    ObjCEmptyCacheVar = new llvm::GlobalVariable(
4436198092Srdivacky      CGM.getModule(),
4437198092Srdivacky      ObjCTypes.CacheTy,
4438198092Srdivacky      false,
4439198092Srdivacky      llvm::GlobalValue::ExternalLinkage,
4440198092Srdivacky      0,
4441198092Srdivacky      "_objc_empty_cache");
4442198092Srdivacky
4443193326Sed    ObjCEmptyVtableVar = new llvm::GlobalVariable(
4444198092Srdivacky      CGM.getModule(),
4445198092Srdivacky      ObjCTypes.ImpnfABITy,
4446198092Srdivacky      false,
4447198092Srdivacky      llvm::GlobalValue::ExternalLinkage,
4448198092Srdivacky      0,
4449198092Srdivacky      "_objc_empty_vtable");
4450193326Sed  }
4451198092Srdivacky  assert(ID->getClassInterface() &&
4452193326Sed         "CGObjCNonFragileABIMac::GenerateClass - class is 0");
4453193326Sed  // FIXME: Is this correct (that meta class size is never computed)?
4454198092Srdivacky  uint32_t InstanceStart =
4455193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
4456193326Sed  uint32_t InstanceSize = InstanceStart;
4457193326Sed  uint32_t flags = CLS_META;
4458193326Sed  std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4459193326Sed  std::string ObjCClassName(getClassSymbolPrefix());
4460198092Srdivacky
4461193326Sed  llvm::GlobalVariable *SuperClassGV, *IsAGV;
4462198092Srdivacky
4463198092Srdivacky  bool classIsHidden =
4464193326Sed    CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden;
4465193326Sed  if (classIsHidden)
4466193326Sed    flags |= OBJC2_CLS_HIDDEN;
4467193326Sed  if (!ID->getClassInterface()->getSuperClass()) {
4468193326Sed    // class is root
4469193326Sed    flags |= CLS_ROOT;
4470193326Sed    SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
4471193326Sed    IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
4472193326Sed  } else {
4473193326Sed    // Has a root. Current class is not a root.
4474193326Sed    const ObjCInterfaceDecl *Root = ID->getClassInterface();
4475193326Sed    while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4476193326Sed      Root = Super;
4477193326Sed    IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
4478200583Srdivacky    if (Root->hasAttr<WeakImportAttr>())
4479200583Srdivacky      IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
4480193326Sed    // work on super class metadata symbol.
4481198092Srdivacky    std::string SuperClassName =
4482200583Srdivacky      ObjCMetaClassName +
4483200583Srdivacky        ID->getClassInterface()->getSuperClass()->getNameAsString();
4484193326Sed    SuperClassGV = GetClassGlobal(SuperClassName);
4485199482Srdivacky    if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
4486199482Srdivacky      SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
4487193326Sed  }
4488193326Sed  llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4489193326Sed                                                               InstanceStart,
4490193326Sed                                                               InstanceSize,ID);
4491193326Sed  std::string TClassName = ObjCMetaClassName + ClassName;
4492198092Srdivacky  llvm::GlobalVariable *MetaTClass =
4493193326Sed    BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4494193326Sed                       classIsHidden);
4495199482Srdivacky  DefinedMetaClasses.push_back(MetaTClass);
4496193326Sed
4497193326Sed  // Metadata for the class
4498193326Sed  flags = CLS;
4499193326Sed  if (classIsHidden)
4500193326Sed    flags |= OBJC2_CLS_HIDDEN;
4501193326Sed
4502194613Sed  if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
4503193326Sed    flags |= CLS_EXCEPTION;
4504193326Sed
4505193326Sed  if (!ID->getClassInterface()->getSuperClass()) {
4506193326Sed    flags |= CLS_ROOT;
4507193326Sed    SuperClassGV = 0;
4508193326Sed  } else {
4509193326Sed    // Has a root. Current class is not a root.
4510193326Sed    std::string RootClassName =
4511193326Sed      ID->getClassInterface()->getSuperClass()->getNameAsString();
4512193326Sed    SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
4513199482Srdivacky    if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
4514199482Srdivacky      SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
4515193326Sed  }
4516193326Sed  GetClassSizeInfo(ID, InstanceStart, InstanceSize);
4517193326Sed  CLASS_RO_GV = BuildClassRoTInitializer(flags,
4518193326Sed                                         InstanceStart,
4519198092Srdivacky                                         InstanceSize,
4520193326Sed                                         ID);
4521198092Srdivacky
4522193326Sed  TClassName = ObjCClassName + ClassName;
4523198092Srdivacky  llvm::GlobalVariable *ClassMD =
4524193326Sed    BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
4525193326Sed                       classIsHidden);
4526193326Sed  DefinedClasses.push_back(ClassMD);
4527193326Sed
4528193326Sed  // Determine if this class is also "non-lazy".
4529193326Sed  if (ImplementationIsNonLazy(ID))
4530193326Sed    DefinedNonLazyClasses.push_back(ClassMD);
4531193326Sed
4532193326Sed  // Force the definition of the EHType if necessary.
4533193326Sed  if (flags & CLS_EXCEPTION)
4534193326Sed    GetInterfaceEHType(ID->getClassInterface(), true);
4535193326Sed}
4536193326Sed
4537193326Sed/// GenerateProtocolRef - This routine is called to generate code for
4538193326Sed/// a protocol reference expression; as in:
4539193326Sed/// @code
4540193326Sed///   @protocol(Proto1);
4541193326Sed/// @endcode
4542193326Sed/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
4543193326Sed/// which will hold address of the protocol meta-data.
4544193326Sed///
4545193326Sedllvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
4546198092Srdivacky                                                         const ObjCProtocolDecl *PD) {
4547198092Srdivacky
4548193326Sed  // This routine is called for @protocol only. So, we must build definition
4549193326Sed  // of protocol's meta-data (not a reference to it!)
4550193326Sed  //
4551198092Srdivacky  llvm::Constant *Init =
4552198092Srdivacky    llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
4553198092Srdivacky                                   ObjCTypes.ExternalProtocolPtrTy);
4554198092Srdivacky
4555193326Sed  std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
4556193326Sed  ProtocolName += PD->getNameAsCString();
4557198092Srdivacky
4558193326Sed  llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
4559193326Sed  if (PTGV)
4560199990Srdivacky    return Builder.CreateLoad(PTGV, "tmp");
4561193326Sed  PTGV = new llvm::GlobalVariable(
4562198092Srdivacky    CGM.getModule(),
4563198092Srdivacky    Init->getType(), false,
4564198092Srdivacky    llvm::GlobalValue::WeakAnyLinkage,
4565198092Srdivacky    Init,
4566198092Srdivacky    ProtocolName);
4567193326Sed  PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
4568193326Sed  PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4569198092Srdivacky  CGM.AddUsedGlobal(PTGV);
4570199990Srdivacky  return Builder.CreateLoad(PTGV, "tmp");
4571193326Sed}
4572193326Sed
4573193326Sed/// GenerateCategory - Build metadata for a category implementation.
4574193326Sed/// struct _category_t {
4575193326Sed///   const char * const name;
4576193326Sed///   struct _class_t *const cls;
4577193326Sed///   const struct _method_list_t * const instance_methods;
4578193326Sed///   const struct _method_list_t * const class_methods;
4579193326Sed///   const struct _protocol_list_t * const protocols;
4580193326Sed///   const struct _prop_list_t * const properties;
4581193326Sed/// }
4582193326Sed///
4583193326Sedvoid CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
4584193326Sed  const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
4585193326Sed  const char *Prefix = "\01l_OBJC_$_CATEGORY_";
4586198092Srdivacky  std::string ExtCatName(Prefix + Interface->getNameAsString()+
4587198092Srdivacky                         "_$_" + OCD->getNameAsString());
4588198092Srdivacky  std::string ExtClassName(getClassSymbolPrefix() +
4589193326Sed                           Interface->getNameAsString());
4590198092Srdivacky
4591193326Sed  std::vector<llvm::Constant*> Values(6);
4592193326Sed  Values[0] = GetClassName(OCD->getIdentifier());
4593193326Sed  // meta-class entry symbol
4594193326Sed  llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
4595199482Srdivacky  if (Interface->hasAttr<WeakImportAttr>())
4596199482Srdivacky    ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
4597199482Srdivacky
4598193326Sed  Values[1] = ClassGV;
4599193326Sed  std::vector<llvm::Constant*> Methods;
4600193326Sed  std::string MethodListName(Prefix);
4601198092Srdivacky  MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
4602193326Sed    "_$_" + OCD->getNameAsString();
4603198092Srdivacky
4604198092Srdivacky  for (ObjCCategoryImplDecl::instmeth_iterator
4605195341Sed         i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
4606193326Sed    // Instance methods should always be defined.
4607193326Sed    Methods.push_back(GetMethodConstant(*i));
4608193326Sed  }
4609198092Srdivacky
4610198092Srdivacky  Values[2] = EmitMethodList(MethodListName,
4611198092Srdivacky                             "__DATA, __objc_const",
4612193326Sed                             Methods);
4613193326Sed
4614193326Sed  MethodListName = Prefix;
4615193326Sed  MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
4616193326Sed    OCD->getNameAsString();
4617193326Sed  Methods.clear();
4618198092Srdivacky  for (ObjCCategoryImplDecl::classmeth_iterator
4619195341Sed         i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
4620193326Sed    // Class methods should always be defined.
4621193326Sed    Methods.push_back(GetMethodConstant(*i));
4622193326Sed  }
4623198092Srdivacky
4624198092Srdivacky  Values[3] = EmitMethodList(MethodListName,
4625198092Srdivacky                             "__DATA, __objc_const",
4626193326Sed                             Methods);
4627198092Srdivacky  const ObjCCategoryDecl *Category =
4628193326Sed    Interface->FindCategoryDeclaration(OCD->getIdentifier());
4629193326Sed  if (Category) {
4630198398Srdivacky    llvm::SmallString<256> ExtName;
4631198398Srdivacky    llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
4632198398Srdivacky                                       << OCD->getName();
4633193326Sed    Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
4634198398Srdivacky                                 + Interface->getName() + "_$_"
4635198398Srdivacky                                 + Category->getName(),
4636193326Sed                                 Category->protocol_begin(),
4637193326Sed                                 Category->protocol_end());
4638198398Srdivacky    Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
4639198398Srdivacky                                 OCD, Category, ObjCTypes);
4640198092Srdivacky  } else {
4641193326Sed    Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
4642193326Sed    Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
4643193326Sed  }
4644198092Srdivacky
4645198092Srdivacky  llvm::Constant *Init =
4646198092Srdivacky    llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
4647193326Sed                              Values);
4648193326Sed  llvm::GlobalVariable *GCATV
4649198092Srdivacky    = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
4650193326Sed                               false,
4651193326Sed                               llvm::GlobalValue::InternalLinkage,
4652193326Sed                               Init,
4653198092Srdivacky                               ExtCatName);
4654193326Sed  GCATV->setAlignment(
4655193326Sed    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.CategorynfABITy));
4656193326Sed  GCATV->setSection("__DATA, __objc_const");
4657198092Srdivacky  CGM.AddUsedGlobal(GCATV);
4658193326Sed  DefinedCategories.push_back(GCATV);
4659193326Sed
4660193326Sed  // Determine if this category is also "non-lazy".
4661193326Sed  if (ImplementationIsNonLazy(OCD))
4662193326Sed    DefinedNonLazyCategories.push_back(GCATV);
4663193326Sed}
4664193326Sed
4665193326Sed/// GetMethodConstant - Return a struct objc_method constant for the
4666193326Sed/// given method if it has been defined. The result is null if the
4667193326Sed/// method has not been defined. The return value has type MethodPtrTy.
4668193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
4669198092Srdivacky  const ObjCMethodDecl *MD) {
4670193326Sed  // FIXME: Use DenseMap::lookup
4671193326Sed  llvm::Function *Fn = MethodDefinitions[MD];
4672193326Sed  if (!Fn)
4673193326Sed    return 0;
4674198092Srdivacky
4675193326Sed  std::vector<llvm::Constant*> Method(3);
4676198092Srdivacky  Method[0] =
4677198092Srdivacky    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
4678198092Srdivacky                                   ObjCTypes.SelectorPtrTy);
4679193326Sed  Method[1] = GetMethodVarType(MD);
4680193326Sed  Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
4681193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
4682193326Sed}
4683193326Sed
4684193326Sed/// EmitMethodList - Build meta-data for method declarations
4685193326Sed/// struct _method_list_t {
4686193326Sed///   uint32_t entsize;  // sizeof(struct _objc_method)
4687193326Sed///   uint32_t method_count;
4688193326Sed///   struct _objc_method method_list[method_count];
4689193326Sed/// }
4690193326Sed///
4691198398Srdivackyllvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
4692198398Srdivacky                                                       const char *Section,
4693198398Srdivacky                                                const ConstantVector &Methods) {
4694193326Sed  // Return null for empty list.
4695193326Sed  if (Methods.empty())
4696193326Sed    return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
4697198092Srdivacky
4698193326Sed  std::vector<llvm::Constant*> Values(3);
4699193326Sed  // sizeof(struct _objc_method)
4700193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
4701193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4702193326Sed  // method_count
4703193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
4704193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
4705193326Sed                                             Methods.size());
4706193326Sed  Values[2] = llvm::ConstantArray::get(AT, Methods);
4707198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
4708198092Srdivacky
4709193326Sed  llvm::GlobalVariable *GV =
4710198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
4711193326Sed                             llvm::GlobalValue::InternalLinkage,
4712193326Sed                             Init,
4713198092Srdivacky                             Name);
4714193326Sed  GV->setAlignment(
4715193326Sed    CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
4716193326Sed  GV->setSection(Section);
4717198092Srdivacky  CGM.AddUsedGlobal(GV);
4718193326Sed  return llvm::ConstantExpr::getBitCast(GV,
4719193326Sed                                        ObjCTypes.MethodListnfABIPtrTy);
4720193326Sed}
4721193326Sed
4722193326Sed/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
4723193326Sed/// the given ivar.
4724193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(
4725198092Srdivacky  const ObjCInterfaceDecl *ID,
4726198092Srdivacky  const ObjCIvarDecl *Ivar) {
4727193326Sed  // FIXME: We shouldn't need to do this lookup.
4728193326Sed  unsigned Index;
4729198092Srdivacky  const ObjCInterfaceDecl *Container =
4730193326Sed    FindIvarInterface(CGM.getContext(), ID, Ivar, Index);
4731193326Sed  assert(Container && "Unable to find ivar container!");
4732193326Sed  std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
4733193326Sed    '.' + Ivar->getNameAsString();
4734198092Srdivacky  llvm::GlobalVariable *IvarOffsetGV =
4735193326Sed    CGM.getModule().getGlobalVariable(Name);
4736193326Sed  if (!IvarOffsetGV)
4737198092Srdivacky    IvarOffsetGV =
4738198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
4739193326Sed                               false,
4740193326Sed                               llvm::GlobalValue::ExternalLinkage,
4741193326Sed                               0,
4742198092Srdivacky                               Name);
4743193326Sed  return IvarOffsetGV;
4744193326Sed}
4745193326Sed
4746193326Sedllvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar(
4747198092Srdivacky  const ObjCInterfaceDecl *ID,
4748198092Srdivacky  const ObjCIvarDecl *Ivar,
4749198092Srdivacky  unsigned long int Offset) {
4750193326Sed  llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
4751198092Srdivacky  IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
4752193326Sed                                                      Offset));
4753193326Sed  IvarOffsetGV->setAlignment(
4754193326Sed    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy));
4755193326Sed
4756193326Sed  // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
4757193326Sed  // well (i.e., in ObjCIvarOffsetVariable).
4758193326Sed  if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
4759193326Sed      Ivar->getAccessControl() == ObjCIvarDecl::Package ||
4760193326Sed      CGM.getDeclVisibilityMode(ID) == LangOptions::Hidden)
4761193326Sed    IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4762193326Sed  else
4763193326Sed    IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
4764193326Sed  IvarOffsetGV->setSection("__DATA, __objc_const");
4765193326Sed  return IvarOffsetGV;
4766193326Sed}
4767193326Sed
4768193326Sed/// EmitIvarList - Emit the ivar list for the given
4769193326Sed/// implementation. The return value has type
4770193326Sed/// IvarListnfABIPtrTy.
4771193326Sed///  struct _ivar_t {
4772193326Sed///   unsigned long int *offset;  // pointer to ivar offset location
4773193326Sed///   char *name;
4774193326Sed///   char *type;
4775193326Sed///   uint32_t alignment;
4776193326Sed///   uint32_t size;
4777193326Sed/// }
4778193326Sed/// struct _ivar_list_t {
4779193326Sed///   uint32 entsize;  // sizeof(struct _ivar_t)
4780193326Sed///   uint32 count;
4781193326Sed///   struct _iver_t list[count];
4782193326Sed/// }
4783193326Sed///
4784193326Sed
4785193326Sedllvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
4786198092Srdivacky  const ObjCImplementationDecl *ID) {
4787198092Srdivacky
4788193326Sed  std::vector<llvm::Constant*> Ivars, Ivar(5);
4789198092Srdivacky
4790193326Sed  const ObjCInterfaceDecl *OID = ID->getClassInterface();
4791193326Sed  assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
4792198092Srdivacky
4793193326Sed  // FIXME. Consolidate this with similar code in GenerateClass.
4794198092Srdivacky
4795193326Sed  // Collect declared and synthesized ivars in a small vector.
4796193326Sed  llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
4797193576Sed  CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
4798198092Srdivacky
4799193326Sed  for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
4800193326Sed    ObjCIvarDecl *IVD = OIvars[i];
4801193576Sed    // Ignore unnamed bit-fields.
4802193576Sed    if (!IVD->getDeclName())
4803193576Sed      continue;
4804198092Srdivacky    Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
4805193326Sed                                ComputeIvarBaseOffset(CGM, ID, IVD));
4806193326Sed    Ivar[1] = GetMethodVarName(IVD->getIdentifier());
4807193326Sed    Ivar[2] = GetMethodVarType(IVD);
4808193326Sed    const llvm::Type *FieldTy =
4809193326Sed      CGM.getTypes().ConvertTypeForMem(IVD->getType());
4810193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
4811193326Sed    unsigned Align = CGM.getContext().getPreferredTypeAlign(
4812198092Srdivacky      IVD->getType().getTypePtr()) >> 3;
4813193326Sed    Align = llvm::Log2_32(Align);
4814193326Sed    Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
4815193326Sed    // NOTE. Size of a bitfield does not match gcc's, because of the
4816193326Sed    // way bitfields are treated special in each. But I am told that
4817193326Sed    // 'size' for bitfield ivars is ignored by the runtime so it does
4818193326Sed    // not matter.  If it matters, there is enough info to get the
4819193326Sed    // bitfield right!
4820193326Sed    Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4821193326Sed    Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
4822193326Sed  }
4823193326Sed  // Return null for empty list.
4824193326Sed  if (Ivars.empty())
4825193326Sed    return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
4826193326Sed  std::vector<llvm::Constant*> Values(3);
4827193326Sed  unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
4828193326Sed  Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4829193326Sed  Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
4830193326Sed  llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
4831193326Sed                                             Ivars.size());
4832193326Sed  Values[2] = llvm::ConstantArray::get(AT, Ivars);
4833198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
4834193326Sed  const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
4835193326Sed  llvm::GlobalVariable *GV =
4836198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
4837193326Sed                             llvm::GlobalValue::InternalLinkage,
4838193326Sed                             Init,
4839198398Srdivacky                             Prefix + OID->getName());
4840193326Sed  GV->setAlignment(
4841193326Sed    CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
4842193326Sed  GV->setSection("__DATA, __objc_const");
4843198092Srdivacky
4844198092Srdivacky  CGM.AddUsedGlobal(GV);
4845198092Srdivacky  return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
4846193326Sed}
4847193326Sed
4848193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
4849198092Srdivacky  const ObjCProtocolDecl *PD) {
4850193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
4851198092Srdivacky
4852193326Sed  if (!Entry) {
4853193326Sed    // We use the initializer as a marker of whether this is a forward
4854193326Sed    // reference or not. At module finalization we add the empty
4855193326Sed    // contents for protocols which were referenced but never defined.
4856198092Srdivacky    Entry =
4857198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
4858198092Srdivacky                               llvm::GlobalValue::ExternalLinkage,
4859198092Srdivacky                               0,
4860198398Srdivacky                               "\01l_OBJC_PROTOCOL_$_" + PD->getName());
4861193326Sed    Entry->setSection("__DATA,__datacoal_nt,coalesced");
4862193326Sed  }
4863198092Srdivacky
4864193326Sed  return Entry;
4865193326Sed}
4866193326Sed
4867193326Sed/// GetOrEmitProtocol - Generate the protocol meta-data:
4868193326Sed/// @code
4869193326Sed/// struct _protocol_t {
4870193326Sed///   id isa;  // NULL
4871193326Sed///   const char * const protocol_name;
4872193326Sed///   const struct _protocol_list_t * protocol_list; // super protocols
4873193326Sed///   const struct method_list_t * const instance_methods;
4874193326Sed///   const struct method_list_t * const class_methods;
4875193326Sed///   const struct method_list_t *optionalInstanceMethods;
4876193326Sed///   const struct method_list_t *optionalClassMethods;
4877193326Sed///   const struct _prop_list_t * properties;
4878193326Sed///   const uint32_t size;  // sizeof(struct _protocol_t)
4879193326Sed///   const uint32_t flags;  // = 0
4880193326Sed/// }
4881193326Sed/// @endcode
4882193326Sed///
4883193326Sed
4884193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
4885198092Srdivacky  const ObjCProtocolDecl *PD) {
4886193326Sed  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
4887198092Srdivacky
4888193326Sed  // Early exit if a defining object has already been generated.
4889193326Sed  if (Entry && Entry->hasInitializer())
4890193326Sed    return Entry;
4891193326Sed
4892193326Sed  // Construct method lists.
4893193326Sed  std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
4894193326Sed  std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
4895198092Srdivacky  for (ObjCProtocolDecl::instmeth_iterator
4896195341Sed         i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
4897193326Sed    ObjCMethodDecl *MD = *i;
4898193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
4899193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
4900193326Sed      OptInstanceMethods.push_back(C);
4901193326Sed    } else {
4902193326Sed      InstanceMethods.push_back(C);
4903198092Srdivacky    }
4904193326Sed  }
4905198092Srdivacky
4906198092Srdivacky  for (ObjCProtocolDecl::classmeth_iterator
4907195341Sed         i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
4908193326Sed    ObjCMethodDecl *MD = *i;
4909193326Sed    llvm::Constant *C = GetMethodDescriptionConstant(MD);
4910193326Sed    if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
4911193326Sed      OptClassMethods.push_back(C);
4912193326Sed    } else {
4913193326Sed      ClassMethods.push_back(C);
4914198092Srdivacky    }
4915193326Sed  }
4916198092Srdivacky
4917193326Sed  std::vector<llvm::Constant*> Values(10);
4918193326Sed  // isa is NULL
4919193326Sed  Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
4920193326Sed  Values[1] = GetClassName(PD->getIdentifier());
4921198398Srdivacky  Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
4922198398Srdivacky                               PD->protocol_begin(),
4923198398Srdivacky                               PD->protocol_end());
4924198092Srdivacky
4925193326Sed  Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
4926198398Srdivacky                             + PD->getName(),
4927193326Sed                             "__DATA, __objc_const",
4928193326Sed                             InstanceMethods);
4929198092Srdivacky  Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
4930198398Srdivacky                             + PD->getName(),
4931193326Sed                             "__DATA, __objc_const",
4932193326Sed                             ClassMethods);
4933193326Sed  Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
4934198398Srdivacky                             + PD->getName(),
4935193326Sed                             "__DATA, __objc_const",
4936193326Sed                             OptInstanceMethods);
4937198092Srdivacky  Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
4938198398Srdivacky                             + PD->getName(),
4939193326Sed                             "__DATA, __objc_const",
4940193326Sed                             OptClassMethods);
4941198398Srdivacky  Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
4942193326Sed                               0, PD, ObjCTypes);
4943198092Srdivacky  uint32_t Size =
4944193326Sed    CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
4945193326Sed  Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4946193326Sed  Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
4947193326Sed  llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
4948193326Sed                                                   Values);
4949198092Srdivacky
4950193326Sed  if (Entry) {
4951193326Sed    // Already created, fix the linkage and update the initializer.
4952193326Sed    Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
4953193326Sed    Entry->setInitializer(Init);
4954193326Sed  } else {
4955198092Srdivacky    Entry =
4956198398Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
4957198398Srdivacky                               false, llvm::GlobalValue::WeakAnyLinkage, Init,
4958198398Srdivacky                               "\01l_OBJC_PROTOCOL_$_" + PD->getName());
4959193326Sed    Entry->setAlignment(
4960193326Sed      CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABITy));
4961193326Sed    Entry->setSection("__DATA,__datacoal_nt,coalesced");
4962193326Sed  }
4963193326Sed  Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
4964198092Srdivacky  CGM.AddUsedGlobal(Entry);
4965198092Srdivacky
4966193326Sed  // Use this protocol meta-data to build protocol list table in section
4967193326Sed  // __DATA, __objc_protolist
4968198398Srdivacky  llvm::GlobalVariable *PTGV =
4969198398Srdivacky    new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
4970198398Srdivacky                             false, llvm::GlobalValue::WeakAnyLinkage, Entry,
4971198398Srdivacky                             "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
4972193326Sed  PTGV->setAlignment(
4973193326Sed    CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
4974193326Sed  PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
4975193326Sed  PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4976198092Srdivacky  CGM.AddUsedGlobal(PTGV);
4977193326Sed  return Entry;
4978193326Sed}
4979193326Sed
4980193326Sed/// EmitProtocolList - Generate protocol list meta-data:
4981193326Sed/// @code
4982193326Sed/// struct _protocol_list_t {
4983193326Sed///   long protocol_count;   // Note, this is 32/64 bit
4984193326Sed///   struct _protocol_t[protocol_count];
4985193326Sed/// }
4986193326Sed/// @endcode
4987193326Sed///
4988193326Sedllvm::Constant *
4989198398SrdivackyCGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
4990198398Srdivacky                                      ObjCProtocolDecl::protocol_iterator begin,
4991198398Srdivacky                                      ObjCProtocolDecl::protocol_iterator end) {
4992193326Sed  std::vector<llvm::Constant*> ProtocolRefs;
4993198092Srdivacky
4994193326Sed  // Just return null for empty protocol lists
4995198092Srdivacky  if (begin == end)
4996193326Sed    return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
4997198092Srdivacky
4998193326Sed  // FIXME: We shouldn't need to do this lookup here, should we?
4999198398Srdivacky  llvm::SmallString<256> TmpName;
5000198398Srdivacky  Name.toVector(TmpName);
5001198398Srdivacky  llvm::GlobalVariable *GV =
5002198398Srdivacky    CGM.getModule().getGlobalVariable(TmpName.str(), true);
5003193326Sed  if (GV)
5004198398Srdivacky    return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
5005198092Srdivacky
5006193326Sed  for (; begin != end; ++begin)
5007193326Sed    ProtocolRefs.push_back(GetProtocolRef(*begin));  // Implemented???
5008193326Sed
5009193326Sed  // This list is null terminated.
5010193326Sed  ProtocolRefs.push_back(llvm::Constant::getNullValue(
5011198092Srdivacky                           ObjCTypes.ProtocolnfABIPtrTy));
5012198092Srdivacky
5013193326Sed  std::vector<llvm::Constant*> Values(2);
5014198092Srdivacky  Values[0] =
5015198092Srdivacky    llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
5016198092Srdivacky  Values[1] =
5017198092Srdivacky    llvm::ConstantArray::get(
5018198092Srdivacky      llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
5019198092Srdivacky                           ProtocolRefs.size()),
5020198092Srdivacky      ProtocolRefs);
5021198092Srdivacky
5022198092Srdivacky  llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
5023198092Srdivacky  GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
5024193326Sed                                llvm::GlobalValue::InternalLinkage,
5025193326Sed                                Init,
5026198092Srdivacky                                Name);
5027193326Sed  GV->setSection("__DATA, __objc_const");
5028193326Sed  GV->setAlignment(
5029193326Sed    CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
5030198092Srdivacky  CGM.AddUsedGlobal(GV);
5031198092Srdivacky  return llvm::ConstantExpr::getBitCast(GV,
5032193326Sed                                        ObjCTypes.ProtocolListnfABIPtrTy);
5033193326Sed}
5034193326Sed
5035193326Sed/// GetMethodDescriptionConstant - This routine build following meta-data:
5036193326Sed/// struct _objc_method {
5037193326Sed///   SEL _cmd;
5038193326Sed///   char *method_type;
5039193326Sed///   char *_imp;
5040193326Sed/// }
5041193326Sed
5042193326Sedllvm::Constant *
5043193326SedCGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
5044193326Sed  std::vector<llvm::Constant*> Desc(3);
5045198092Srdivacky  Desc[0] =
5046198092Srdivacky    llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5047198092Srdivacky                                   ObjCTypes.SelectorPtrTy);
5048193326Sed  Desc[1] = GetMethodVarType(MD);
5049193326Sed  // Protocol methods have no implementation. So, this entry is always NULL.
5050193326Sed  Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5051193326Sed  return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
5052193326Sed}
5053193326Sed
5054193326Sed/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
5055193326Sed/// This code gen. amounts to generating code for:
5056193326Sed/// @code
5057193326Sed/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
5058193326Sed/// @encode
5059198092Srdivacky///
5060193326SedLValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
5061198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5062198092Srdivacky  QualType ObjectTy,
5063198092Srdivacky  llvm::Value *BaseValue,
5064198092Srdivacky  const ObjCIvarDecl *Ivar,
5065198092Srdivacky  unsigned CVRQualifiers) {
5066198092Srdivacky  const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl();
5067193326Sed  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5068193326Sed                                  EmitIvarOffset(CGF, ID, Ivar));
5069193326Sed}
5070193326Sed
5071193326Sedllvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
5072198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5073198092Srdivacky  const ObjCInterfaceDecl *Interface,
5074198092Srdivacky  const ObjCIvarDecl *Ivar) {
5075199990Srdivacky  return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
5076193326Sed}
5077193326Sed
5078193326SedCodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
5079198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5080198092Srdivacky  QualType ResultType,
5081198092Srdivacky  Selector Sel,
5082198092Srdivacky  llvm::Value *Receiver,
5083198092Srdivacky  QualType Arg0Ty,
5084198092Srdivacky  bool IsSuper,
5085198092Srdivacky  const CallArgList &CallArgs) {
5086193326Sed  // FIXME. Even though IsSuper is passes. This function doese not handle calls
5087193326Sed  // to 'super' receivers.
5088193326Sed  CodeGenTypes &Types = CGM.getTypes();
5089193326Sed  llvm::Value *Arg0 = Receiver;
5090193326Sed  if (!IsSuper)
5091193326Sed    Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
5092198092Srdivacky
5093193326Sed  // Find the message function name.
5094193326Sed  // FIXME. This is too much work to get the ABI-specific result type needed to
5095193326Sed  // find the message name.
5096198092Srdivacky  const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType,
5097203955Srdivacky                                                       llvm::SmallVector<QualType, 16>(),
5098203955Srdivacky                                                       CC_Default, false);
5099193326Sed  llvm::Constant *Fn = 0;
5100193326Sed  std::string Name("\01l_");
5101193326Sed  if (CGM.ReturnTypeUsesSret(FnInfo)) {
5102193326Sed#if 0
5103193326Sed    // unlike what is documented. gcc never generates this API!!
5104193326Sed    if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
5105193326Sed      Fn = ObjCTypes.getMessageSendIdStretFixupFn();
5106193326Sed      // FIXME. Is there a better way of getting these names.
5107193326Sed      // They are available in RuntimeFunctions vector pair.
5108193326Sed      Name += "objc_msgSendId_stret_fixup";
5109198092Srdivacky    } else
5110193326Sed#endif
5111198092Srdivacky      if (IsSuper) {
5112193326Sed        Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
5113193326Sed        Name += "objc_msgSendSuper2_stret_fixup";
5114198092Srdivacky      } else {
5115198092Srdivacky        Fn = ObjCTypes.getMessageSendStretFixupFn();
5116198092Srdivacky        Name += "objc_msgSend_stret_fixup";
5117198092Srdivacky      }
5118198092Srdivacky  } else if (!IsSuper && ResultType->isFloatingType()) {
5119195099Sed    if (ResultType->isSpecificBuiltinType(BuiltinType::LongDouble)) {
5120195099Sed      Fn = ObjCTypes.getMessageSendFpretFixupFn();
5121195099Sed      Name += "objc_msgSend_fpret_fixup";
5122198092Srdivacky    } else {
5123195099Sed      Fn = ObjCTypes.getMessageSendFixupFn();
5124195099Sed      Name += "objc_msgSend_fixup";
5125193326Sed    }
5126198092Srdivacky  } else {
5127193326Sed#if 0
5128193326Sed// unlike what is documented. gcc never generates this API!!
5129193326Sed    if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
5130193326Sed      Fn = ObjCTypes.getMessageSendIdFixupFn();
5131193326Sed      Name += "objc_msgSendId_fixup";
5132198092Srdivacky    } else
5133193326Sed#endif
5134198092Srdivacky      if (IsSuper) {
5135193326Sed        Fn = ObjCTypes.getMessageSendSuper2FixupFn();
5136193326Sed        Name += "objc_msgSendSuper2_fixup";
5137198092Srdivacky      } else {
5138198092Srdivacky        Fn = ObjCTypes.getMessageSendFixupFn();
5139198092Srdivacky        Name += "objc_msgSend_fixup";
5140198092Srdivacky      }
5141193326Sed  }
5142193326Sed  assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend");
5143193326Sed  Name += '_';
5144193326Sed  std::string SelName(Sel.getAsString());
5145193326Sed  // Replace all ':' in selector name with '_'  ouch!
5146198092Srdivacky  for (unsigned i = 0; i < SelName.size(); i++)
5147193326Sed    if (SelName[i] == ':')
5148193326Sed      SelName[i] = '_';
5149193326Sed  Name += SelName;
5150193326Sed  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5151193326Sed  if (!GV) {
5152193326Sed    // Build message ref table entry.
5153193326Sed    std::vector<llvm::Constant*> Values(2);
5154193326Sed    Values[0] = Fn;
5155193326Sed    Values[1] = GetMethodVarName(Sel);
5156198092Srdivacky    llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
5157198092Srdivacky    GV =  new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
5158193326Sed                                   llvm::GlobalValue::WeakAnyLinkage,
5159193326Sed                                   Init,
5160198092Srdivacky                                   Name);
5161193326Sed    GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
5162193326Sed    GV->setAlignment(16);
5163193326Sed    GV->setSection("__DATA, __objc_msgrefs, coalesced");
5164193326Sed  }
5165193326Sed  llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy);
5166198092Srdivacky
5167193326Sed  CallArgList ActualArgs;
5168193326Sed  ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
5169198092Srdivacky  ActualArgs.push_back(std::make_pair(RValue::get(Arg1),
5170193326Sed                                      ObjCTypes.MessageRefCPtrTy));
5171193326Sed  ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
5172203955Srdivacky  const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs,
5173203955Srdivacky                                                        CC_Default, false);
5174193326Sed  llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0);
5175193326Sed  Callee = CGF.Builder.CreateLoad(Callee);
5176193326Sed  const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true);
5177193326Sed  Callee = CGF.Builder.CreateBitCast(Callee,
5178193326Sed                                     llvm::PointerType::getUnqual(FTy));
5179201361Srdivacky  return CGF.EmitCall(FnInfo1, Callee, ReturnValueSlot(), ActualArgs);
5180193326Sed}
5181193326Sed
5182193326Sed/// Generate code for a message send expression in the nonfragile abi.
5183198092SrdivackyCodeGen::RValue
5184198092SrdivackyCGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
5185198092Srdivacky                                            QualType ResultType,
5186198092Srdivacky                                            Selector Sel,
5187198092Srdivacky                                            llvm::Value *Receiver,
5188198092Srdivacky                                            bool IsClassMessage,
5189198092Srdivacky                                            const CallArgList &CallArgs,
5190198092Srdivacky                                            const ObjCMethodDecl *Method) {
5191193326Sed  return LegacyDispatchedSelector(Sel)
5192198092Srdivacky    ? EmitLegacyMessageSend(CGF, ResultType, EmitSelector(CGF.Builder, Sel),
5193198092Srdivacky                            Receiver, CGF.getContext().getObjCIdType(),
5194198092Srdivacky                            false, CallArgs, Method, ObjCTypes)
5195198092Srdivacky    : EmitMessageSend(CGF, ResultType, Sel,
5196198092Srdivacky                      Receiver, CGF.getContext().getObjCIdType(),
5197198092Srdivacky                      false, CallArgs);
5198193326Sed}
5199193326Sed
5200193326Sedllvm::GlobalVariable *
5201193326SedCGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
5202193326Sed  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5203193326Sed
5204193326Sed  if (!GV) {
5205198092Srdivacky    GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
5206198092Srdivacky                                  false, llvm::GlobalValue::ExternalLinkage,
5207198092Srdivacky                                  0, Name);
5208193326Sed  }
5209193326Sed
5210193326Sed  return GV;
5211193326Sed}
5212193326Sed
5213198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5214198092Srdivacky                                                  const ObjCInterfaceDecl *ID) {
5215193326Sed  llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
5216198092Srdivacky
5217193326Sed  if (!Entry) {
5218193326Sed    std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5219193326Sed    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5220198092Srdivacky    Entry =
5221198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
5222198092Srdivacky                               false, llvm::GlobalValue::InternalLinkage,
5223198092Srdivacky                               ClassGV,
5224198092Srdivacky                               "\01L_OBJC_CLASSLIST_REFERENCES_$_");
5225193326Sed    Entry->setAlignment(
5226198092Srdivacky      CGM.getTargetData().getPrefTypeAlignment(
5227198092Srdivacky        ObjCTypes.ClassnfABIPtrTy));
5228193326Sed    Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
5229198092Srdivacky    CGM.AddUsedGlobal(Entry);
5230193326Sed  }
5231198092Srdivacky
5232199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
5233193326Sed}
5234193326Sed
5235193326Sedllvm::Value *
5236198092SrdivackyCGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
5237193326Sed                                          const ObjCInterfaceDecl *ID) {
5238193326Sed  llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
5239198092Srdivacky
5240193326Sed  if (!Entry) {
5241193326Sed    std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5242193326Sed    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5243198092Srdivacky    Entry =
5244198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
5245198092Srdivacky                               false, llvm::GlobalValue::InternalLinkage,
5246198092Srdivacky                               ClassGV,
5247198092Srdivacky                               "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
5248193326Sed    Entry->setAlignment(
5249198092Srdivacky      CGM.getTargetData().getPrefTypeAlignment(
5250198092Srdivacky        ObjCTypes.ClassnfABIPtrTy));
5251193326Sed    Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
5252198092Srdivacky    CGM.AddUsedGlobal(Entry);
5253193326Sed  }
5254198092Srdivacky
5255199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
5256193326Sed}
5257193326Sed
5258193326Sed/// EmitMetaClassRef - Return a Value * of the address of _class_t
5259193326Sed/// meta-data
5260193326Sed///
5261198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5262198092Srdivacky                                                      const ObjCInterfaceDecl *ID) {
5263193326Sed  llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5264193326Sed  if (Entry)
5265199990Srdivacky    return Builder.CreateLoad(Entry, "tmp");
5266198092Srdivacky
5267193326Sed  std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
5268193326Sed  llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
5269198092Srdivacky  Entry =
5270198092Srdivacky    new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
5271193326Sed                             llvm::GlobalValue::InternalLinkage,
5272198092Srdivacky                             MetaClassGV,
5273198092Srdivacky                             "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
5274193326Sed  Entry->setAlignment(
5275198092Srdivacky    CGM.getTargetData().getPrefTypeAlignment(
5276198092Srdivacky      ObjCTypes.ClassnfABIPtrTy));
5277198092Srdivacky
5278193326Sed  Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
5279198092Srdivacky  CGM.AddUsedGlobal(Entry);
5280198092Srdivacky
5281199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
5282193326Sed}
5283193326Sed
5284193326Sed/// GetClass - Return a reference to the class for the given interface
5285193326Sed/// decl.
5286193326Sedllvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
5287193326Sed                                              const ObjCInterfaceDecl *ID) {
5288199482Srdivacky  if (ID->hasAttr<WeakImportAttr>()) {
5289199482Srdivacky    std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5290199482Srdivacky    llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5291199482Srdivacky    ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5292199482Srdivacky  }
5293199482Srdivacky
5294193326Sed  return EmitClassRef(Builder, ID);
5295193326Sed}
5296193326Sed
5297193326Sed/// Generates a message send where the super is the receiver.  This is
5298193326Sed/// a message send to self with special delivery semantics indicating
5299193326Sed/// which class's method should be called.
5300193326SedCodeGen::RValue
5301193326SedCGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
5302198092Srdivacky                                                 QualType ResultType,
5303198092Srdivacky                                                 Selector Sel,
5304198092Srdivacky                                                 const ObjCInterfaceDecl *Class,
5305198092Srdivacky                                                 bool isCategoryImpl,
5306198092Srdivacky                                                 llvm::Value *Receiver,
5307198092Srdivacky                                                 bool IsClassMessage,
5308198092Srdivacky                                                 const CodeGen::CallArgList &CallArgs,
5309198092Srdivacky                                                 const ObjCMethodDecl *Method) {
5310193326Sed  // ...
5311193326Sed  // Create and init a super structure; this is a (receiver, class)
5312193326Sed  // pair we will pass to objc_msgSendSuper.
5313193326Sed  llvm::Value *ObjCSuper =
5314193326Sed    CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
5315198092Srdivacky
5316193326Sed  llvm::Value *ReceiverAsObject =
5317193326Sed    CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
5318193326Sed  CGF.Builder.CreateStore(ReceiverAsObject,
5319193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 0));
5320198092Srdivacky
5321193326Sed  // If this is a class message the metaclass is passed as the target.
5322193326Sed  llvm::Value *Target;
5323193326Sed  if (IsClassMessage) {
5324193326Sed    if (isCategoryImpl) {
5325193326Sed      // Message sent to "super' in a class method defined in
5326193326Sed      // a category implementation.
5327193326Sed      Target = EmitClassRef(CGF.Builder, Class);
5328193326Sed      Target = CGF.Builder.CreateStructGEP(Target, 0);
5329193326Sed      Target = CGF.Builder.CreateLoad(Target);
5330198092Srdivacky    } else
5331193326Sed      Target = EmitMetaClassRef(CGF.Builder, Class);
5332198092Srdivacky  } else
5333193326Sed    Target = EmitSuperClassRef(CGF.Builder, Class);
5334198092Srdivacky
5335193326Sed  // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5336193326Sed  // ObjCTypes types.
5337193326Sed  const llvm::Type *ClassTy =
5338193326Sed    CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
5339193326Sed  Target = CGF.Builder.CreateBitCast(Target, ClassTy);
5340193326Sed  CGF.Builder.CreateStore(Target,
5341193326Sed                          CGF.Builder.CreateStructGEP(ObjCSuper, 1));
5342198092Srdivacky
5343193326Sed  return (LegacyDispatchedSelector(Sel))
5344198092Srdivacky    ? EmitLegacyMessageSend(CGF, ResultType,EmitSelector(CGF.Builder, Sel),
5345198092Srdivacky                            ObjCSuper, ObjCTypes.SuperPtrCTy,
5346198092Srdivacky                            true, CallArgs, Method, ObjCTypes)
5347198092Srdivacky    : EmitMessageSend(CGF, ResultType, Sel,
5348198092Srdivacky                      ObjCSuper, ObjCTypes.SuperPtrCTy,
5349198092Srdivacky                      true, CallArgs);
5350193326Sed}
5351193326Sed
5352198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
5353193326Sed                                                  Selector Sel) {
5354193326Sed  llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5355198092Srdivacky
5356193326Sed  if (!Entry) {
5357198092Srdivacky    llvm::Constant *Casted =
5358198092Srdivacky      llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
5359198092Srdivacky                                     ObjCTypes.SelectorPtrTy);
5360198092Srdivacky    Entry =
5361198092Srdivacky      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
5362198092Srdivacky                               llvm::GlobalValue::InternalLinkage,
5363198092Srdivacky                               Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
5364193326Sed    Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
5365198092Srdivacky    CGM.AddUsedGlobal(Entry);
5366193326Sed  }
5367198092Srdivacky
5368199990Srdivacky  return Builder.CreateLoad(Entry, "tmp");
5369193326Sed}
5370193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
5371198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
5372193326Sed///
5373193326Sedvoid CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
5374198092Srdivacky                                                llvm::Value *src,
5375198092Srdivacky                                                llvm::Value *dst,
5376198092Srdivacky                                                llvm::Value *ivarOffset) {
5377193326Sed  const llvm::Type * SrcTy = src->getType();
5378193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5379193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5380193326Sed    assert(Size <= 8 && "does not support size > 8");
5381193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5382193326Sed           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5383193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5384193326Sed  }
5385193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5386193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5387198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5388198092Srdivacky                          src, dst, ivarOffset);
5389193326Sed  return;
5390193326Sed}
5391193326Sed
5392193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5393193326Sed/// objc_assign_strongCast (id src, id *dst)
5394193326Sed///
5395193326Sedvoid CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
5396198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5397198092Srdivacky  llvm::Value *src, llvm::Value *dst) {
5398193326Sed  const llvm::Type * SrcTy = src->getType();
5399193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5400193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5401193326Sed    assert(Size <= 8 && "does not support size > 8");
5402193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5403198092Srdivacky           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5404193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5405193326Sed  }
5406193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5407193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5408193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
5409193326Sed                          src, dst, "weakassign");
5410193326Sed  return;
5411193326Sed}
5412193326Sed
5413198092Srdivackyvoid CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
5414198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5415198092Srdivacky  llvm::Value *DestPtr,
5416198092Srdivacky  llvm::Value *SrcPtr,
5417198092Srdivacky  QualType Ty) {
5418198092Srdivacky  // Get size info for this aggregate.
5419198092Srdivacky  std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty);
5420198092Srdivacky  unsigned long size = TypeInfo.first/8;
5421198092Srdivacky  SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5422198092Srdivacky  DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
5423198092Srdivacky  llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size);
5424198092Srdivacky  CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
5425198092Srdivacky                          DestPtr, SrcPtr, N);
5426198092Srdivacky  return;
5427198092Srdivacky}
5428198092Srdivacky
5429193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak
5430193326Sed/// object: objc_read_weak (id *src)
5431193326Sed///
5432193326Sedllvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
5433198092Srdivacky  CodeGen::CodeGenFunction &CGF,
5434198092Srdivacky  llvm::Value *AddrWeakObj) {
5435193326Sed  const llvm::Type* DestTy =
5436198092Srdivacky    cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5437198092Srdivacky  AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
5438193326Sed  llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
5439193326Sed                                                  AddrWeakObj, "weakread");
5440193326Sed  read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
5441193326Sed  return read_weak;
5442193326Sed}
5443193326Sed
5444193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
5445193326Sed/// objc_assign_weak (id src, id *dst)
5446193326Sed///
5447193326Sedvoid CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
5448198092Srdivacky                                                llvm::Value *src, llvm::Value *dst) {
5449193326Sed  const llvm::Type * SrcTy = src->getType();
5450193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5451193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5452193326Sed    assert(Size <= 8 && "does not support size > 8");
5453193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5454193326Sed           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5455193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5456193326Sed  }
5457193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5458193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5459193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
5460193326Sed                          src, dst, "weakassign");
5461193326Sed  return;
5462193326Sed}
5463193326Sed
5464193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
5465193326Sed/// objc_assign_global (id src, id *dst)
5466193326Sed///
5467193326Sedvoid CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
5468198092Srdivacky                                                  llvm::Value *src, llvm::Value *dst) {
5469193326Sed  const llvm::Type * SrcTy = src->getType();
5470193326Sed  if (!isa<llvm::PointerType>(SrcTy)) {
5471193326Sed    unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
5472193326Sed    assert(Size <= 8 && "does not support size > 8");
5473193326Sed    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5474193326Sed           : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
5475193326Sed    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5476193326Sed  }
5477193326Sed  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5478193326Sed  dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5479193326Sed  CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
5480193326Sed                          src, dst, "globalassign");
5481193326Sed  return;
5482193326Sed}
5483193326Sed
5484198092Srdivackyvoid
5485193326SedCGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
5486193326Sed                                                  const Stmt &S) {
5487193326Sed  bool isTry = isa<ObjCAtTryStmt>(S);
5488193326Sed  llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
5489193326Sed  llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest();
5490193326Sed  llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
5491193326Sed  llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
5492193326Sed  llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
5493193326Sed  llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
5494193326Sed
5495193326Sed  // For @synchronized, call objc_sync_enter(sync.expr). The
5496193326Sed  // evaluation of the expression must occur before we enter the
5497193326Sed  // @synchronized. We can safely avoid a temp here because jumps into
5498193326Sed  // @synchronized are illegal & this will dominate uses.
5499193326Sed  llvm::Value *SyncArg = 0;
5500193326Sed  if (!isTry) {
5501198092Srdivacky    SyncArg =
5502193326Sed      CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
5503193326Sed    SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
5504193326Sed    CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg);
5505193326Sed  }
5506193326Sed
5507193326Sed  // Push an EH context entry, used for handling rethrows and jumps
5508193326Sed  // through finally.
5509193326Sed  CGF.PushCleanupBlock(FinallyBlock);
5510193326Sed
5511193326Sed  CGF.setInvokeDest(TryHandler);
5512193326Sed
5513193326Sed  CGF.EmitBlock(TryBlock);
5514198092Srdivacky  CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
5515198092Srdivacky               : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
5516193326Sed  CGF.EmitBranchThroughCleanup(FinallyEnd);
5517198092Srdivacky
5518193326Sed  // Emit the exception handler.
5519193326Sed
5520193326Sed  CGF.EmitBlock(TryHandler);
5521193326Sed
5522198092Srdivacky  llvm::Value *llvm_eh_exception =
5523193326Sed    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
5524198092Srdivacky  llvm::Value *llvm_eh_selector =
5525198092Srdivacky    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
5526198092Srdivacky  llvm::Value *llvm_eh_typeid_for =
5527198092Srdivacky    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for);
5528193326Sed  llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
5529193326Sed  llvm::Value *RethrowPtr = CGF.CreateTempAlloca(Exc->getType(), "_rethrow");
5530193326Sed
5531193326Sed  llvm::SmallVector<llvm::Value*, 8> SelectorArgs;
5532193326Sed  SelectorArgs.push_back(Exc);
5533193326Sed  SelectorArgs.push_back(ObjCTypes.getEHPersonalityPtr());
5534193326Sed
5535193326Sed  // Construct the lists of (type, catch body) to handle.
5536193326Sed  llvm::SmallVector<std::pair<const ParmVarDecl*, const Stmt*>, 8> Handlers;
5537193326Sed  bool HasCatchAll = false;
5538193326Sed  if (isTry) {
5539193326Sed    if (const ObjCAtCatchStmt* CatchStmt =
5540193326Sed        cast<ObjCAtTryStmt>(S).getCatchStmts())  {
5541193326Sed      for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
5542193326Sed        const ParmVarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
5543193326Sed        Handlers.push_back(std::make_pair(CatchDecl, CatchStmt->getCatchBody()));
5544193326Sed
5545193326Sed        // catch(...) always matches.
5546193326Sed        if (!CatchDecl) {
5547193326Sed          // Use i8* null here to signal this is a catch all, not a cleanup.
5548193326Sed          llvm::Value *Null = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5549193326Sed          SelectorArgs.push_back(Null);
5550193326Sed          HasCatchAll = true;
5551193326Sed          break;
5552193326Sed        }
5553193326Sed
5554198092Srdivacky        if (CatchDecl->getType()->isObjCIdType() ||
5555193326Sed            CatchDecl->getType()->isObjCQualifiedIdType()) {
5556198092Srdivacky          llvm::Value *IDEHType =
5557193326Sed            CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
5558193326Sed          if (!IDEHType)
5559198092Srdivacky            IDEHType =
5560198092Srdivacky              new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
5561198092Srdivacky                                       false,
5562193326Sed                                       llvm::GlobalValue::ExternalLinkage,
5563198092Srdivacky                                       0, "OBJC_EHTYPE_id");
5564193326Sed          SelectorArgs.push_back(IDEHType);
5565198092Srdivacky        } else {
5566198092Srdivacky          // All other types should be Objective-C interface pointer types.
5567198092Srdivacky          const ObjCObjectPointerType *PT =
5568198092Srdivacky            CatchDecl->getType()->getAs<ObjCObjectPointerType>();
5569198092Srdivacky          assert(PT && "Invalid @catch type.");
5570198092Srdivacky          const ObjCInterfaceType *IT = PT->getInterfaceType();
5571198092Srdivacky          assert(IT && "Invalid @catch type.");
5572198092Srdivacky          llvm::Value *EHType = GetInterfaceEHType(IT->getDecl(), false);
5573198092Srdivacky          SelectorArgs.push_back(EHType);
5574198092Srdivacky        }
5575193326Sed      }
5576193326Sed    }
5577193326Sed  }
5578193326Sed
5579193326Sed  // We use a cleanup unless there was already a catch all.
5580193326Sed  if (!HasCatchAll) {
5581198092Srdivacky    // Even though this is a cleanup, treat it as a catch all to avoid the C++
5582198092Srdivacky    // personality behavior of terminating the process if only cleanups are
5583198092Srdivacky    // found in the exception handling stack.
5584198092Srdivacky    SelectorArgs.push_back(llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy));
5585193326Sed    Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0));
5586193326Sed  }
5587198092Srdivacky
5588198092Srdivacky  llvm::Value *Selector =
5589198092Srdivacky    CGF.Builder.CreateCall(llvm_eh_selector,
5590193326Sed                           SelectorArgs.begin(), SelectorArgs.end(),
5591193326Sed                           "selector");
5592193326Sed  for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
5593193326Sed    const ParmVarDecl *CatchParam = Handlers[i].first;
5594193326Sed    const Stmt *CatchBody = Handlers[i].second;
5595193326Sed
5596193326Sed    llvm::BasicBlock *Next = 0;
5597193326Sed
5598193326Sed    // The last handler always matches.
5599193326Sed    if (i + 1 != e) {
5600193326Sed      assert(CatchParam && "Only last handler can be a catch all.");
5601193326Sed
5602193326Sed      llvm::BasicBlock *Match = CGF.createBasicBlock("match");
5603193326Sed      Next = CGF.createBasicBlock("catch.next");
5604198092Srdivacky      llvm::Value *Id =
5605198092Srdivacky        CGF.Builder.CreateCall(llvm_eh_typeid_for,
5606193326Sed                               CGF.Builder.CreateBitCast(SelectorArgs[i+2],
5607193326Sed                                                         ObjCTypes.Int8PtrTy));
5608193326Sed      CGF.Builder.CreateCondBr(CGF.Builder.CreateICmpEQ(Selector, Id),
5609193326Sed                               Match, Next);
5610193326Sed
5611193326Sed      CGF.EmitBlock(Match);
5612193326Sed    }
5613198092Srdivacky
5614193326Sed    if (CatchBody) {
5615193326Sed      llvm::BasicBlock *MatchEnd = CGF.createBasicBlock("match.end");
5616193326Sed      llvm::BasicBlock *MatchHandler = CGF.createBasicBlock("match.handler");
5617193326Sed
5618193326Sed      // Cleanups must call objc_end_catch.
5619198092Srdivacky      //
5620193326Sed      // FIXME: It seems incorrect for objc_begin_catch to be inside this
5621193326Sed      // context, but this matches gcc.
5622193326Sed      CGF.PushCleanupBlock(MatchEnd);
5623193326Sed      CGF.setInvokeDest(MatchHandler);
5624198092Srdivacky
5625198092Srdivacky      llvm::Value *ExcObject =
5626193326Sed        CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), Exc);
5627193326Sed
5628193326Sed      // Bind the catch parameter if it exists.
5629193326Sed      if (CatchParam) {
5630198092Srdivacky        ExcObject =
5631198092Srdivacky          CGF.Builder.CreateBitCast(ExcObject,
5632193326Sed                                    CGF.ConvertType(CatchParam->getType()));
5633193326Sed        // CatchParam is a ParmVarDecl because of the grammar
5634193326Sed        // construction used to handle this, but for codegen purposes
5635193326Sed        // we treat this as a local decl.
5636193326Sed        CGF.EmitLocalBlockVarDecl(*CatchParam);
5637193326Sed        CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(CatchParam));
5638193326Sed      }
5639193326Sed
5640193326Sed      CGF.ObjCEHValueStack.push_back(ExcObject);
5641193326Sed      CGF.EmitStmt(CatchBody);
5642193326Sed      CGF.ObjCEHValueStack.pop_back();
5643193326Sed
5644193326Sed      CGF.EmitBranchThroughCleanup(FinallyEnd);
5645193326Sed
5646193326Sed      CGF.EmitBlock(MatchHandler);
5647193326Sed
5648193326Sed      llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
5649193326Sed      // We are required to emit this call to satisfy LLVM, even
5650193326Sed      // though we don't use the result.
5651193326Sed      llvm::SmallVector<llvm::Value*, 8> Args;
5652193326Sed      Args.push_back(Exc);
5653193326Sed      Args.push_back(ObjCTypes.getEHPersonalityPtr());
5654198092Srdivacky      Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
5655193326Sed                                            0));
5656198092Srdivacky      CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
5657193326Sed      CGF.Builder.CreateStore(Exc, RethrowPtr);
5658193326Sed      CGF.EmitBranchThroughCleanup(FinallyRethrow);
5659193326Sed
5660193326Sed      CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
5661198092Srdivacky
5662193326Sed      CGF.EmitBlock(MatchEnd);
5663193326Sed
5664193326Sed      // Unfortunately, we also have to generate another EH frame here
5665193326Sed      // in case this throws.
5666198092Srdivacky      llvm::BasicBlock *MatchEndHandler =
5667193326Sed        CGF.createBasicBlock("match.end.handler");
5668193326Sed      llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
5669198092Srdivacky      CGF.Builder.CreateInvoke(ObjCTypes.getObjCEndCatchFn(),
5670193326Sed                               Cont, MatchEndHandler,
5671193326Sed                               Args.begin(), Args.begin());
5672193326Sed
5673193326Sed      CGF.EmitBlock(Cont);
5674193326Sed      if (Info.SwitchBlock)
5675193326Sed        CGF.EmitBlock(Info.SwitchBlock);
5676193326Sed      if (Info.EndBlock)
5677193326Sed        CGF.EmitBlock(Info.EndBlock);
5678193326Sed
5679193326Sed      CGF.EmitBlock(MatchEndHandler);
5680193326Sed      Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
5681193326Sed      // We are required to emit this call to satisfy LLVM, even
5682193326Sed      // though we don't use the result.
5683193326Sed      Args.clear();
5684193326Sed      Args.push_back(Exc);
5685193326Sed      Args.push_back(ObjCTypes.getEHPersonalityPtr());
5686198092Srdivacky      Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
5687193326Sed                                            0));
5688198092Srdivacky      CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
5689193326Sed      CGF.Builder.CreateStore(Exc, RethrowPtr);
5690193326Sed      CGF.EmitBranchThroughCleanup(FinallyRethrow);
5691193326Sed
5692193326Sed      if (Next)
5693193326Sed        CGF.EmitBlock(Next);
5694193326Sed    } else {
5695193326Sed      assert(!Next && "catchup should be last handler.");
5696193326Sed
5697193326Sed      CGF.Builder.CreateStore(Exc, RethrowPtr);
5698193326Sed      CGF.EmitBranchThroughCleanup(FinallyRethrow);
5699193326Sed    }
5700193326Sed  }
5701193326Sed
5702193326Sed  // Pop the cleanup entry, the @finally is outside this cleanup
5703193326Sed  // scope.
5704193326Sed  CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
5705193326Sed  CGF.setInvokeDest(PrevLandingPad);
5706193326Sed
5707193326Sed  CGF.EmitBlock(FinallyBlock);
5708193326Sed
5709193326Sed  if (isTry) {
5710198092Srdivacky    if (const ObjCAtFinallyStmt* FinallyStmt =
5711193326Sed        cast<ObjCAtTryStmt>(S).getFinallyStmt())
5712193326Sed      CGF.EmitStmt(FinallyStmt->getFinallyBody());
5713193326Sed  } else {
5714193326Sed    // Emit 'objc_sync_exit(expr)' as finally's sole statement for
5715193326Sed    // @synchronized.
5716193326Sed    CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg);
5717193326Sed  }
5718193326Sed
5719193326Sed  if (Info.SwitchBlock)
5720193326Sed    CGF.EmitBlock(Info.SwitchBlock);
5721193326Sed  if (Info.EndBlock)
5722193326Sed    CGF.EmitBlock(Info.EndBlock);
5723193326Sed
5724193326Sed  // Branch around the rethrow code.
5725193326Sed  CGF.EmitBranch(FinallyEnd);
5726193326Sed
5727193326Sed  CGF.EmitBlock(FinallyRethrow);
5728198092Srdivacky  CGF.Builder.CreateCall(ObjCTypes.getUnwindResumeOrRethrowFn(),
5729193326Sed                         CGF.Builder.CreateLoad(RethrowPtr));
5730193326Sed  CGF.Builder.CreateUnreachable();
5731198092Srdivacky
5732193326Sed  CGF.EmitBlock(FinallyEnd);
5733193326Sed}
5734193326Sed
5735193326Sed/// EmitThrowStmt - Generate code for a throw statement.
5736193326Sedvoid CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
5737193326Sed                                           const ObjCAtThrowStmt &S) {
5738198092Srdivacky  llvm::Value *Exception;
5739193326Sed  if (const Expr *ThrowExpr = S.getThrowExpr()) {
5740193326Sed    Exception = CGF.EmitScalarExpr(ThrowExpr);
5741193326Sed  } else {
5742198092Srdivacky    assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
5743193326Sed           "Unexpected rethrow outside @catch block.");
5744193326Sed    Exception = CGF.ObjCEHValueStack.back();
5745193326Sed  }
5746193326Sed
5747198092Srdivacky  llvm::Value *ExceptionAsObject =
5748193326Sed    CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
5749193326Sed  llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
5750193326Sed  if (InvokeDest) {
5751193326Sed    llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
5752193326Sed    CGF.Builder.CreateInvoke(ObjCTypes.getExceptionThrowFn(),
5753193326Sed                             Cont, InvokeDest,
5754193326Sed                             &ExceptionAsObject, &ExceptionAsObject + 1);
5755193326Sed    CGF.EmitBlock(Cont);
5756193326Sed  } else
5757198092Srdivacky    CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject);
5758193326Sed  CGF.Builder.CreateUnreachable();
5759193326Sed
5760193326Sed  // Clear the insertion point to indicate we are in unreachable code.
5761193326Sed  CGF.Builder.ClearInsertionPoint();
5762193326Sed}
5763193326Sed
5764193326Sedllvm::Value *
5765198092SrdivackyCGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
5766193326Sed                                           bool ForDefinition) {
5767193326Sed  llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
5768193326Sed
5769193326Sed  // If we don't need a definition, return the entry if found or check
5770193326Sed  // if we use an external reference.
5771193326Sed  if (!ForDefinition) {
5772193326Sed    if (Entry)
5773193326Sed      return Entry;
5774193326Sed
5775193326Sed    // If this type (or a super class) has the __objc_exception__
5776193326Sed    // attribute, emit an external reference.
5777194613Sed    if (hasObjCExceptionAttribute(CGM.getContext(), ID))
5778198092Srdivacky      return Entry =
5779198092Srdivacky        new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
5780193326Sed                                 llvm::GlobalValue::ExternalLinkage,
5781198092Srdivacky                                 0,
5782198398Srdivacky                                 ("OBJC_EHTYPE_$_" +
5783198092Srdivacky                                  ID->getIdentifier()->getName()));
5784193326Sed  }
5785198092Srdivacky
5786193326Sed  // Otherwise we need to either make a new entry or fill in the
5787193326Sed  // initializer.
5788193326Sed  assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
5789193326Sed  std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5790193326Sed  std::string VTableName = "objc_ehtype_vtable";
5791198092Srdivacky  llvm::GlobalVariable *VTableGV =
5792193326Sed    CGM.getModule().getGlobalVariable(VTableName);
5793193326Sed  if (!VTableGV)
5794198092Srdivacky    VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
5795198092Srdivacky                                        false,
5796193326Sed                                        llvm::GlobalValue::ExternalLinkage,
5797198092Srdivacky                                        0, VTableName);
5798193326Sed
5799198092Srdivacky  llvm::Value *VTableIdx = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
5800193326Sed
5801193326Sed  std::vector<llvm::Constant*> Values(3);
5802193326Sed  Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
5803193326Sed  Values[1] = GetClassName(ID->getIdentifier());
5804193326Sed  Values[2] = GetClassGlobal(ClassName);
5805198092Srdivacky  llvm::Constant *Init =
5806198092Srdivacky    llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
5807193326Sed
5808193326Sed  if (Entry) {
5809193326Sed    Entry->setInitializer(Init);
5810193326Sed  } else {
5811198092Srdivacky    Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
5812193326Sed                                     llvm::GlobalValue::WeakAnyLinkage,
5813198092Srdivacky                                     Init,
5814198398Srdivacky                                     ("OBJC_EHTYPE_$_" +
5815198092Srdivacky                                      ID->getIdentifier()->getName()));
5816193326Sed  }
5817193326Sed
5818193326Sed  if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden)
5819193326Sed    Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
5820193326Sed  Entry->setAlignment(8);
5821193326Sed
5822193326Sed  if (ForDefinition) {
5823193326Sed    Entry->setSection("__DATA,__objc_const");
5824193326Sed    Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
5825193326Sed  } else {
5826193326Sed    Entry->setSection("__DATA,__datacoal_nt,coalesced");
5827193326Sed  }
5828193326Sed
5829193326Sed  return Entry;
5830193326Sed}
5831198092Srdivacky
5832193326Sed/* *** */
5833193326Sed
5834193326SedCodeGen::CGObjCRuntime *
5835193326SedCodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
5836193326Sed  return new CGObjCMac(CGM);
5837193326Sed}
5838193326Sed
5839193326SedCodeGen::CGObjCRuntime *
5840193326SedCodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) {
5841193326Sed  return new CGObjCNonFragileABIMac(CGM);
5842193326Sed}
5843