CGObjCGNU.cpp revision d9a1db3a4ded1c8f0daa43c0d6167576e2766453
120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
20f984268b05edab2cc555a427c441baa9c252658Chris Lattner//
30f984268b05edab2cc555a427c441baa9c252658Chris Lattner//                     The LLVM Compiler Infrastructure
40f984268b05edab2cc555a427c441baa9c252658Chris Lattner//
50f984268b05edab2cc555a427c441baa9c252658Chris Lattner// This file is distributed under the University of Illinois Open Source
60f984268b05edab2cc555a427c441baa9c252658Chris Lattner// License. See LICENSE.TXT for details.
70f984268b05edab2cc555a427c441baa9c252658Chris Lattner//
80f984268b05edab2cc555a427c441baa9c252658Chris Lattner//===----------------------------------------------------------------------===//
90f984268b05edab2cc555a427c441baa9c252658Chris Lattner//
1020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov// This provides Objective-C code generation targetting the GNU runtime.  The
1120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov// class in this file generates structures used by the GNU Objective-C runtime
1220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov// library.  These structures are defined in objc/objc.h and objc/objc-api.h in
1320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov// the GNU runtime distribution.
140f984268b05edab2cc555a427c441baa9c252658Chris Lattner//
150f984268b05edab2cc555a427c441baa9c252658Chris Lattner//===----------------------------------------------------------------------===//
160f984268b05edab2cc555a427c441baa9c252658Chris Lattner
170f984268b05edab2cc555a427c441baa9c252658Chris Lattner#include "CGObjCRuntime.h"
18dce1406f1c1f572cfd61c494546572d63461c741Chris Lattner#include "CodeGenModule.h"
198f2926b73ed635afecd020da787af6a837601a2bDaniel Dunbar#include "CodeGenFunction.h"
205dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
21dce1406f1c1f572cfd61c494546572d63461c741Chris Lattner#include "clang/AST/ASTContext.h"
22e91593ef084479340582b2ba177b44be50a717b7Daniel Dunbar#include "clang/AST/Decl.h"
23af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar#include "clang/AST/DeclObjC.h"
2419cc4abea06a9b49e0e16a50d335c064cd723572Anders Carlsson#include "clang/AST/RecordLayout.h"
2516f0049415ec596504891259e2a83e19871c0d52Chris Lattner#include "clang/AST/StmtObjC.h"
265dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
275dc0867af17b3bd6f567897433853b2b4767446cChris Lattner#include "llvm/Intrinsics.h"
280f984268b05edab2cc555a427c441baa9c252658Chris Lattner#include "llvm/Module.h"
290f984268b05edab2cc555a427c441baa9c252658Chris Lattner#include "llvm/ADT/SmallVector.h"
3020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov#include "llvm/ADT/StringMap.h"
317ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar#include "llvm/Support/Compiler.h"
327ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar#include "llvm/Target/TargetData.h"
335dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
3420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov#include <map>
35e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner
36e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner
37dce1406f1c1f572cfd61c494546572d63461c741Chris Lattnerusing namespace clang;
3846f45b9bec4a265ad8400a538e5ec3a5683617f1Daniel Dunbarusing namespace CodeGen;
3920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovusing llvm::dyn_cast;
4020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
4120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov// The version of the runtime that this class targets.  Must match the version
4220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov// in the runtime.
4320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovstatic const int RuntimeVersion = 8;
449cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanianstatic const int NonFragileRuntimeVersion = 9;
4520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovstatic const int ProtocolVersion = 2;
46d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanianstatic const int NonFragileProtocolVersion = 3;
470f984268b05edab2cc555a427c441baa9c252658Chris Lattner
480f984268b05edab2cc555a427c441baa9c252658Chris Lattnernamespace {
49dce1406f1c1f572cfd61c494546572d63461c741Chris Lattnerclass CGObjCGNU : public CodeGen::CGObjCRuntime {
500f984268b05edab2cc555a427c441baa9c252658Chris Lattnerprivate:
51dce1406f1c1f572cfd61c494546572d63461c741Chris Lattner  CodeGen::CodeGenModule &CGM;
520f984268b05edab2cc555a427c441baa9c252658Chris Lattner  llvm::Module &TheModule;
53e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  const llvm::PointerType *SelectorTy;
54d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  const llvm::IntegerType *Int8Ty;
55e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  const llvm::PointerType *PtrToInt8Ty;
56b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  const llvm::FunctionType *IMPTy;
57e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  const llvm::PointerType *IdTy;
580f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall  QualType ASTIdTy;
59e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  const llvm::IntegerType *IntTy;
60e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  const llvm::PointerType *PtrTy;
61e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  const llvm::IntegerType *LongTy;
62e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  const llvm::PointerType *PtrToIntTy;
635efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  llvm::GlobalAlias *ClassPtrAlias;
645efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  llvm::GlobalAlias *MetaClassPtrAlias;
6520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Classes;
6620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Categories;
6720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> ConstantStrings;
6820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Function *LoadFunction;
6920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::StringMap<llvm::Constant*> ExistingProtocols;
7020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  typedef std::pair<std::string, std::string> TypedSelector;
7120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::map<TypedSelector, llvm::GlobalAlias*> TypedSelectors;
7220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::StringMap<llvm::GlobalAlias*> UntypedSelectors;
7320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Some zeros used for GEPs in lots of places.
7420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *Zeros[2];
7520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *NULLPtr;
76a1cf15f4680e5cf39e72e28c5ea854fcba792e84Owen Anderson  llvm::LLVMContext &VMContext;
7720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovprivate:
7820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *GenerateIvarList(
7920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      const llvm::SmallVectorImpl<llvm::Constant *>  &IvarNames,
8020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      const llvm::SmallVectorImpl<llvm::Constant *>  &IvarTypes,
8120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      const llvm::SmallVectorImpl<llvm::Constant *>  &IvarOffsets);
8220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *GenerateMethodList(const std::string &ClassName,
8320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      const std::string &CategoryName,
841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      const llvm::SmallVectorImpl<Selector>  &MethodSels,
851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      const llvm::SmallVectorImpl<llvm::Constant *>  &MethodTypes,
8620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      bool isClassMethodList);
87f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName);
88d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *GeneratePropertyList(const ObjCImplementationDecl *OID,
89d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
90d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes);
9120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *GenerateProtocolList(
9220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      const llvm::SmallVectorImpl<std::string> &Protocols);
93d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // To ensure that all protocols are seen by the runtime, we add a category on
94d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // a class defined in the runtime, declaring no methods, but adopting the
95d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // protocols.
96d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  void GenerateProtocolHolderCategory(void);
9720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *GenerateClassStructure(
9820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      llvm::Constant *MetaClass,
9920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      llvm::Constant *SuperClass,
10020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      unsigned info,
101d002cc6fc5b72bf00e3b7b4571ccf0f23c789b4bChris Lattner      const char *Name,
10220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      llvm::Constant *Version,
10320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      llvm::Constant *InstanceSize,
10420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      llvm::Constant *IVars,
10520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      llvm::Constant *Methods,
106d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::Constant *Protocols,
107d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::Constant *IvarOffsets,
108d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::Constant *Properties);
10920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *GenerateProtocolMethodList(
11020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      const llvm::SmallVectorImpl<llvm::Constant *>  &MethodNames,
11120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      const llvm::SmallVectorImpl<llvm::Constant *>  &MethodTypes);
11220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *MakeConstantString(const std::string &Str, const std::string
11320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      &Name="");
114d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *ExportUniqueString(const std::string &Str, const std::string
115d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          prefix);
11620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *MakeGlobal(const llvm::StructType *Ty,
11720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      std::vector<llvm::Constant*> &V, const std::string &Name="");
11820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty,
11920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      std::vector<llvm::Constant*> &V, const std::string &Name="");
1209cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
1219cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian      const ObjCIvarDecl *Ivar);
1222a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  void EmitClassRef(const std::string &className);
1230f984268b05edab2cc555a427c441baa9c252658Chris Lattnerpublic:
124dce1406f1c1f572cfd61c494546572d63461c741Chris Lattner  CGObjCGNU(CodeGen::CodeGenModule &cgm);
12533fdb738a6c125f4c788733897021b7c1a062b0cSteve Naroff  virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *);
1261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  virtual CodeGen::RValue
1278f2926b73ed635afecd020da787af6a837601a2bDaniel Dunbar  GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1287f8ea5c5b3a6a4332a841eefdd86b0726722ea7bDaniel Dunbar                      QualType ResultType,
1297f8ea5c5b3a6a4332a841eefdd86b0726722ea7bDaniel Dunbar                      Selector Sel,
130f56f1913e91ad32bed52dd3f6afc26735d336584Daniel Dunbar                      llvm::Value *Receiver,
13119cd87eb5fb3c197e631ce08fd52c446c4d4e8f1Daniel Dunbar                      bool IsClassMessage,
132df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian                      const CallArgList &CallArgs,
133df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian                      const ObjCMethodDecl *Method);
1341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  virtual CodeGen::RValue
1358f2926b73ed635afecd020da787af6a837601a2bDaniel Dunbar  GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
1367f8ea5c5b3a6a4332a841eefdd86b0726722ea7bDaniel Dunbar                           QualType ResultType,
1377f8ea5c5b3a6a4332a841eefdd86b0726722ea7bDaniel Dunbar                           Selector Sel,
138f56f1913e91ad32bed52dd3f6afc26735d336584Daniel Dunbar                           const ObjCInterfaceDecl *Class,
1397ce77920a35060f1c8dd72e541e42ce296ccd168Fariborz Jahanian                           bool isCategoryImpl,
140f56f1913e91ad32bed52dd3f6afc26735d336584Daniel Dunbar                           llvm::Value *Receiver,
14119cd87eb5fb3c197e631ce08fd52c446c4d4e8f1Daniel Dunbar                           bool IsClassMessage,
14219cd87eb5fb3c197e631ce08fd52c446c4d4e8f1Daniel Dunbar                           const CallArgList &CallArgs);
14345d196b8387dcefc4df26cda114fa34c6528e928Daniel Dunbar  virtual llvm::Value *GetClass(CGBuilderTy &Builder,
144ddb2a3d55a24a1dbdf9152621642d9a4b4fc2f61Daniel Dunbar                                const ObjCInterfaceDecl *OID);
14545d196b8387dcefc4df26cda114fa34c6528e928Daniel Dunbar  virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel);
146df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
147df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian      *Method);
1481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
150679a502d462ef819e6175b58e255ca3f3391e7cfFariborz Jahanian                                         const ObjCContainerDecl *CD);
1517ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
1527ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
15345d196b8387dcefc4df26cda114fa34c6528e928Daniel Dunbar  virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
154af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar                                           const ObjCProtocolDecl *PD);
155af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar  virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
15620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  virtual llvm::Function *ModuleInitFunction();
15749f6602707887eea1a558a1dffe0213102f887f2Daniel Dunbar  virtual llvm::Function *GetPropertyGetFunction();
15849f6602707887eea1a558a1dffe0213102f887f2Daniel Dunbar  virtual llvm::Function *GetPropertySetFunction();
159309a4368cd299cff30ab22709e2b772cf8059e45Daniel Dunbar  virtual llvm::Constant *EnumerationMutationFunction();
1601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
161bd71be4683c195260d5245118b1e13e6b2e20504Fariborz Jahanian  virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
162bd71be4683c195260d5245118b1e13e6b2e20504Fariborz Jahanian                                         const Stmt &S);
16364d5d6c5903157c521af496479d06dc26032d718Anders Carlsson  virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
16464d5d6c5903157c521af496479d06dc26032d718Anders Carlsson                             const ObjCAtThrowStmt &S);
1653e283e344595e0bd499b13b30a92b7d9c10a2140Fariborz Jahanian  virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1666dc2317b59cb1180a59f6c283d96b7a5dfeb5307Fariborz Jahanian                                         llvm::Value *AddrWeakObj);
1673e283e344595e0bd499b13b30a92b7d9c10a2140Fariborz Jahanian  virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1683e283e344595e0bd499b13b30a92b7d9c10a2140Fariborz Jahanian                                  llvm::Value *src, llvm::Value *dst);
16958626500527695865683d1d65053743de8770b60Fariborz Jahanian  virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
17058626500527695865683d1d65053743de8770b60Fariborz Jahanian                                    llvm::Value *src, llvm::Value *dest);
1717eda8367cf63caee8acf907356b1d199ccaa6e89Fariborz Jahanian  virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1727eda8367cf63caee8acf907356b1d199ccaa6e89Fariborz Jahanian                                    llvm::Value *src, llvm::Value *dest);
17358626500527695865683d1d65053743de8770b60Fariborz Jahanian  virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
17458626500527695865683d1d65053743de8770b60Fariborz Jahanian                                        llvm::Value *src, llvm::Value *dest);
175082b02e8403d3ee9d2ded969fbe0e5d472f04cd8Fariborz Jahanian  virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                        llvm::Value *DestPtr,
177082b02e8403d3ee9d2ded969fbe0e5d472f04cd8Fariborz Jahanian                                        llvm::Value *SrcPtr,
17808c321380fff07d476a19daab6d29522c046cd49Fariborz Jahanian                                        QualType Ty);
179598d3f61b6ca854e9d3c2f3359e24468502a61aaFariborz Jahanian  virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
180598d3f61b6ca854e9d3c2f3359e24468502a61aaFariborz Jahanian                                      QualType ObjectTy,
181598d3f61b6ca854e9d3c2f3359e24468502a61aaFariborz Jahanian                                      llvm::Value *BaseValue,
182598d3f61b6ca854e9d3c2f3359e24468502a61aaFariborz Jahanian                                      const ObjCIvarDecl *Ivar,
183598d3f61b6ca854e9d3c2f3359e24468502a61aaFariborz Jahanian                                      unsigned CVRQualifiers);
184f63aa3fd429cdb9145d78f0b656bc78754efedb9Fariborz Jahanian  virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1852a03192a02dbf4fdff438d1e658356bde871aba4Daniel Dunbar                                      const ObjCInterfaceDecl *Interface,
186f63aa3fd429cdb9145d78f0b656bc78754efedb9Fariborz Jahanian                                      const ObjCIvarDecl *Ivar);
1870f984268b05edab2cc555a427c441baa9c252658Chris Lattner};
1880f984268b05edab2cc555a427c441baa9c252658Chris Lattner} // end anonymous namespace
1890f984268b05edab2cc555a427c441baa9c252658Chris Lattner
19020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
1912a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner/// Emits a reference to a dummy variable which is emitted with each class.
1922a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner/// This ensures that a linker error will be generated when trying to link
1932a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner/// together modules where a referenced class is not defined.
194bb1c8600218b3244340331165fc7cba7bf227655Mike Stumpvoid CGObjCGNU::EmitClassRef(const std::string &className) {
1952a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  std::string symbolRef = "__objc_class_ref_" + className;
1962a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  // Don't emit two copies of the same symbol
197bb1c8600218b3244340331165fc7cba7bf227655Mike Stump  if (TheModule.getGlobalVariable(symbolRef))
198bb1c8600218b3244340331165fc7cba7bf227655Mike Stump    return;
1992a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  std::string symbolName = "__objc_class_name_" + className;
2002a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
2012a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  if (!ClassSymbol) {
2021c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson    ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
2031c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson        llvm::GlobalValue::ExternalLinkage, 0, symbolName);
2042a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  }
2051c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson  new llvm::GlobalVariable(TheModule, ClassSymbol->getType(), true,
206f35271b8677a5f31498b89587b1da42a06dd46fdChris Lattner    llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
2072a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner}
20820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
20920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovstatic std::string SymbolNameForClass(const std::string &ClassName) {
2102a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  return "_OBJC_CLASS_" + ClassName;
21120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
21220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
213d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanianstatic std::string SymbolNameForMethod(const std::string &ClassName, const
214d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
215d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian{
2162a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  return "_OBJC_METHOD_" + ClassName + "("+CategoryName+")"+
21720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov            (isClassMethod ? "+" : "-") + MethodName;
21820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
21920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
220dce1406f1c1f572cfd61c494546572d63461c741Chris LattnerCGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
2215efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  : CGM(cgm), TheModule(CGM.getModule()), ClassPtrAlias(0),
222a1cf15f4680e5cf39e72e28c5ea854fcba792e84Owen Anderson    MetaClassPtrAlias(0), VMContext(cgm.getLLVMContext()) {
223e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  IntTy = cast<llvm::IntegerType>(
224e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner      CGM.getTypes().ConvertType(CGM.getContext().IntTy));
225e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  LongTy = cast<llvm::IntegerType>(
226e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner      CGM.getTypes().ConvertType(CGM.getContext().LongTy));
2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
228d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Int8Ty = llvm::Type::getInt8Ty(VMContext);
229d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // C string type.  Used in lots of places.
230d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
231d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
2324a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson  Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
23320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Zeros[1] = Zeros[0];
234d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
235391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner  // Get the selector Type.
236e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  SelectorTy = cast<llvm::PointerType>(
237e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner    CGM.getTypes().ConvertType(CGM.getContext().getObjCSelType()));
238e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner
23996e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson  PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
240391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner  PtrTy = PtrToInt8Ty;
2411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
242391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner  // Object type
2430f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall  ASTIdTy = CGM.getContext().getObjCIdType();
2440f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall  IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
2451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
246391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner  // IMP type
247391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner  std::vector<const llvm::Type*> IMPArgs;
248391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner  IMPArgs.push_back(IdTy);
249391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner  IMPArgs.push_back(SelectorTy);
25096e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson  IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
25120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
252bb1c8600218b3244340331165fc7cba7bf227655Mike Stump
25320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov// This has to perform the lookup every time, since posing and related
25420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov// techniques can modify the name -> class mapping.
25545d196b8387dcefc4df26cda114fa34c6528e928Daniel Dunbarllvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder,
256ddb2a3d55a24a1dbdf9152621642d9a4b4fc2f61Daniel Dunbar                                 const ObjCInterfaceDecl *OID) {
257d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner  llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getNameAsString());
2582a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  EmitClassRef(OID->getNameAsString());
259ddb2a3d55a24a1dbdf9152621642d9a4b4fc2f61Daniel Dunbar  ClassName = Builder.CreateStructGEP(ClassName, 0);
260ddb2a3d55a24a1dbdf9152621642d9a4b4fc2f61Daniel Dunbar
26126c8294dacc2efc83d8d560593ff863e7a32a48fFariborz Jahanian  std::vector<const llvm::Type*> Params(1, PtrToInt8Ty);
26220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *ClassLookupFn =
26396e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson    CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy,
26426c8294dacc2efc83d8d560593ff863e7a32a48fFariborz Jahanian                                                      Params,
26526c8294dacc2efc83d8d560593ff863e7a32a48fFariborz Jahanian                                                      true),
26626c8294dacc2efc83d8d560593ff863e7a32a48fFariborz Jahanian                              "objc_lookup_class");
26720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  return Builder.CreateCall(ClassLookupFn, ClassName);
268391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner}
269391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner
27045d196b8387dcefc4df26cda114fa34c6528e928Daniel Dunbarllvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel) {
271077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner  llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()];
2728e67b63530b4f39a48bc12d97376f373a6901279Chris Lattner  if (US == 0)
27396e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson    US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy),
2740f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall                               llvm::GlobalValue::PrivateLinkage,
2750f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall                               ".objc_untyped_selector_alias"+Sel.getAsString(),
2768e67b63530b4f39a48bc12d97376f373a6901279Chris Lattner                               NULL, &TheModule);
2771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2788e67b63530b4f39a48bc12d97376f373a6901279Chris Lattner  return Builder.CreateLoad(US);
279df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian}
280df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian
281df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanianllvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
282df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian    *Method) {
283df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian
284df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  std::string SelName = Method->getSelector().getAsString();
285df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  std::string SelTypes;
286df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  CGM.getContext().getObjCEncodingForMethodDecl(Method, SelTypes);
287df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  // Typed selectors
288df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  TypedSelector Selector = TypedSelector(SelName,
289df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian          SelTypes);
290df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian
291df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  // If it's already cached, return it.
292bb1c8600218b3244340331165fc7cba7bf227655Mike Stump  if (TypedSelectors[Selector]) {
293bb1c8600218b3244340331165fc7cba7bf227655Mike Stump    return Builder.CreateLoad(TypedSelectors[Selector]);
294df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  }
295df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian
296df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  // If it isn't, cache it.
297df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  llvm::GlobalAlias *Sel = new llvm::GlobalAlias(
29896e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson          llvm::PointerType::getUnqual(SelectorTy),
2990f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall          llvm::GlobalValue::PrivateLinkage, ".objc_selector_alias" + SelName,
300df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian          NULL, &TheModule);
301df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  TypedSelectors[Selector] = Sel;
302df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian
303df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  return Builder.CreateLoad(Sel);
3048e67b63530b4f39a48bc12d97376f373a6901279Chris Lattner}
3058e67b63530b4f39a48bc12d97376f373a6901279Chris Lattner
3065e7dcc62e4637591959f9c372f6c5258d0d263e0Chris Lattnerllvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str,
3075e7dcc62e4637591959f9c372f6c5258d0d263e0Chris Lattner                                              const std::string &Name) {
3088a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
3093c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson  return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
31020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
311d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanianllvm::Constant *CGObjCGNU::ExportUniqueString(const std::string &Str,
312d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        const std::string prefix) {
313d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  std::string name = prefix + Str;
314d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *ConstStr = TheModule.getGlobalVariable(name);
315d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  if (!ConstStr) {
316d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    llvm::Constant *value = llvm::ConstantArray::get(VMContext, Str, true);
317d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true,
318d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian            llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str);
319d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  }
320d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
321d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian}
322bb1c8600218b3244340331165fc7cba7bf227655Mike Stump
32320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovllvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty,
32420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    std::vector<llvm::Constant*> &V, const std::string &Name) {
32508e252425ca2cbdc44ba65d9a657ed5398014e36Owen Anderson  llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
3261c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson  return new llvm::GlobalVariable(TheModule, Ty, false,
3271c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson      llvm::GlobalValue::InternalLinkage, C, Name);
32820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
329bb1c8600218b3244340331165fc7cba7bf227655Mike Stump
33020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovllvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
33120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    std::vector<llvm::Constant*> &V, const std::string &Name) {
3327db6d838aad4083fe86d7bf703a75fe6e8a17856Owen Anderson  llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
3331c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson  return new llvm::GlobalVariable(TheModule, Ty, false,
334bb1c8600218b3244340331165fc7cba7bf227655Mike Stump                                  llvm::GlobalValue::InternalLinkage, C, Name);
33520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
33620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
33720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov/// Generate an NSConstantString object.
33820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov//TODO: In case there are any crazy people still using the GNU runtime without
33920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov//an OpenStep implementation, this should let them select their own class for
34020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov//constant strings.
34133fdb738a6c125f4c788733897021b7c1a062b0cSteve Naroffllvm::Constant *CGObjCGNU::GenerateConstantString(const ObjCStringLiteral *SL) {
3421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  std::string Str(SL->getString()->getStrData(),
34333fdb738a6c125f4c788733897021b7c1a062b0cSteve Naroff                  SL->getString()->getByteLength());
34420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Ivars;
34520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Ivars.push_back(NULLPtr);
34613fd7e5111032f54b538dd66d035b0ccc1f82467Chris Lattner  Ivars.push_back(MakeConstantString(Str));
3474a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson  Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
34820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *ObjCStr = MakeGlobal(
34947a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson    llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL),
35020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    Ivars, ".objc_str");
35120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  ConstantStrings.push_back(
3523c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson      llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty));
35320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  return ObjCStr;
35420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
35520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
35620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov///Generates a message send where the super is the receiver.  This is a message
35720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov///send to self with special delivery semantics indicating which class's method
35820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov///should be called.
3598f2926b73ed635afecd020da787af6a837601a2bDaniel DunbarCodeGen::RValue
3608f2926b73ed635afecd020da787af6a837601a2bDaniel DunbarCGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
3617f8ea5c5b3a6a4332a841eefdd86b0726722ea7bDaniel Dunbar                                    QualType ResultType,
3627f8ea5c5b3a6a4332a841eefdd86b0726722ea7bDaniel Dunbar                                    Selector Sel,
363f56f1913e91ad32bed52dd3f6afc26735d336584Daniel Dunbar                                    const ObjCInterfaceDecl *Class,
3647ce77920a35060f1c8dd72e541e42ce296ccd168Fariborz Jahanian                                    bool isCategoryImpl,
365f56f1913e91ad32bed52dd3f6afc26735d336584Daniel Dunbar                                    llvm::Value *Receiver,
36619cd87eb5fb3c197e631ce08fd52c446c4d4e8f1Daniel Dunbar                                    bool IsClassMessage,
36719cd87eb5fb3c197e631ce08fd52c446c4d4e8f1Daniel Dunbar                                    const CallArgList &CallArgs) {
368b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
369b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian
370b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  CallArgList ActualArgs;
371b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian
372b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  ActualArgs.push_back(
3730f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall      std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)),
3740f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall      ASTIdTy));
375b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  ActualArgs.push_back(std::make_pair(RValue::get(cmd),
376b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian                                      CGF.getContext().getObjCSelType()));
377b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
378b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian
379b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  CodeGenTypes &Types = CGM.getTypes();
380b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
381b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  const llvm::FunctionType *impType = Types.GetFunctionType(FnInfo, false);
382b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian
3835efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  llvm::Value *ReceiverClass = 0;
38448e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner  if (isCategoryImpl) {
38548e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner    llvm::Constant *classLookupFunction = 0;
38648e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner    std::vector<const llvm::Type*> Params;
38748e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner    Params.push_back(PtrTy);
38848e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner    if (IsClassMessage)  {
38996e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson      classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
39048e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner            IdTy, Params, true), "objc_get_meta_class");
39148e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner    } else {
39296e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson      classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
39348e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner            IdTy, Params, true), "objc_get_class");
3945efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar    }
39548e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner    ReceiverClass = CGF.Builder.CreateCall(classLookupFunction,
39648e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner        MakeConstantString(Class->getNameAsString()));
3975efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  } else {
39848e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner    // Set up global aliases for the metaclass or class pointer if they do not
39948e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner    // already exist.  These will are forward-references which will be set to
400bb1c8600218b3244340331165fc7cba7bf227655Mike Stump    // pointers to the class and metaclass structure created for the runtime
401bb1c8600218b3244340331165fc7cba7bf227655Mike Stump    // load function.  To send a message to super, we look up the value of the
40248e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner    // super_class pointer from either the class or metaclass structure.
40348e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner    if (IsClassMessage)  {
40448e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner      if (!MetaClassPtrAlias) {
40548e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner        MetaClassPtrAlias = new llvm::GlobalAlias(IdTy,
40648e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner            llvm::GlobalValue::InternalLinkage, ".objc_metaclass_ref" +
40748e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner            Class->getNameAsString(), NULL, &TheModule);
40848e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner      }
40948e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner      ReceiverClass = MetaClassPtrAlias;
41048e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner    } else {
41148e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner      if (!ClassPtrAlias) {
41248e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner        ClassPtrAlias = new llvm::GlobalAlias(IdTy,
41348e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner            llvm::GlobalValue::InternalLinkage, ".objc_class_ref" +
41448e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner            Class->getNameAsString(), NULL, &TheModule);
41548e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner      }
41648e6e7e8106f2404bfdd2d8abe7a840aeeaf047bChris Lattner      ReceiverClass = ClassPtrAlias;
4175efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar    }
41871238f67c5df13eef19450d66b7a7ab28377192aChris Lattner  }
4195efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  // Cast the pointer to a simplified version of the class structure
4201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ReceiverClass = CGF.Builder.CreateBitCast(ReceiverClass,
42196e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson      llvm::PointerType::getUnqual(
42247a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson        llvm::StructType::get(VMContext, IdTy, IdTy, NULL)));
4235efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  // Get the superclass pointer
4245efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  ReceiverClass = CGF.Builder.CreateStructGEP(ReceiverClass, 1);
4255efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  // Load the superclass pointer
4265efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  ReceiverClass = CGF.Builder.CreateLoad(ReceiverClass);
42720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Construct the structure used to look up the IMP
42847a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType *ObjCSuperTy = llvm::StructType::get(VMContext,
42947a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson      Receiver->getType(), IdTy, NULL);
4308f2926b73ed635afecd020da787af6a837601a2bDaniel Dunbar  llvm::Value *ObjCSuper = CGF.Builder.CreateAlloca(ObjCSuperTy);
431b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian
4328f2926b73ed635afecd020da787af6a837601a2bDaniel Dunbar  CGF.Builder.CreateStore(Receiver, CGF.Builder.CreateStructGEP(ObjCSuper, 0));
4335efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  CGF.Builder.CreateStore(ReceiverClass,
4345efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar      CGF.Builder.CreateStructGEP(ObjCSuper, 1));
43520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
43620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Get the IMP
43726c8294dacc2efc83d8d560593ff863e7a32a48fFariborz Jahanian  std::vector<const llvm::Type*> Params;
43896e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson  Params.push_back(llvm::PointerType::getUnqual(ObjCSuperTy));
43926c8294dacc2efc83d8d560593ff863e7a32a48fFariborz Jahanian  Params.push_back(SelectorTy);
4401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  llvm::Constant *lookupFunction =
44196e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson    CGM.CreateRuntimeFunction(llvm::FunctionType::get(
44296e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson          llvm::PointerType::getUnqual(impType), Params, true),
44326c8294dacc2efc83d8d560593ff863e7a32a48fFariborz Jahanian        "objc_msg_lookup_super");
44426c8294dacc2efc83d8d560593ff863e7a32a48fFariborz Jahanian
44520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
4468f2926b73ed635afecd020da787af6a837601a2bDaniel Dunbar  llvm::Value *imp = CGF.Builder.CreateCall(lookupFunction, lookupArgs,
44720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      lookupArgs+2);
44820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
449b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  return CGF.EmitCall(FnInfo, imp, ActualArgs);
45020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
45120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
4521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// Generate code for a message send expression.
4538f2926b73ed635afecd020da787af6a837601a2bDaniel DunbarCodeGen::RValue
4548f2926b73ed635afecd020da787af6a837601a2bDaniel DunbarCGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
4557f8ea5c5b3a6a4332a841eefdd86b0726722ea7bDaniel Dunbar                               QualType ResultType,
4567f8ea5c5b3a6a4332a841eefdd86b0726722ea7bDaniel Dunbar                               Selector Sel,
457f56f1913e91ad32bed52dd3f6afc26735d336584Daniel Dunbar                               llvm::Value *Receiver,
45819cd87eb5fb3c197e631ce08fd52c446c4d4e8f1Daniel Dunbar                               bool IsClassMessage,
459df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian                               const CallArgList &CallArgs,
460df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian                               const ObjCMethodDecl *Method) {
461d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  CGBuilderTy &Builder = CGF.Builder;
4620f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall  IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
463df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  llvm::Value *cmd;
464df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  if (Method)
465d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    cmd = GetSelector(Builder, Method);
466df9ccc6381314ccca6407abb209155e9273a631dFariborz Jahanian  else
467d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    cmd = GetSelector(Builder, Sel);
468b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  CallArgList ActualArgs;
469b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian
470d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Receiver = Builder.CreateBitCast(Receiver, IdTy);
471b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  ActualArgs.push_back(
472d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    std::make_pair(RValue::get(Receiver), ASTIdTy));
473b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  ActualArgs.push_back(std::make_pair(RValue::get(cmd),
474b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian                                      CGF.getContext().getObjCSelType()));
475b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
476b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian
477b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  CodeGenTypes &Types = CGM.getTypes();
478b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
479b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  const llvm::FunctionType *impType = Types.GetFunctionType(FnInfo, false);
4800f984268b05edab2cc555a427c441baa9c252658Chris Lattner
48134e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian  llvm::Value *imp;
48234e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian  // For sender-aware dispatch, we pass the sender as the third argument to a
48334e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian  // lookup function.  When sending messages from C code, the sender is nil.
484d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // objc_msg_lookup_sender(id *receiver, SEL selector, id sender);
485d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
486d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
487d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    std::vector<const llvm::Type*> Params;
488d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    llvm::Value *ReceiverPtr = CGF.CreateTempAlloca(Receiver->getType());
489d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Builder.CreateStore(Receiver, ReceiverPtr);
490d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Params.push_back(ReceiverPtr->getType());
491d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Params.push_back(SelectorTy);
49234e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian    llvm::Value *self;
49334e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian
49434e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian    if (isa<ObjCMethodDecl>(CGF.CurFuncDecl)) {
49534e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian      self = CGF.LoadObjCSelf();
49634e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian    } else {
49703e205031b08669f05c41eed5b896fc94c4a12bbOwen Anderson      self = llvm::ConstantPointerNull::get(IdTy);
49834e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian    }
499d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
50034e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian    Params.push_back(self->getType());
501d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
502d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    // The lookup function returns a slot, which can be safely cached.
503d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy,
504d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian            IntTy, llvm::PointerType::getUnqual(impType), NULL);
5051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    llvm::Constant *lookupFunction =
50696e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson      CGM.CreateRuntimeFunction(llvm::FunctionType::get(
507d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          llvm::PointerType::getUnqual(SlotTy), Params, true),
50834e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian        "objc_msg_lookup_sender");
50926c8294dacc2efc83d8d560593ff863e7a32a48fFariborz Jahanian
510d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    // The lookup function is guaranteed not to capture the receiver pointer.
511d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    if (llvm::Function *LookupFn = dyn_cast<llvm::Function>(lookupFunction)) {
512d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      LookupFn->setDoesNotCapture(1);
513d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    }
514d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
515d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    llvm::Value *slot =
516d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        Builder.CreateCall3(lookupFunction, ReceiverPtr, cmd, self);
517d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4));
518d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    // The lookup function may have changed the receiver, so make sure we use
519d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    // the new one.
520d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    ActualArgs[0] =
521d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        std::make_pair(RValue::get(Builder.CreateLoad(ReceiverPtr)), ASTIdTy);
52234e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian  } else {
523d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    std::vector<const llvm::Type*> Params;
524d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Params.push_back(Receiver->getType());
525d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Params.push_back(SelectorTy);
5261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    llvm::Constant *lookupFunction =
52796e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson    CGM.CreateRuntimeFunction(llvm::FunctionType::get(
52896e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson        llvm::PointerType::getUnqual(impType), Params, true),
52934e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian      "objc_msg_lookup");
53034e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian
531d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    imp = Builder.CreateCall2(lookupFunction, Receiver, cmd);
53234e65770ad6142b033d6cec4f476ed20fb248bf3Fariborz Jahanian  }
5333eae03e7d165f20a863a9a4d7122ba2a691ab16dChris Lattner
534b3716efb0966620f205c939b671b579ad331ca0dFariborz Jahanian  return CGF.EmitCall(FnInfo, imp, ActualArgs);
53520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
53620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
5371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// Generates a MethodList.  Used in construction of a objc_class and
53820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov/// objc_category structures.
53920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovllvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName,
5401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                              const std::string &CategoryName,
5411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    const llvm::SmallVectorImpl<Selector> &MethodSels,
5421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
54320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    bool isClassMethodList) {
5440f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall  if (MethodSels.empty())
5450f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall    return NULLPtr;
5461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Get the method structure type.
54747a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType *ObjCMethodTy = llvm::StructType::get(VMContext,
54820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    PtrToInt8Ty, // Really a selector, but the runtime creates it us.
54920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    PtrToInt8Ty, // Method types
55096e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson    llvm::PointerType::getUnqual(IMPTy), //Method pointer
55120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    NULL);
55220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Methods;
55320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Elements;
55420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
55520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    Elements.clear();
5561e64a9531bf6e9d99ad3271b3a735ef702689b06Fariborz Jahanian    if (llvm::Constant *Method =
55720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
558077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner                                                MethodSels[i].getAsString(),
5591e64a9531bf6e9d99ad3271b3a735ef702689b06Fariborz Jahanian                                                isClassMethodList))) {
5608a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString());
5618a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      Elements.push_back(C);
5628a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      Elements.push_back(MethodTypes[i]);
5633c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson      Method = llvm::ConstantExpr::getBitCast(Method,
56496e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson          llvm::PointerType::getUnqual(IMPTy));
5651e64a9531bf6e9d99ad3271b3a735ef702689b06Fariborz Jahanian      Elements.push_back(Method);
56608e252425ca2cbdc44ba65d9a657ed5398014e36Owen Anderson      Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements));
5671e64a9531bf6e9d99ad3271b3a735ef702689b06Fariborz Jahanian    }
56820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  }
56920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
57020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Array of method structures
57196e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson  llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
5721e64a9531bf6e9d99ad3271b3a735ef702689b06Fariborz Jahanian                                                            Methods.size());
5737db6d838aad4083fe86d7bf703a75fe6e8a17856Owen Anderson  llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy,
574fba676396703e87a5034e5f308aa30a633468f66Chris Lattner                                                         Methods);
57520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
57620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Structure containing list pointer, array and array count
57720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields;
5788c8f69ec1477424e11faef6b235505584d61e522Owen Anderson  llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get(VMContext);
57996e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson  llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy);
58047a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType *ObjCMethodListTy = llvm::StructType::get(VMContext,
5811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      NextPtrTy,
5821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      IntTy,
58320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      ObjCMethodArrayTy,
58420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      NULL);
58520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Refine next pointer type to concrete type
58620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::cast<llvm::OpaqueType>(
58720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      OpaqueNextTy.get())->refineAbstractTypeTo(ObjCMethodListTy);
58820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  ObjCMethodListTy = llvm::cast<llvm::StructType>(OpaqueNextTy.get());
58920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
59020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Methods.clear();
59103e205031b08669f05c41eed5b896fc94c4a12bbOwen Anderson  Methods.push_back(llvm::ConstantPointerNull::get(
59296e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson        llvm::PointerType::getUnqual(ObjCMethodListTy)));
5930032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson  Methods.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
59420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov        MethodTypes.size()));
59520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Methods.push_back(MethodArray);
5961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
59720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Create an instance of the structure
59820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list");
59920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
60020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
60120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov/// Generates an IvarList.  Used in construction of a objc_class.
60220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovllvm::Constant *CGObjCGNU::GenerateIvarList(
60320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    const llvm::SmallVectorImpl<llvm::Constant *>  &IvarNames,
60420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    const llvm::SmallVectorImpl<llvm::Constant *>  &IvarTypes,
60520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    const llvm::SmallVectorImpl<llvm::Constant *>  &IvarOffsets) {
6061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Get the method structure type.
60747a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType *ObjCIvarTy = llvm::StructType::get(VMContext,
60820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    PtrToInt8Ty,
60920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    PtrToInt8Ty,
61020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    IntTy,
61120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    NULL);
61220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Ivars;
61320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Elements;
61420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
61520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    Elements.clear();
6168a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    Elements.push_back(IvarNames[i]);
6178a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    Elements.push_back(IvarTypes[i]);
61820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    Elements.push_back(IvarOffsets[i]);
61908e252425ca2cbdc44ba65d9a657ed5398014e36Owen Anderson    Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements));
62020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  }
62120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
62220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Array of method structures
62396e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson  llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
62420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      IvarNames.size());
62520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
6261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
62720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.clear();
6284a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson  Elements.push_back(llvm::ConstantInt::get(IntTy, (int)IvarNames.size()));
6297db6d838aad4083fe86d7bf703a75fe6e8a17856Owen Anderson  Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars));
63020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Structure containing array and array count
63147a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType *ObjCIvarListTy = llvm::StructType::get(VMContext, IntTy,
63220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    ObjCIvarArrayTy,
63320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    NULL);
63420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
63520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Create an instance of the structure
63620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list");
6370f984268b05edab2cc555a427c441baa9c252658Chris Lattner}
6380f984268b05edab2cc555a427c441baa9c252658Chris Lattner
63920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov/// Generate a class structure
64020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovllvm::Constant *CGObjCGNU::GenerateClassStructure(
64120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    llvm::Constant *MetaClass,
64220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    llvm::Constant *SuperClass,
64320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    unsigned info,
644d002cc6fc5b72bf00e3b7b4571ccf0f23c789b4bChris Lattner    const char *Name,
64520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    llvm::Constant *Version,
64620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    llvm::Constant *InstanceSize,
64720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    llvm::Constant *IVars,
64820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    llvm::Constant *Methods,
649d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    llvm::Constant *Protocols,
650d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    llvm::Constant *IvarOffsets,
651d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    llvm::Constant *Properties) {
65220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Set up the class structure
65320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Note:  Several of these are char*s when they should be ids.  This is
65420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // because the runtime performs this translation on load.
655d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  //
656d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // Fields marked New ABI are part of the GNUstep runtime.  We emit them
657d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // anyway; the classes will still work with the GNU runtime, they will just
658d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // be ignored.
65947a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType *ClassTy = llvm::StructType::get(VMContext,
66020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      PtrToInt8Ty,        // class_pointer
66120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      PtrToInt8Ty,        // super_class
66220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      PtrToInt8Ty,        // name
66320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      LongTy,             // version
66420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      LongTy,             // info
66520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      LongTy,             // instance_size
66620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      IVars->getType(),   // ivars
66720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      Methods->getType(), // methods
6681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      // These are all filled in by the runtime, so we pretend
66920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      PtrTy,              // dtable
67020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      PtrTy,              // subclass_list
67120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      PtrTy,              // sibling_class
67220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      PtrTy,              // protocols
67320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      PtrTy,              // gc_object_type
674d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      // New ABI:
675d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      LongTy,                 // abi_version
676d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      IvarOffsets->getType(), // ivar_offsets
677d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Properties->getType(),  // properties
67820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      NULL);
6794a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson  llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
68020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Fill in the structure
68120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Elements;
6823c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson  Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
68320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(SuperClass);
684d002cc6fc5b72bf00e3b7b4571ccf0f23c789b4bChris Lattner  Elements.push_back(MakeConstantString(Name, ".class_name"));
68520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(Zero);
6864a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson  Elements.push_back(llvm::ConstantInt::get(LongTy, info));
68720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(InstanceSize);
68820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(IVars);
68920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(Methods);
690d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(NULLPtr);
691d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(NULLPtr);
692d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(NULLPtr);
6933c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson  Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
694d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(NULLPtr);
695d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(Zero);
696d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(IvarOffsets);
697d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(Properties);
69820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Create an instance of the structure
6991565e0364b05d163640dd2b6feed43bae67df4fdChris Lattner  return MakeGlobal(ClassTy, Elements, SymbolNameForClass(Name));
70020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
70120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
70220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovllvm::Constant *CGObjCGNU::GenerateProtocolMethodList(
70320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    const llvm::SmallVectorImpl<llvm::Constant *>  &MethodNames,
70420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    const llvm::SmallVectorImpl<llvm::Constant *>  &MethodTypes) {
7051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Get the method structure type.
70647a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(VMContext,
70720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
70820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    PtrToInt8Ty,
70920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    NULL);
71020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Methods;
71120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Elements;
71220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
71320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    Elements.clear();
7141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    Elements.push_back(MethodNames[i]);
7158a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    Elements.push_back(MethodTypes[i]);
71608e252425ca2cbdc44ba65d9a657ed5398014e36Owen Anderson    Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements));
71720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  }
71896e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson  llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
71920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      MethodNames.size());
7207db6d838aad4083fe86d7bf703a75fe6e8a17856Owen Anderson  llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy,
721bb1c8600218b3244340331165fc7cba7bf227655Mike Stump                                                   Methods);
72247a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(VMContext,
72320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      IntTy, ObjCMethodArrayTy, NULL);
72420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Methods.clear();
7254a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson  Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
72620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Methods.push_back(Array);
72720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list");
72820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
729bb1c8600218b3244340331165fc7cba7bf227655Mike Stump
73020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov// Create the protocol list structure used in classes, categories and so on
73120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikovllvm::Constant *CGObjCGNU::GenerateProtocolList(
73220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    const llvm::SmallVectorImpl<std::string> &Protocols) {
73396e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson  llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
73420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      Protocols.size());
73547a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext,
73620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      PtrTy, //Should be a recurisve pointer, but it's always NULL here.
73720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      LongTy,//FIXME: Should be size_t
73820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      ProtocolArrayTy,
73920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      NULL);
7401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  std::vector<llvm::Constant*> Elements;
74120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
74220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      iter != endIter ; iter++) {
743f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian    llvm::Constant *protocol = ExistingProtocols[*iter];
744f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian    if (!protocol)
745f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian      protocol = GenerateEmptyProtocol(*iter);
7463c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson    llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(protocol,
747a1cf15f4680e5cf39e72e28c5ea854fcba792e84Owen Anderson                                                           PtrToInt8Ty);
74820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    Elements.push_back(Ptr);
74920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  }
7507db6d838aad4083fe86d7bf703a75fe6e8a17856Owen Anderson  llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
75120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      Elements);
75220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.clear();
75320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(NULLPtr);
7544a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson  Elements.push_back(llvm::ConstantInt::get(LongTy, Protocols.size()));
75520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(ProtocolArray);
75620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list");
75720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
75820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
7591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpllvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder,
760af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar                                            const ObjCProtocolDecl *PD) {
761f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  llvm::Value *protocol = ExistingProtocols[PD->getNameAsString()];
7621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const llvm::Type *T =
763f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian    CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType());
76496e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson  return Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
765f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian}
766f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian
767f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanianllvm::Constant *CGObjCGNU::GenerateEmptyProtocol(
768f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  const std::string &ProtocolName) {
769f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  llvm::SmallVector<std::string, 0> EmptyStringVector;
770f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  llvm::SmallVector<llvm::Constant*, 0> EmptyConstantVector;
771f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian
772f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  llvm::Constant *ProtocolList = GenerateProtocolList(EmptyStringVector);
773d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *MethodList =
774f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian    GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector);
775f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  // Protocols are objects containing lists of the methods implemented and
776f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  // protocols adopted.
77747a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy,
778f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian      PtrToInt8Ty,
779f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian      ProtocolList->getType(),
780d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      MethodList->getType(),
781d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      MethodList->getType(),
782d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      MethodList->getType(),
783d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      MethodList->getType(),
784f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian      NULL);
7851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  std::vector<llvm::Constant*> Elements;
786f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  // The isa pointer must be set to a magic number so the runtime knows it's
787f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  // the correct layout.
788d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ?
789d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      NonFragileProtocolVersion : ProtocolVersion;
7903c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson  Elements.push_back(llvm::ConstantExpr::getIntToPtr(
791d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy));
792f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
793f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  Elements.push_back(ProtocolList);
794d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(MethodList);
795d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(MethodList);
796d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(MethodList);
797d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(MethodList);
798f8c4f5469d7db591eeacfc3381d91f773fb7af43Fariborz Jahanian  return MakeGlobal(ProtocolTy, Elements, ".objc_protocol");
79920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
80020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
801af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbarvoid CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
802af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar  ASTContext &Context = CGM.getContext();
8038ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner  std::string ProtocolName = PD->getNameAsString();
804af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar  llvm::SmallVector<std::string, 16> Protocols;
805af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar  for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(),
806af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar       E = PD->protocol_end(); PI != E; ++PI)
807d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner    Protocols.push_back((*PI)->getNameAsString());
808af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar  llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames;
809af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar  llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
810d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodNames;
811d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodTypes;
81217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis  for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(),
81317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis       E = PD->instmeth_end(); iter != E; iter++) {
814af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar    std::string TypeStr;
815af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar    Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
816d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) {
817d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      InstanceMethodNames.push_back(
818d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          MakeConstantString((*iter)->getSelector().getAsString()));
819d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
820d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    } else {
821d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      OptionalInstanceMethodNames.push_back(
822d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          MakeConstantString((*iter)->getSelector().getAsString()));
823d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      OptionalInstanceMethodTypes.push_back(MakeConstantString(TypeStr));
824d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    }
825af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar  }
826af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar  // Collect information about class methods:
827af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar  llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames;
828af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar  llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
829d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodNames;
830d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodTypes;
8311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  for (ObjCProtocolDecl::classmeth_iterator
83217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis         iter = PD->classmeth_begin(), endIter = PD->classmeth_end();
83317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis       iter != endIter ; iter++) {
834af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar    std::string TypeStr;
835af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar    Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
836d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) {
837d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      ClassMethodNames.push_back(
838d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          MakeConstantString((*iter)->getSelector().getAsString()));
839d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      ClassMethodTypes.push_back(MakeConstantString(TypeStr));
840d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    } else {
841d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      OptionalClassMethodNames.push_back(
842d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          MakeConstantString((*iter)->getSelector().getAsString()));
843d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      OptionalClassMethodTypes.push_back(MakeConstantString(TypeStr));
844d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    }
845af2f62ce32e462f256855cd24b06dec4755d2827Daniel Dunbar  }
84620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
84720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
84820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *InstanceMethodList =
84920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes);
85020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *ClassMethodList =
85120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes);
852d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *OptionalInstanceMethodList =
853d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    GenerateProtocolMethodList(OptionalInstanceMethodNames,
854d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian            OptionalInstanceMethodTypes);
855d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *OptionalClassMethodList =
856d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    GenerateProtocolMethodList(OptionalClassMethodNames,
857d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian            OptionalClassMethodTypes);
858d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
859d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // Property metadata: name, attributes, isSynthesized, setter name, setter
860d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // types, getter name, getter types.
861d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // The isSynthesized value is always set to 0 in a protocol.  It exists to
862d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // simplify the runtime library by allowing it to use the same data
863d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // structures for protocol metadata everywhere.
864d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext,
865d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty,
866d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          PtrToInt8Ty, NULL);
867d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  std::vector<llvm::Constant*> Properties;
868d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  std::vector<llvm::Constant*> OptionalProperties;
869d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
870d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // Add all of the property methods need adding to the method list and to the
871d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // property metadata list.
872d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  for (ObjCContainerDecl::prop_iterator
873d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian         iter = PD->prop_begin(), endIter = PD->prop_end();
874d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian       iter != endIter ; iter++) {
875d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    std::vector<llvm::Constant*> Fields;
876d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    ObjCPropertyDecl *property = (*iter);
877d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
878d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Fields.push_back(MakeConstantString(property->getNameAsString()));
879d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Fields.push_back(llvm::ConstantInt::get(Int8Ty,
880d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian                property->getPropertyAttributes()));
881d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0));
882d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
883d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      std::string TypeStr;
884d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Context.getObjCEncodingForMethodDecl(getter,TypeStr);
885d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
886d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      InstanceMethodTypes.push_back(TypeEncoding);
887d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
888d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(TypeEncoding);
889d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    } else {
890d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(NULLPtr);
891d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(NULLPtr);
892d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    }
893d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
894d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      std::string TypeStr;
895d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Context.getObjCEncodingForMethodDecl(setter,TypeStr);
896d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
897d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      InstanceMethodTypes.push_back(TypeEncoding);
898d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
899d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(TypeEncoding);
900d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    } else {
901d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(NULLPtr);
902d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(NULLPtr);
903d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    }
904d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    if (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) {
905d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      OptionalProperties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
906d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    } else {
907d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
908d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    }
909d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  }
910d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *PropertyArray = llvm::ConstantArray::get(
911d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::ArrayType::get(PropertyMetadataTy, Properties.size()), Properties);
912d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant* PropertyListInitFields[] =
913d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
914d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
915d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *PropertyListInit =
916d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3);
917d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *PropertyList = new llvm::GlobalVariable(TheModule,
918d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      PropertyListInit->getType(), false, llvm::GlobalValue::InternalLinkage,
919d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      PropertyListInit, ".objc_property_list");
920d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
921d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *OptionalPropertyArray =
922d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::ConstantArray::get(llvm::ArrayType::get(PropertyMetadataTy,
923d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          OptionalProperties.size()) , OptionalProperties);
924d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant* OptionalPropertyListInitFields[] = {
925d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::ConstantInt::get(IntTy, OptionalProperties.size()), NULLPtr,
926d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      OptionalPropertyArray };
927d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
928d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *OptionalPropertyListInit =
929d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::ConstantStruct::get(VMContext, OptionalPropertyListInitFields, 3);
930d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *OptionalPropertyList = new llvm::GlobalVariable(TheModule,
931d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          OptionalPropertyListInit->getType(), false,
932d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          llvm::GlobalValue::InternalLinkage, OptionalPropertyListInit,
933d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          ".objc_property_list");
934d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
93520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Protocols are objects containing lists of the methods implemented and
93620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // protocols adopted.
93747a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy,
93820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      PtrToInt8Ty,
93920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      ProtocolList->getType(),
94020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      InstanceMethodList->getType(),
94120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      ClassMethodList->getType(),
942d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      OptionalInstanceMethodList->getType(),
943d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      OptionalClassMethodList->getType(),
944d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      PropertyList->getType(),
945d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      OptionalPropertyList->getType(),
94620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      NULL);
9471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  std::vector<llvm::Constant*> Elements;
94820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // The isa pointer must be set to a magic number so the runtime knows it's
94920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // the correct layout.
950d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ?
951d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      NonFragileProtocolVersion : ProtocolVersion;
9523c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson  Elements.push_back(llvm::ConstantExpr::getIntToPtr(
953d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy));
95420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
95520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(ProtocolList);
95620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(InstanceMethodList);
95720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(ClassMethodList);
958d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(OptionalInstanceMethodList);
959d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(OptionalClassMethodList);
960d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(PropertyList);
961d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(OptionalPropertyList);
9621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ExistingProtocols[ProtocolName] =
9633c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson    llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
96420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov          ".objc_protocol"), IdTy);
96520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
966d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanianvoid CGObjCGNU::GenerateProtocolHolderCategory(void) {
967d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // Collect information about instance methods
968d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::SmallVector<Selector, 1> MethodSels;
969d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::SmallVector<llvm::Constant*, 1> MethodTypes;
970d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
971d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  std::vector<llvm::Constant*> Elements;
972d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack";
973d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  const std::string CategoryName = "AnotherHack";
974d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(MakeConstantString(CategoryName));
975d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(MakeConstantString(ClassName));
976d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // Instance method list
977d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
978d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy));
979d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // Class method list
980d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
981d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy));
982d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // Protocol list
983d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrTy,
984d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      ExistingProtocols.size());
985d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext,
986d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      PtrTy, //Should be a recurisve pointer, but it's always NULL here.
987d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      LongTy,//FIXME: Should be size_t
988d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      ProtocolArrayTy,
989d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      NULL);
990d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  std::vector<llvm::Constant*> ProtocolElements;
991d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  for (llvm::StringMapIterator<llvm::Constant*> iter =
992d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian       ExistingProtocols.begin(), endIter = ExistingProtocols.end();
993d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian       iter != endIter ; iter++) {
994d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(iter->getValue(),
995d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian            PtrTy);
996d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    ProtocolElements.push_back(Ptr);
997d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  }
998d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
999d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      ProtocolElements);
1000d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  ProtocolElements.clear();
1001d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  ProtocolElements.push_back(NULLPtr);
1002d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  ProtocolElements.push_back(llvm::ConstantInt::get(LongTy,
1003d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian              ExistingProtocols.size()));
1004d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  ProtocolElements.push_back(ProtocolArray);
1005d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Elements.push_back(llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolListTy,
1006d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian                  ProtocolElements, ".objc_protocol_list"), PtrTy));
1007d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  Categories.push_back(llvm::ConstantExpr::getBitCast(
1008d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty,
1009d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian            PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy));
1010d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian}
101120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
10127ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbarvoid CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
10138ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner  std::string ClassName = OCD->getClassInterface()->getNameAsString();
10148ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner  std::string CategoryName = OCD->getNameAsString();
10157ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  // Collect information about instance methods
10167ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<Selector, 16> InstanceMethodSels;
10177ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
1018653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor  for (ObjCCategoryImplDecl::instmeth_iterator
101917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis         iter = OCD->instmeth_begin(), endIter = OCD->instmeth_end();
1020653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor       iter != endIter ; iter++) {
10217ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    InstanceMethodSels.push_back((*iter)->getSelector());
10227ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    std::string TypeStr;
10237ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
10248a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
10257ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  }
10267ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
10277ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  // Collect information about class methods
10287ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<Selector, 16> ClassMethodSels;
10297ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
10301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  for (ObjCCategoryImplDecl::classmeth_iterator
103117945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis         iter = OCD->classmeth_begin(), endIter = OCD->classmeth_end();
1032653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor       iter != endIter ; iter++) {
10337ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    ClassMethodSels.push_back((*iter)->getSelector());
10347ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    std::string TypeStr;
10357ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
10368a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    ClassMethodTypes.push_back(MakeConstantString(TypeStr));
10377ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  }
10387ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
10397ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  // Collect the names of referenced protocols
10407ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<std::string, 16> Protocols;
10417ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  const ObjCInterfaceDecl *ClassDecl = OCD->getClassInterface();
10427ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
10437ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
10447ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar       E = Protos.end(); I != E; ++I)
1045d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner    Protocols.push_back((*I)->getNameAsString());
10467ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
104720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Elements;
104820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(MakeConstantString(CategoryName));
104920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(MakeConstantString(ClassName));
10501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Instance method list
10513c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson  Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
1052a4210076fc1d7ac0a20b8b4a79e18a8ae33b9c69Chris Lattner          ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes,
105320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov          false), PtrTy));
105420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Class method list
10553c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson  Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
1056a4210076fc1d7ac0a20b8b4a79e18a8ae33b9c69Chris Lattner          ClassName, CategoryName, ClassMethodSels, ClassMethodTypes, true),
105720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov        PtrTy));
105820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Protocol list
10593c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson  Elements.push_back(llvm::ConstantExpr::getBitCast(
106020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov        GenerateProtocolList(Protocols), PtrTy));
10613c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson  Categories.push_back(llvm::ConstantExpr::getBitCast(
10621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty,
106347a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson            PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy));
106420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
10657ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
1066d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanianllvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OID,
1067d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
1068d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes) {
1069d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  ASTContext &Context = CGM.getContext();
1070d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  //
1071d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // Property metadata: name, attributes, isSynthesized, setter name, setter
1072d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // types, getter name, getter types.
1073d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext,
1074d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty,
1075d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          PtrToInt8Ty, NULL);
1076d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  std::vector<llvm::Constant*> Properties;
1077d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
1078d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
1079d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // Add all of the property methods need adding to the method list and to the
1080d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // property metadata list.
1081d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  for (ObjCImplDecl::propimpl_iterator
1082d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian         iter = OID->propimpl_begin(), endIter = OID->propimpl_end();
1083d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian       iter != endIter ; iter++) {
1084d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    std::vector<llvm::Constant*> Fields;
1085d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    ObjCPropertyDecl *property = (*iter)->getPropertyDecl();
1086d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
1087d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Fields.push_back(MakeConstantString(property->getNameAsString()));
1088d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Fields.push_back(llvm::ConstantInt::get(Int8Ty,
1089d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian                property->getPropertyAttributes()));
1090d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Fields.push_back(llvm::ConstantInt::get(Int8Ty,
1091d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian                (*iter)->getPropertyImplementation() ==
1092d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian                ObjCPropertyImplDecl::Synthesize));
1093d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
1094d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      InstanceMethodSels.push_back(getter->getSelector());
1095d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      std::string TypeStr;
1096d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Context.getObjCEncodingForMethodDecl(getter,TypeStr);
1097d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
1098d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      InstanceMethodTypes.push_back(TypeEncoding);
1099d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
1100d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(TypeEncoding);
1101d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    } else {
1102d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(NULLPtr);
1103d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(NULLPtr);
1104d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    }
1105d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
1106d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      InstanceMethodSels.push_back(setter->getSelector());
1107d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      std::string TypeStr;
1108d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Context.getObjCEncodingForMethodDecl(setter,TypeStr);
1109d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
1110d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      InstanceMethodTypes.push_back(TypeEncoding);
1111d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
1112d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(TypeEncoding);
1113d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    } else {
1114d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(NULLPtr);
1115d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Fields.push_back(NULLPtr);
1116d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    }
1117d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
1118d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  }
1119d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::ArrayType *PropertyArrayTy =
1120d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::ArrayType::get(PropertyMetadataTy, Properties.size());
1121d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *PropertyArray = llvm::ConstantArray::get(PropertyArrayTy,
1122d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          Properties);
1123d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant* PropertyListInitFields[] =
1124d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
1125d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
1126d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *PropertyListInit =
1127d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3);
1128d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  return new llvm::GlobalVariable(TheModule, PropertyListInit->getType(), false,
1129d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          llvm::GlobalValue::InternalLinkage, PropertyListInit,
1130d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          ".objc_property_list");
1131d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian}
1132d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
11337ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbarvoid CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
11347ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  ASTContext &Context = CGM.getContext();
11357ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
11367ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  // Get the superclass name.
11371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const ObjCInterfaceDecl * SuperClassDecl =
11387ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    OID->getClassInterface()->getSuperClass();
11398ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner  std::string SuperClassName;
11402a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  if (SuperClassDecl) {
11418ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner    SuperClassName = SuperClassDecl->getNameAsString();
11422a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner    EmitClassRef(SuperClassName);
11432a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  }
11447ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
11457ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  // Get the class name
114609dc6660487fc2f4a4bb2032e30123d3e0da7230Chris Lattner  ObjCInterfaceDecl *ClassDecl =
114709dc6660487fc2f4a4bb2032e30123d3e0da7230Chris Lattner    const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
11488ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner  std::string ClassName = ClassDecl->getNameAsString();
11492a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  // Emit the symbol that is used to generate linker errors if this class is
11502a8e4e1d8548dc3e30d7c9ba92127c7884a11448Chris Lattner  // referenced in other modules but not declared.
1151c51db23f58bd887b16cf91554aa86c430a2496e7Fariborz Jahanian  std::string classSymbolName = "__objc_class_name_" + ClassName;
11521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (llvm::GlobalVariable *symbol =
1153c51db23f58bd887b16cf91554aa86c430a2496e7Fariborz Jahanian      TheModule.getGlobalVariable(classSymbolName)) {
11544a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson    symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0));
1155c51db23f58bd887b16cf91554aa86c430a2496e7Fariborz Jahanian  } else {
11561c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson    new llvm::GlobalVariable(TheModule, LongTy, false,
11574a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson    llvm::GlobalValue::ExternalLinkage, llvm::ConstantInt::get(LongTy, 0),
11581c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson    classSymbolName);
1159c51db23f58bd887b16cf91554aa86c430a2496e7Fariborz Jahanian  }
11601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11612bebbf0acee55404de4b8846713b64429e744e8fDaniel Dunbar  // Get the size of instances.
11622bebbf0acee55404de4b8846713b64429e744e8fDaniel Dunbar  int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8;
11637ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
11647ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  // Collect information about instance variables.
11657ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<llvm::Constant*, 16> IvarNames;
11667ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<llvm::Constant*, 16> IvarTypes;
11677ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<llvm::Constant*, 16> IvarOffsets;
11681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1169d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  std::vector<llvm::Constant*> IvarOffsetValues;
1170d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
11711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  int superInstanceSize = !SuperClassDecl ? 0 :
11729cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian    Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize() / 8;
11739cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  // For non-fragile ivars, set the instance size to 0 - {the size of just this
11749cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  // class}.  The runtime will then set this to the correct value on load.
11759cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
11769cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian    instanceSize = 0 - (instanceSize - superInstanceSize);
11779cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  }
11787ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
11797ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar      endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
11807ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar      // Store the name
11818a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      IvarNames.push_back(MakeConstantString((*iter)->getNameAsString()));
11827ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar      // Get the type encoding for this ivar
11837ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar      std::string TypeStr;
11840d504c1da852e58ff802545c823ecff3b6c654b8Daniel Dunbar      Context.getObjCEncodingForType((*iter)->getType(), TypeStr);
11858a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      IvarTypes.push_back(MakeConstantString(TypeStr));
11867ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar      // Get the offset
11879cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian      uint64_t Offset;
1188d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, ClassDecl, *iter);
11899cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian      if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
1190d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        Offset = BaseOffset - superInstanceSize;
11919cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian      }
11927ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar      IvarOffsets.push_back(
11930032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson          llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset));
1194d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      IvarOffsetValues.push_back(new llvm::GlobalVariable(TheModule, IntTy,
1195d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          false, llvm::GlobalValue::ExternalLinkage,
1196d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          llvm::ConstantInt::get(IntTy, BaseOffset),
1197d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          "__objc_ivar_offset_value_" + ClassName +"." +
1198d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          (*iter)->getNameAsString()));
11997ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  }
1200d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *IvarOffsetArrayInit =
1201d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      llvm::ConstantArray::get(llvm::ArrayType::get(PtrToIntTy,
1202d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian                  IvarOffsetValues.size()), IvarOffsetValues);
1203d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::GlobalVariable *IvarOffsetArray = new llvm::GlobalVariable(TheModule,
1204d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          IvarOffsetArrayInit->getType(), false,
1205d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          llvm::GlobalValue::InternalLinkage, IvarOffsetArrayInit,
1206d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          ".ivar.offsets");
12077ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
12087ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  // Collect information about instance methods
12097ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<Selector, 16> InstanceMethodSels;
12107ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
12111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  for (ObjCImplementationDecl::instmeth_iterator
121217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis         iter = OID->instmeth_begin(), endIter = OID->instmeth_end();
1213653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor       iter != endIter ; iter++) {
12147ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    InstanceMethodSels.push_back((*iter)->getSelector());
12157ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    std::string TypeStr;
12167ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
12178a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
12187ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  }
1219d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
1220d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Constant *Properties = GeneratePropertyList(OID, InstanceMethodSels,
1221d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian          InstanceMethodTypes);
1222d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
12237ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
12247ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  // Collect information about class methods
12257ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<Selector, 16> ClassMethodSels;
12267ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
1227653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor  for (ObjCImplementationDecl::classmeth_iterator
122817945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis         iter = OID->classmeth_begin(), endIter = OID->classmeth_end();
1229653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor       iter != endIter ; iter++) {
12307ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    ClassMethodSels.push_back((*iter)->getSelector());
12317ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    std::string TypeStr;
12327ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar    Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
12338a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    ClassMethodTypes.push_back(MakeConstantString(TypeStr));
12347ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  }
12357ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  // Collect the names of referenced protocols
12367ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  llvm::SmallVector<std::string, 16> Protocols;
12377ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
12387ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar  for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
12397ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar       E = Protos.end(); I != E; ++I)
1240d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner    Protocols.push_back((*I)->getNameAsString());
12417ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
12427ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
12437ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
124420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Get the superclass pointer.
124520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *SuperClass;
12468ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner  if (!SuperClassName.empty()) {
124720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    SuperClass = MakeConstantString(SuperClassName, ".super_class_name");
124820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  } else {
124903e205031b08669f05c41eed5b896fc94c4a12bbOwen Anderson    SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty);
125020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  }
125120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Empty vector used to construct empty method lists
125220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::SmallVector<llvm::Constant*, 1>  empty;
125320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Generate the method and instance variable lists
125420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
1255a4210076fc1d7ac0a20b8b4a79e18a8ae33b9c69Chris Lattner      InstanceMethodSels, InstanceMethodTypes, false);
125620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
1257a4210076fc1d7ac0a20b8b4a79e18a8ae33b9c69Chris Lattner      ClassMethodSels, ClassMethodTypes, true);
125820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
125920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      IvarOffsets);
12601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Irrespective of whether we are compiling for a fragile or non-fragile ABI,
12618a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  // we emit a symbol containing the offset for each ivar in the class.  This
12628a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  // allows code compiled for the non-Fragile ABI to inherit from code compiled
12638a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  // for the legacy ABI, without causing problems.  The converse is also
12648a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  // possible, but causes all ivar accesses to be fragile.
12658a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  int i = 0;
12668a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  // Offset pointer for getting at the correct field in the ivar list when
12678a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  // setting up the alias.  These are: The base address for the global, the
12688a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  // ivar array (second field), the ivar in this list (set for each ivar), and
12698a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  // the offset (third field in ivar structure)
12708a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  const llvm::Type *IndexTy = llvm::Type::getInt32Ty(VMContext);
12718a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
12721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      llvm::ConstantInt::get(IndexTy, 1), 0,
12738a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      llvm::ConstantInt::get(IndexTy, 2) };
12748a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall
12758a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
12768a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
12778a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      const std::string Name = "__objc_ivar_offset_" + ClassName + '.'
12788a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall          +(*iter)->getNameAsString();
12798a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, i++);
12808a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      // Get the correct ivar field
12818a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
12828a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall              IvarList, offsetPointerIndexes, 4);
12838a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      // Get the existing alias, if one exists.
12848a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
12858a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      if (offset) {
12868a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall          offset->setInitializer(offsetValue);
12878a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall          // If this is the real definition, change its linkage type so that
12888a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall          // different modules will use this one, rather than their private
12898a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall          // copy.
12908a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall          offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
12918a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      } else {
12928a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall          // Add a new alias if there isn't one already.
12938a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall          offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(),
12948a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall                  false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
12958a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      }
12968a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  }
129720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  //Generate metaclass for class methods
129820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
1299d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      NULLPtr, 0x12L, /*name*/"", 0, Zeros[0], GenerateIvarList(
1300d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr, NULLPtr);
13015efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar
130220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Generate the class structure
13038ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner  llvm::Constant *ClassStruct =
1304d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    GenerateClassStructure(MetaClassStruct, SuperClass, 0x11L,
13058ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner                           ClassName.c_str(), 0,
13064a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson      llvm::ConstantInt::get(LongTy, instanceSize), IvarList,
1307d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      MethodList, GenerateProtocolList(Protocols), IvarOffsetArray,
1308d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian      Properties);
13095efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar
13105efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  // Resolve the class aliases, if they exist.
13115efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  if (ClassPtrAlias) {
13125efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar    ClassPtrAlias->setAliasee(
13133c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson        llvm::ConstantExpr::getBitCast(ClassStruct, IdTy));
13145efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar    ClassPtrAlias = 0;
13155efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  }
13165efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  if (MetaClassPtrAlias) {
13175efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar    MetaClassPtrAlias->setAliasee(
13183c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson        llvm::ConstantExpr::getBitCast(MetaClassStruct, IdTy));
13195efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar    MetaClassPtrAlias = 0;
13205efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar  }
13215efccb1ab81a029ddeb3ea18e239d0ddc124ec2bDaniel Dunbar
132220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Add class structure to list to be added to the symtab later
13233c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson  ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty);
132420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Classes.push_back(ClassStruct);
132520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
132620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
1327c38e9affd4519ea199af22419c8c794973cc4b23Fariborz Jahanian
13281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpllvm::Function *CGObjCGNU::ModuleInitFunction() {
132920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Only emit an ObjC load function if no Objective-C stuff has been called
133020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
133120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      ExistingProtocols.empty() && TypedSelectors.empty() &&
13325f58b911304f7d114f929d1726a09cd1c828a5ddAnton Korobeynikov      UntypedSelectors.empty())
133320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    return NULL;
13341b8956e1ce4c5770982d6e59edb16979b500677aEli Friedman
1335d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  // Add all referenced protocols to a category.
1336d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  GenerateProtocolHolderCategory();
1337d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian
1338e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  const llvm::StructType *SelStructTy = dyn_cast<llvm::StructType>(
1339e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner          SelectorTy->getElementType());
1340e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  const llvm::Type *SelStructPtrTy = SelectorTy;
1341e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  bool isSelOpaque = false;
1342e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  if (SelStructTy == 0) {
134347a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson    SelStructTy = llvm::StructType::get(VMContext, PtrToInt8Ty,
134447a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson                                        PtrToInt8Ty, NULL);
134596e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson    SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy);
1346e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner    isSelOpaque = true;
1347e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  }
1348e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner
13491b8956e1ce4c5770982d6e59edb16979b500677aEli Friedman  // Name the ObjC types to make the IR a bit easier to read
1350e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner  TheModule.addTypeName(".objc_selector", SelStructPtrTy);
13511b8956e1ce4c5770982d6e59edb16979b500677aEli Friedman  TheModule.addTypeName(".objc_id", IdTy);
13521b8956e1ce4c5770982d6e59edb16979b500677aEli Friedman  TheModule.addTypeName(".objc_imp", IMPTy);
13531b8956e1ce4c5770982d6e59edb16979b500677aEli Friedman
135420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Elements;
135571238f67c5df13eef19450d66b7a7ab28377192aChris Lattner  llvm::Constant *Statics = NULLPtr;
135620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Generate statics list:
135771238f67c5df13eef19450d66b7a7ab28377192aChris Lattner  if (ConstantStrings.size()) {
135896e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson    llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
135971238f67c5df13eef19450d66b7a7ab28377192aChris Lattner        ConstantStrings.size() + 1);
136071238f67c5df13eef19450d66b7a7ab28377192aChris Lattner    ConstantStrings.push_back(NULLPtr);
13618a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall
13628a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    const char *StringClass = CGM.getLangOptions().ObjCConstantStringClass;
13638a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    if (!StringClass) StringClass = "NXConstantString";
13648a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    Elements.push_back(MakeConstantString(StringClass,
13658a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall                ".objc_static_class_name"));
13667db6d838aad4083fe86d7bf703a75fe6e8a17856Owen Anderson    Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy,
136771238f67c5df13eef19450d66b7a7ab28377192aChris Lattner       ConstantStrings));
13681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    llvm::StructType *StaticsListTy =
136947a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson      llvm::StructType::get(VMContext, PtrToInt8Ty, StaticsArrayTy, NULL);
1370a1cf15f4680e5cf39e72e28c5ea854fcba792e84Owen Anderson    llvm::Type *StaticsListPtrTy =
137196e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson      llvm::PointerType::getUnqual(StaticsListTy);
137271238f67c5df13eef19450d66b7a7ab28377192aChris Lattner    Statics = MakeGlobal(StaticsListTy, Elements, ".objc_statics");
13731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    llvm::ArrayType *StaticsListArrayTy =
137496e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson      llvm::ArrayType::get(StaticsListPtrTy, 2);
137571238f67c5df13eef19450d66b7a7ab28377192aChris Lattner    Elements.clear();
137671238f67c5df13eef19450d66b7a7ab28377192aChris Lattner    Elements.push_back(Statics);
1377c9c88b4159791c48e486ca94e3743b5979e2b7a6Owen Anderson    Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
137871238f67c5df13eef19450d66b7a7ab28377192aChris Lattner    Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr");
13793c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson    Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
138071238f67c5df13eef19450d66b7a7ab28377192aChris Lattner  }
138120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Array of classes, categories, and constant objects
138296e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson  llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty,
138320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      Classes.size() + Categories.size()  + 2);
13841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  llvm::StructType *SymTabTy = llvm::StructType::get(VMContext,
138547a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson                                                     LongTy, SelStructPtrTy,
13860032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson                                                     llvm::Type::getInt16Ty(VMContext),
13870032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson                                                     llvm::Type::getInt16Ty(VMContext),
1388630404b16e886238ed68a1abbfe2e548f43aa664Chris Lattner                                                     ClassListTy, NULL);
138920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
139020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.clear();
139120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Pointer to an array of selectors used in this module.
139220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::vector<llvm::Constant*> Selectors;
139320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
139420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov     iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end();
139520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov     iter != iterEnd ; ++iter) {
1396d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Elements.push_back(ExportUniqueString(iter->first.first, ".objc_sel_name"));
1397d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian    Elements.push_back(ExportUniqueString(iter->first.second,
1398630404b16e886238ed68a1abbfe2e548f43aa664Chris Lattner                                          ".objc_sel_types"));
139908e252425ca2cbdc44ba65d9a657ed5398014e36Owen Anderson    Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
140020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    Elements.clear();
140120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  }
140220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  for (llvm::StringMap<llvm::GlobalAlias*>::iterator
140320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
1404630404b16e886238ed68a1abbfe2e548f43aa664Chris Lattner      iter != iterEnd; ++iter) {
140520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    Elements.push_back(
1406d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        ExportUniqueString(iter->getKeyData(), ".objc_sel_name"));
140720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    Elements.push_back(NULLPtr);
140808e252425ca2cbdc44ba65d9a657ed5398014e36Owen Anderson    Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
140920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    Elements.clear();
141020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  }
141120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(NULLPtr);
141220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(NULLPtr);
141308e252425ca2cbdc44ba65d9a657ed5398014e36Owen Anderson  Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
141420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.clear();
141520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Number of static selectors
14164a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson  Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() ));
141720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *SelectorList = MakeGlobal(
141896e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson          llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors,
141920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov          ".objc_selector_list");
14201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList,
1421e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner    SelStructPtrTy));
142220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
142320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Now that all of the static selectors exist, create pointers to them.
142420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  int index = 0;
142520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
142620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov     iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end();
142720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov     iter != iterEnd; ++iter) {
142820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    llvm::Constant *Idxs[] = {Zeros[0],
14290032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson      llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]};
14301c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson    llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy,
14311c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson        true, llvm::GlobalValue::InternalLinkage,
14323c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson        llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
14331c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson        ".objc_sel_ptr");
1434e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner    // If selectors are defined as an opaque type, cast the pointer to this
1435e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner    // type.
1436e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner    if (isSelOpaque) {
14373c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson      SelPtr = llvm::ConstantExpr::getBitCast(SelPtr,
143896e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson        llvm::PointerType::getUnqual(SelectorTy));
1439e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner    }
144020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    (*iter).second->setAliasee(SelPtr);
144120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  }
144220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  for (llvm::StringMap<llvm::GlobalAlias*>::iterator
144320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
144420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      iter != iterEnd; iter++) {
144520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    llvm::Constant *Idxs[] = {Zeros[0],
14460032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson      llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]};
1447bb1c8600218b3244340331165fc7cba7bf227655Mike Stump    llvm::Constant *SelPtr = new llvm::GlobalVariable
14481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      (TheModule, SelStructPtrTy,
1449bb1c8600218b3244340331165fc7cba7bf227655Mike Stump       true, llvm::GlobalValue::InternalLinkage,
1450bb1c8600218b3244340331165fc7cba7bf227655Mike Stump       llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
1451bb1c8600218b3244340331165fc7cba7bf227655Mike Stump       ".objc_sel_ptr");
1452e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner    // If selectors are defined as an opaque type, cast the pointer to this
1453e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner    // type.
1454e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner    if (isSelOpaque) {
14553c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson      SelPtr = llvm::ConstantExpr::getBitCast(SelPtr,
145696e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson        llvm::PointerType::getUnqual(SelectorTy));
1457e160c9b09d2f5098dfdcca99b9c6485487e0c252Chris Lattner    }
145820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov    (*iter).second->setAliasee(SelPtr);
145920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  }
146020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Number of classes defined.
14611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext),
146220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov        Classes.size()));
146320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Number of categories defined
14641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext),
146520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov        Categories.size()));
146620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Create an array of classes, then categories, then static object instances
146720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Classes.insert(Classes.end(), Categories.begin(), Categories.end());
146820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  //  NULL-terminated list of static object instances (mainly constant strings)
146920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Classes.push_back(Statics);
147020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Classes.push_back(NULLPtr);
14717db6d838aad4083fe86d7bf703a75fe6e8a17856Owen Anderson  llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes);
147220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(ClassList);
14731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Construct the symbol table
147420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements);
147520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
147620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // The symbol table is contained in a module which has some version-checking
147720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // constants
147847a434ff3d49e7906eda88e8e8242e4297725b32Owen Anderson  llvm::StructType * ModuleTy = llvm::StructType::get(VMContext, LongTy, LongTy,
147996e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson      PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL);
148020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.clear();
148120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Runtime version used for compatibility checking.
14829cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
14831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    Elements.push_back(llvm::ConstantInt::get(LongTy,
1484d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian        NonFragileRuntimeVersion));
14859cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  } else {
14864a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson    Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
14879cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  }
148891a0b51438e5259a79d68d7450c453827beed9e2Fariborz Jahanian  // sizeof(ModuleTy)
148991a0b51438e5259a79d68d7450c453827beed9e2Fariborz Jahanian  llvm::TargetData td = llvm::TargetData::TargetData(&TheModule);
14904a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson  Elements.push_back(llvm::ConstantInt::get(LongTy,
1491a1cf15f4680e5cf39e72e28c5ea854fcba792e84Owen Anderson                     td.getTypeSizeInBits(ModuleTy)/8));
149220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  //FIXME: Should be the path to the file where this module was declared
149320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(NULLPtr);
149420ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Elements.push_back(SymTab);
149520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Value *Module = MakeGlobal(ModuleTy, Elements);
149620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
149720ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // Create the load function calling the runtime entry point with the module
149820ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  // structure
149920ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  llvm::Function * LoadFunction = llvm::Function::Create(
15000032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
150120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      llvm::GlobalValue::InternalLinkage, ".objc_load_function",
150220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      &TheModule);
15030032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson  llvm::BasicBlock *EntryBB =
15040032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson      llvm::BasicBlock::Create(VMContext, "entry", LoadFunction);
1505a1cf15f4680e5cf39e72e28c5ea854fcba792e84Owen Anderson  CGBuilderTy Builder(VMContext);
150620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Builder.SetInsertPoint(EntryBB);
150726c8294dacc2efc83d8d560593ff863e7a32a48fFariborz Jahanian
150826c8294dacc2efc83d8d560593ff863e7a32a48fFariborz Jahanian  std::vector<const llvm::Type*> Params(1,
150996e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson      llvm::PointerType::getUnqual(ModuleTy));
151096e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson  llvm::Value *Register = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
15110032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson        llvm::Type::getVoidTy(VMContext), Params, true), "__objc_exec_class");
151220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Builder.CreateCall(Register, Module);
151320ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  Builder.CreateRetVoid();
15149cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian
151520ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  return LoadFunction;
151620ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov}
15177ded7f4983dc4a20561db7a8d02c6b2435030961Daniel Dunbar
1518679a502d462ef819e6175b58e255ca3f3391e7cfFariborz Jahanianllvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD,
15191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                          const ObjCContainerDecl *CD) {
15201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const ObjCCategoryImplDecl *OCD =
15213e0a540b6d846178857289ec0eb8470a278d11a3Steve Naroff    dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext());
1522077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner  std::string CategoryName = OCD ? OCD->getNameAsString() : "";
1523077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner  std::string ClassName = OMD->getClassInterface()->getNameAsString();
1524077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner  std::string MethodName = OMD->getSelector().getAsString();
1525f8d49f64ef6ab7e632717a31631fc289aab69428Douglas Gregor  bool isClassMethod = !OMD->isInstanceMethod();
1526391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner
1527541b63b1a9db77e4a8670e9823711c2c12e58afbDaniel Dunbar  CodeGenTypes &Types = CGM.getTypes();
15281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const llvm::FunctionType *MethodTy =
1529541b63b1a9db77e4a8670e9823711c2c12e58afbDaniel Dunbar    Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
153020ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov  std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
153120ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov      MethodName, isClassMethod);
153220ff3108fcd2c3bd734dc79efc22ebaa090abd41Anton Korobeynikov
1533d9a1db3a4ded1c8f0daa43c0d6167576e2766453Fariborz Jahanian  llvm::Function *Method
15341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    = llvm::Function::Create(MethodTy,
15351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                             llvm::GlobalValue::InternalLinkage,
15361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                             FunctionName,
15371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                             &TheModule);
1538391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner  return Method;
1539391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner}
1540391d77a26382dddf25da73e29fc1fa5aaaea4c6fChris Lattner
154149f6602707887eea1a558a1dffe0213102f887f2Daniel Dunbarllvm::Function *CGObjCGNU::GetPropertyGetFunction() {
15421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  std::vector<const llvm::Type*> Params;
15431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const llvm::Type *BoolTy =
15441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    CGM.getTypes().ConvertType(CGM.getContext().BoolTy);
15451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Params.push_back(IdTy);
15461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Params.push_back(SelectorTy);
15471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // FIXME: Using LongTy for ptrdiff_t is probably broken on Win64
15481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Params.push_back(LongTy);
15491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Params.push_back(BoolTy);
15501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // void objc_getProperty (id, SEL, ptrdiff_t, bool)
15511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const llvm::FunctionType *FTy =
15521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    llvm::FunctionType::get(IdTy, Params, false);
15531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
15541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                                        "objc_getProperty"));
155549f6602707887eea1a558a1dffe0213102f887f2Daniel Dunbar}
155649f6602707887eea1a558a1dffe0213102f887f2Daniel Dunbar
155749f6602707887eea1a558a1dffe0213102f887f2Daniel Dunbarllvm::Function *CGObjCGNU::GetPropertySetFunction() {
15581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  std::vector<const llvm::Type*> Params;
15591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const llvm::Type *BoolTy =
15601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    CGM.getTypes().ConvertType(CGM.getContext().BoolTy);
15611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Params.push_back(IdTy);
15621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Params.push_back(SelectorTy);
15631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // FIXME: Using LongTy for ptrdiff_t is probably broken on Win64
15641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Params.push_back(LongTy);
15651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Params.push_back(IdTy);
15661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Params.push_back(BoolTy);
15671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Params.push_back(BoolTy);
15681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
15691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const llvm::FunctionType *FTy =
15701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
15711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
15721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                                        "objc_setProperty"));
157349f6602707887eea1a558a1dffe0213102f887f2Daniel Dunbar}
157449f6602707887eea1a558a1dffe0213102f887f2Daniel Dunbar
1575309a4368cd299cff30ab22709e2b772cf8059e45Daniel Dunbarllvm::Constant *CGObjCGNU::EnumerationMutationFunction() {
1576309a4368cd299cff30ab22709e2b772cf8059e45Daniel Dunbar  CodeGen::CodeGenTypes &Types = CGM.getTypes();
1577309a4368cd299cff30ab22709e2b772cf8059e45Daniel Dunbar  ASTContext &Ctx = CGM.getContext();
1578309a4368cd299cff30ab22709e2b772cf8059e45Daniel Dunbar  // void objc_enumerationMutation (id)
1579309a4368cd299cff30ab22709e2b772cf8059e45Daniel Dunbar  llvm::SmallVector<QualType,16> Params;
15800f436560640a1cff5b6d96f80f540770f139453fDavid Chisnall  Params.push_back(ASTIdTy);
1581309a4368cd299cff30ab22709e2b772cf8059e45Daniel Dunbar  const llvm::FunctionType *FTy =
1582309a4368cd299cff30ab22709e2b772cf8059e45Daniel Dunbar    Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
1583309a4368cd299cff30ab22709e2b772cf8059e45Daniel Dunbar  return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
15842abd89c039e835e84519a4cd8a7495899a70153dAnders Carlsson}
15852abd89c039e835e84519a4cd8a7495899a70153dAnders Carlsson
1586bd71be4683c195260d5245118b1e13e6b2e20504Fariborz Jahanianvoid CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1587bd71be4683c195260d5245118b1e13e6b2e20504Fariborz Jahanian                                          const Stmt &S) {
15885dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // Pointer to the personality function
15895dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::Constant *Personality =
15900032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson    CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
1591b59761b2530bf54926bf67de11956f3820ac38d9Chris Lattner          true),
15925dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        "__gnu_objc_personality_v0");
15933c4972def972f8ca44dcd0561779a12aaa6fec97Owen Anderson  Personality = llvm::ConstantExpr::getBitCast(Personality, PtrTy);
15945dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  std::vector<const llvm::Type*> Params;
15955dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  Params.push_back(PtrTy);
15965dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::Value *RethrowFn =
15970032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson    CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
15985dc0867af17b3bd6f567897433853b2b4767446cChris Lattner          Params, false), "_Unwind_Resume_or_Rethrow");
15995dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16005dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  bool isTry = isa<ObjCAtTryStmt>(S);
16015dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
16025dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest();
16035dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
1604d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  llvm::BasicBlock *CatchInCatch = CGF.createBasicBlock("catch.rethrow");
16055dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
16065dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
16075dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
16085dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16095dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // GNU runtime does not currently support @synchronized()
16105dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  if (!isTry) {
1611d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner    std::vector<const llvm::Type*> Args(1, IdTy);
1612d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner    llvm::FunctionType *FTy =
16130032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
1614d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner    llvm::Value *SyncEnter = CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
16151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    llvm::Value *SyncArg =
1616d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner      CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
1617d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner    SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy);
1618d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner    CGF.Builder.CreateCall(SyncEnter, SyncArg);
16195dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  }
16205dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
1621d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner
16225dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // Push an EH context entry, used for handling rethrows and jumps
16235dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // through finally.
16245dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.PushCleanupBlock(FinallyBlock);
16255dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16265dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // Emit the statements in the @try {} block
16275dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.setInvokeDest(TryHandler);
16285dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16295dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.EmitBlock(TryBlock);
16301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
16315dc0867af17b3bd6f567897433853b2b4767446cChris Lattner                     : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
16325dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16335dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // Jump to @finally if there is no exception
16345dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.EmitBranchThroughCleanup(FinallyEnd);
16355dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16365dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // Emit the handlers
16375dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.EmitBlock(TryHandler);
16385dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
1639bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner  // Get the correct versions of the exception handling intrinsics
1640bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner  llvm::TargetData td = llvm::TargetData::TargetData(&TheModule);
1641bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner  int PointerWidth = td.getTypeSizeInBits(PtrTy);
1642bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner  assert((PointerWidth == 32 || PointerWidth == 64) &&
1643bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner    "Can't yet handle exceptions if pointers are not 32 or 64 bits");
16441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  llvm::Value *llvm_eh_exception =
16455dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
1646bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner  llvm::Value *llvm_eh_selector = PointerWidth == 32 ?
1647bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector_i32) :
1648bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector_i64);
1649bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner  llvm::Value *llvm_eh_typeid_for = PointerWidth == 32 ?
1650bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for_i32) :
1651bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for_i64);
16525dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16535dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // Exception object
16545dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
16555dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::Value *RethrowPtr = CGF.CreateTempAlloca(Exc->getType(), "_rethrow");
16565dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16575dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::SmallVector<llvm::Value*, 8> ESelArgs;
16585dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::SmallVector<std::pair<const ParmVarDecl*, const Stmt*>, 8> Handlers;
16595dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16605dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  ESelArgs.push_back(Exc);
16615dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  ESelArgs.push_back(Personality);
16625dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16635dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  bool HasCatchAll = false;
16645dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // Only @try blocks are allowed @catch blocks, but both can have @finally
16655dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  if (isTry) {
16665dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    if (const ObjCAtCatchStmt* CatchStmt =
16675dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      cast<ObjCAtTryStmt>(S).getCatchStmts())  {
1668d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner      CGF.setInvokeDest(CatchInCatch);
16695dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16705dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
16715dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        const ParmVarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
1672bb1c8600218b3244340331165fc7cba7bf227655Mike Stump        Handlers.push_back(std::make_pair(CatchDecl,
1673bb1c8600218b3244340331165fc7cba7bf227655Mike Stump                                          CatchStmt->getCatchBody()));
16745dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16755dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        // @catch() and @catch(id) both catch any ObjC exception
167614108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff        if (!CatchDecl || CatchDecl->getType()->isObjCIdType()
16775dc0867af17b3bd6f567897433853b2b4767446cChris Lattner            || CatchDecl->getType()->isObjCQualifiedIdType()) {
16785dc0867af17b3bd6f567897433853b2b4767446cChris Lattner          // Use i8* null here to signal this is a catch all, not a cleanup.
16795dc0867af17b3bd6f567897433853b2b4767446cChris Lattner          ESelArgs.push_back(NULLPtr);
16805dc0867af17b3bd6f567897433853b2b4767446cChris Lattner          HasCatchAll = true;
16815dc0867af17b3bd6f567897433853b2b4767446cChris Lattner          // No further catches after this one will ever by reached
16825dc0867af17b3bd6f567897433853b2b4767446cChris Lattner          break;
16831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        }
16845dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16855dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        // All other types should be Objective-C interface pointer types.
16861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        const ObjCObjectPointerType *OPT =
168714108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff          CatchDecl->getType()->getAsObjCObjectPointerType();
168814108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff        assert(OPT && "Invalid @catch type.");
16891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        const ObjCInterfaceType *IT =
169014108da7f7fc059772711e4ffee1322a27b152a7Steve Naroff          OPT->getPointeeType()->getAsObjCInterfaceType();
16915dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        assert(IT && "Invalid @catch type.");
1692bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner        llvm::Value *EHType =
1693bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner          MakeConstantString(IT->getDecl()->getNameAsString());
16945dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        ESelArgs.push_back(EHType);
16955dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      }
16965dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    }
16975dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  }
16985dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
16995dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // We use a cleanup unless there was already a catch all.
17005dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  if (!HasCatchAll) {
17010032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson    ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0));
17025dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0));
17035dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  }
17045dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17055dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // Find which handler was matched.
1706bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner  llvm::Value *ESelector = CGF.Builder.CreateCall(llvm_eh_selector,
17075dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      ESelArgs.begin(), ESelArgs.end(), "selector");
17085dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17095dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
17105dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    const ParmVarDecl *CatchParam = Handlers[i].first;
17115dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    const Stmt *CatchBody = Handlers[i].second;
17125dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17135dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    llvm::BasicBlock *Next = 0;
17145dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17155dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    // The last handler always matches.
17165dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    if (i + 1 != e) {
17175dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      assert(CatchParam && "Only last handler can be a catch all.");
17185dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17195dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      // Test whether this block matches the type for the selector and branch
17205dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      // to Match if it does, or to the next BB if it doesn't.
17215dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      llvm::BasicBlock *Match = CGF.createBasicBlock("match");
17225dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      Next = CGF.createBasicBlock("catch.next");
1723bb422ad4f449cd195a141309a886ff467baac5b2Chris Lattner      llvm::Value *Id = CGF.Builder.CreateCall(llvm_eh_typeid_for,
17245dc0867af17b3bd6f567897433853b2b4767446cChris Lattner          CGF.Builder.CreateBitCast(ESelArgs[i+2], PtrTy));
17255dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      CGF.Builder.CreateCondBr(CGF.Builder.CreateICmpEQ(ESelector, Id), Match,
17265dc0867af17b3bd6f567897433853b2b4767446cChris Lattner          Next);
17275dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17285dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      CGF.EmitBlock(Match);
17295dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    }
17301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
17315dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    if (CatchBody) {
17325dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      llvm::Value *ExcObject = CGF.Builder.CreateBitCast(Exc,
17335dc0867af17b3bd6f567897433853b2b4767446cChris Lattner          CGF.ConvertType(CatchParam->getType()));
17341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
17355dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      // Bind the catch parameter if it exists.
17365dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      if (CatchParam) {
17375dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        // CatchParam is a ParmVarDecl because of the grammar
17385dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        // construction used to handle this, but for codegen purposes
17395dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        // we treat this as a local decl.
17405dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        CGF.EmitLocalBlockVarDecl(*CatchParam);
17415dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(CatchParam));
17425dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      }
17435dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17445dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      CGF.ObjCEHValueStack.push_back(ExcObject);
17455dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      CGF.EmitStmt(CatchBody);
17465dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      CGF.ObjCEHValueStack.pop_back();
17475dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17485dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      CGF.EmitBranchThroughCleanup(FinallyEnd);
17495dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17505dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      if (Next)
17515dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        CGF.EmitBlock(Next);
17525dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    } else {
17535dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      assert(!Next && "catchup should be last handler.");
17545dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17555dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      CGF.Builder.CreateStore(Exc, RethrowPtr);
17565dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      CGF.EmitBranchThroughCleanup(FinallyRethrow);
17575dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    }
17585dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  }
1759d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  // The @finally block is a secondary landing pad for any exceptions thrown in
1760d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  // @catch() blocks
1761d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  CGF.EmitBlock(CatchInCatch);
1762d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
1763d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  ESelArgs.clear();
1764d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  ESelArgs.push_back(Exc);
1765d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  ESelArgs.push_back(Personality);
17660032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson  ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0));
1767d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  CGF.Builder.CreateCall(llvm_eh_selector, ESelArgs.begin(), ESelArgs.end(),
1768d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner      "selector");
1769d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  CGF.Builder.CreateCall(llvm_eh_typeid_for,
1770d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner      CGF.Builder.CreateIntToPtr(ESelArgs[2], PtrTy));
1771d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  CGF.Builder.CreateStore(Exc, RethrowPtr);
1772d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner  CGF.EmitBranchThroughCleanup(FinallyRethrow);
1773d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner
17745dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
17755dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17765dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.setInvokeDest(PrevLandingPad);
17775dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17785dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.EmitBlock(FinallyBlock);
17795dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
1780d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner
17815dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  if (isTry) {
17821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    if (const ObjCAtFinallyStmt* FinallyStmt =
17835dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        cast<ObjCAtTryStmt>(S).getFinallyStmt())
17845dc0867af17b3bd6f567897433853b2b4767446cChris Lattner      CGF.EmitStmt(FinallyStmt->getFinallyBody());
17855dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  } else {
1786d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner    // Emit 'objc_sync_exit(expr)' as finally's sole statement for
17875dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    // @synchronized.
1788d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner    std::vector<const llvm::Type*> Args(1, IdTy);
1789d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner    llvm::FunctionType *FTy =
17900032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
1791d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner    llvm::Value *SyncExit = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
17921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    llvm::Value *SyncArg =
1793d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner      CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
1794d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner    SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy);
1795d6a9907ceff2c52738a72e38b6a04ab44ce1173fChris Lattner    CGF.Builder.CreateCall(SyncExit, SyncArg);
17965dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  }
17975dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
17985dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  if (Info.SwitchBlock)
17995dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    CGF.EmitBlock(Info.SwitchBlock);
18005dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  if (Info.EndBlock)
18015dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    CGF.EmitBlock(Info.EndBlock);
18025dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
18035dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // Branch around the rethrow code.
18045dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.EmitBranch(FinallyEnd);
18055dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
18065dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.EmitBlock(FinallyRethrow);
18075dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.Builder.CreateCall(RethrowFn, CGF.Builder.CreateLoad(RethrowPtr));
18085dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.Builder.CreateUnreachable();
18091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18105dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.EmitBlock(FinallyEnd);
18115dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
181264d5d6c5903157c521af496479d06dc26032d718Anders Carlsson}
181364d5d6c5903157c521af496479d06dc26032d718Anders Carlsson
181464d5d6c5903157c521af496479d06dc26032d718Anders Carlssonvoid CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
181549f6602707887eea1a558a1dffe0213102f887f2Daniel Dunbar                              const ObjCAtThrowStmt &S) {
18165dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::Value *ExceptionAsObject;
18175dc0867af17b3bd6f567897433853b2b4767446cChris Lattner
18185dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  std::vector<const llvm::Type*> Args(1, IdTy);
18195dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::FunctionType *FTy =
18200032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson    llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
18211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  llvm::Value *ThrowFn =
18225dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
18231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18245dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  if (const Expr *ThrowExpr = S.getThrowExpr()) {
18255dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
18261e64a9531bf6e9d99ad3271b3a735ef702689b06Fariborz Jahanian    ExceptionAsObject = Exception;
18275dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  } else {
18281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
18295dc0867af17b3bd6f567897433853b2b4767446cChris Lattner           "Unexpected rethrow outside @catch block.");
18305dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    ExceptionAsObject = CGF.ObjCEHValueStack.back();
18315dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  }
18321e64a9531bf6e9d99ad3271b3a735ef702689b06Fariborz Jahanian  ExceptionAsObject =
18331e64a9531bf6e9d99ad3271b3a735ef702689b06Fariborz Jahanian      CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy, "tmp");
18341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18355dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // Note: This may have to be an invoke, if we want to support constructs like:
18365dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // @try {
18375dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  //  @throw(obj);
18385dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // }
18395dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // @catch(id) ...
18405dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  //
18415dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // This is effectively turning @throw into an incredibly-expensive goto, but
18425dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // it may happen as a result of inlining followed by missed optimizations, or
18435dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // as a result of stupidity.
18445dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  llvm::BasicBlock *UnwindBB = CGF.getInvokeDest();
18455dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  if (!UnwindBB) {
18465dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    CGF.Builder.CreateCall(ThrowFn, ExceptionAsObject);
18475dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    CGF.Builder.CreateUnreachable();
18485dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  } else {
18495dc0867af17b3bd6f567897433853b2b4767446cChris Lattner    CGF.Builder.CreateInvoke(ThrowFn, UnwindBB, UnwindBB, &ExceptionAsObject,
18505dc0867af17b3bd6f567897433853b2b4767446cChris Lattner        &ExceptionAsObject+1);
18515dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  }
18525dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  // Clear the insertion point to indicate we are in unreachable code.
18535dc0867af17b3bd6f567897433853b2b4767446cChris Lattner  CGF.Builder.ClearInsertionPoint();
185464d5d6c5903157c521af496479d06dc26032d718Anders Carlsson}
185564d5d6c5903157c521af496479d06dc26032d718Anders Carlsson
18563e283e344595e0bd499b13b30a92b7d9c10a2140Fariborz Jahanianllvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
18571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                          llvm::Value *AddrWeakObj) {
18586dc2317b59cb1180a59f6c283d96b7a5dfeb5307Fariborz Jahanian  return 0;
18596dc2317b59cb1180a59f6c283d96b7a5dfeb5307Fariborz Jahanian}
18606dc2317b59cb1180a59f6c283d96b7a5dfeb5307Fariborz Jahanian
18613e283e344595e0bd499b13b30a92b7d9c10a2140Fariborz Jahanianvoid CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
18621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                   llvm::Value *src, llvm::Value *dst) {
18633e283e344595e0bd499b13b30a92b7d9c10a2140Fariborz Jahanian  return;
18643e283e344595e0bd499b13b30a92b7d9c10a2140Fariborz Jahanian}
18653e283e344595e0bd499b13b30a92b7d9c10a2140Fariborz Jahanian
186658626500527695865683d1d65053743de8770b60Fariborz Jahanianvoid CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
18671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                     llvm::Value *src, llvm::Value *dst) {
186858626500527695865683d1d65053743de8770b60Fariborz Jahanian  return;
186958626500527695865683d1d65053743de8770b60Fariborz Jahanian}
187058626500527695865683d1d65053743de8770b60Fariborz Jahanian
18717eda8367cf63caee8acf907356b1d199ccaa6e89Fariborz Jahanianvoid CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
18721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                   llvm::Value *src, llvm::Value *dst) {
18737eda8367cf63caee8acf907356b1d199ccaa6e89Fariborz Jahanian  return;
18747eda8367cf63caee8acf907356b1d199ccaa6e89Fariborz Jahanian}
18757eda8367cf63caee8acf907356b1d199ccaa6e89Fariborz Jahanian
187658626500527695865683d1d65053743de8770b60Fariborz Jahanianvoid CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
18771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                         llvm::Value *src, llvm::Value *dst) {
187858626500527695865683d1d65053743de8770b60Fariborz Jahanian  return;
187958626500527695865683d1d65053743de8770b60Fariborz Jahanian}
188058626500527695865683d1d65053743de8770b60Fariborz Jahanian
1881082b02e8403d3ee9d2ded969fbe0e5d472f04cd8Fariborz Jahanianvoid CGObjCGNU::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
18821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                                         llvm::Value *DestPtr,
1883082b02e8403d3ee9d2ded969fbe0e5d472f04cd8Fariborz Jahanian                                         llvm::Value *SrcPtr,
188408c321380fff07d476a19daab6d29522c046cd49Fariborz Jahanian                                         QualType Ty) {
1885082b02e8403d3ee9d2ded969fbe0e5d472f04cd8Fariborz Jahanian  return;
1886082b02e8403d3ee9d2ded969fbe0e5d472f04cd8Fariborz Jahanian}
1887082b02e8403d3ee9d2ded969fbe0e5d472f04cd8Fariborz Jahanian
18889cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanianllvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
18899cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian                              const ObjCInterfaceDecl *ID,
18909cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian                              const ObjCIvarDecl *Ivar) {
18919cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
18929cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian    + '.' + Ivar->getNameAsString();
18939cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  // Emit the variable and initialize it with what we think the correct value
18949cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  // is.  This allows code compiled with non-fragile ivars to work correctly
18959cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  // when linked against code which isn't (most of the time).
18968a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
18978a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  if (!IvarOffsetPointer) {
18989cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian    uint64_t Offset = ComputeIvarBaseOffset(CGM, ID, Ivar);
18999cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian    llvm::ConstantInt *OffsetGuess =
19004a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson      llvm::ConstantInt::get(LongTy, Offset, "ivar");
19018a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    // Don't emit the guess in non-PIC code because the linker will not be able
19028a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    // to replace it with the real version for a library.  In non-PIC code you
19038a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    // must compile with the fragile ABI if you want to use ivars from a
19041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    // GCC-compiled class.
19058a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    if (CGM.getLangOptions().PICLevel) {
19068a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule,
19078a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall            llvm::Type::getInt32Ty(VMContext), false,
19088a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall            llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess");
19098a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
19108a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall            IvarOffsetGV->getType(), false, llvm::GlobalValue::LinkOnceAnyLinkage,
19118a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall            IvarOffsetGV, Name);
19128a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    } else {
19138a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall      IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
19148a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall              llvm::PointerType::getUnqual(llvm::Type::getInt32Ty(VMContext)),
19158a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall              false, llvm::GlobalValue::ExternalLinkage, 0, Name);
19168a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    }
19179cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  }
19188a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  return IvarOffsetPointer;
19199cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian}
19209cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian
1921598d3f61b6ca854e9d3c2f3359e24468502a61aaFariborz JahanianLValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1922598d3f61b6ca854e9d3c2f3359e24468502a61aaFariborz Jahanian                                       QualType ObjectTy,
1923598d3f61b6ca854e9d3c2f3359e24468502a61aaFariborz Jahanian                                       llvm::Value *BaseValue,
1924598d3f61b6ca854e9d3c2f3359e24468502a61aaFariborz Jahanian                                       const ObjCIvarDecl *Ivar,
1925598d3f61b6ca854e9d3c2f3359e24468502a61aaFariborz Jahanian                                       unsigned CVRQualifiers) {
1926525c9b7baeeff022127cd1b167579f3bda73b3edDaniel Dunbar  const ObjCInterfaceDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl();
19279777687562c338601c2f17906e65e1c1a0aad96fDaniel Dunbar  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
19289777687562c338601c2f17906e65e1c1a0aad96fDaniel Dunbar                                  EmitIvarOffset(CGF, ID, Ivar));
19290bb20361a321593887f067515dd04cf109f4c74aFariborz Jahanian}
1930bb1c8600218b3244340331165fc7cba7bf227655Mike Stump
19319cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanianstatic const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
19329cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian                                                  const ObjCInterfaceDecl *OID,
19339cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian                                                  const ObjCIvarDecl *OIVD) {
19349cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
19358e6ac1d80055fa37b9b84029c7e751624ba7f84cFariborz Jahanian  Context.ShallowCollectObjCIvars(OID, Ivars);
19369cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
19379cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian    if (OIVD == Ivars[k])
19389cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian      return OID;
19399cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  }
19401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19419cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  // Otherwise check in the super class.
19429cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
19439cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian    return FindIvarInterface(Context, Super, OIVD);
19441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19459cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  return 0;
19469cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian}
19470bb20361a321593887f067515dd04cf109f4c74aFariborz Jahanian
1948f63aa3fd429cdb9145d78f0b656bc78754efedb9Fariborz Jahanianllvm::Value *CGObjCGNU::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
19492a03192a02dbf4fdff438d1e658356bde871aba4Daniel Dunbar                         const ObjCInterfaceDecl *Interface,
1950f63aa3fd429cdb9145d78f0b656bc78754efedb9Fariborz Jahanian                         const ObjCIvarDecl *Ivar) {
19518a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall  if (CGM.getLangOptions().ObjCNonFragileABI) {
19529cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian    Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar);
19538a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall    return CGF.Builder.CreateLoad(CGF.Builder.CreateLoad(
19548a5a9aaddb627c0884c2ed8db55cc29fdb601195David Chisnall                ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar"));
19559cd96ff7dfcb51fdba03df8803fff6cc36e9633fFariborz Jahanian  }
19569777687562c338601c2f17906e65e1c1a0aad96fDaniel Dunbar  uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar);
19574a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson  return llvm::ConstantInt::get(LongTy, Offset, "ivar");
1958f63aa3fd429cdb9145d78f0b656bc78754efedb9Fariborz Jahanian}
1959f63aa3fd429cdb9145d78f0b656bc78754efedb9Fariborz Jahanian
1960bb1c8600218b3244340331165fc7cba7bf227655Mike StumpCodeGen::CGObjCRuntime *
1961bb1c8600218b3244340331165fc7cba7bf227655Mike StumpCodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM) {
1962dce1406f1c1f572cfd61c494546572d63461c741Chris Lattner  return new CGObjCGNU(CGM);
19630f984268b05edab2cc555a427c441baa9c252658Chris Lattner}
1964