blob: 7bcd9797fb1d58599a87b750be62f5a98102b9e1 [file] [log] [blame]
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
Chris Lattner0f984262008-03-01 08:50:34 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000010// This provides Objective-C code generation targetting the GNU runtime. The
11// class in this file generates structures used by the GNU Objective-C runtime
12// library. These structures are defined in objc/objc.h and objc/objc-api.h in
13// the GNU runtime distribution.
Chris Lattner0f984262008-03-01 08:50:34 +000014//
15//===----------------------------------------------------------------------===//
16
17#include "CGObjCRuntime.h"
Chris Lattnerdce14062008-06-26 04:19:03 +000018#include "CodeGenModule.h"
Daniel Dunbar8f2926b2008-08-23 03:46:30 +000019#include "CodeGenFunction.h"
Chris Lattnerdce14062008-06-26 04:19:03 +000020#include "clang/AST/ASTContext.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000021#include "clang/AST/Decl.h"
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +000022#include "clang/AST/DeclObjC.h"
Daniel Dunbar2bebbf02009-05-03 10:46:44 +000023#include "clang/AST/RecordLayout.h"
Chris Lattner16f00492009-04-26 01:32:48 +000024#include "clang/AST/StmtObjC.h"
Chris Lattner0f984262008-03-01 08:50:34 +000025#include "llvm/Module.h"
Chris Lattner0f984262008-03-01 08:50:34 +000026#include "llvm/ADT/SmallVector.h"
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000027#include "llvm/ADT/StringMap.h"
Daniel Dunbar7ded7f42008-08-15 22:20:32 +000028#include "llvm/Support/Compiler.h"
Daniel Dunbar7ded7f42008-08-15 22:20:32 +000029#include "llvm/Target/TargetData.h"
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000030#include <map>
Chris Lattnere160c9b2009-01-27 05:06:01 +000031
32
Chris Lattnerdce14062008-06-26 04:19:03 +000033using namespace clang;
Daniel Dunbar46f45b92008-09-09 01:06:48 +000034using namespace CodeGen;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000035using llvm::dyn_cast;
36
37// The version of the runtime that this class targets. Must match the version
38// in the runtime.
39static const int RuntimeVersion = 8;
40static const int ProtocolVersion = 2;
Chris Lattner0f984262008-03-01 08:50:34 +000041
Chris Lattner0f984262008-03-01 08:50:34 +000042namespace {
Chris Lattnerdce14062008-06-26 04:19:03 +000043class CGObjCGNU : public CodeGen::CGObjCRuntime {
Chris Lattner0f984262008-03-01 08:50:34 +000044private:
Chris Lattnerdce14062008-06-26 04:19:03 +000045 CodeGen::CodeGenModule &CGM;
Chris Lattner0f984262008-03-01 08:50:34 +000046 llvm::Module &TheModule;
Chris Lattnere160c9b2009-01-27 05:06:01 +000047 const llvm::PointerType *SelectorTy;
48 const llvm::PointerType *PtrToInt8Ty;
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +000049 const llvm::FunctionType *IMPTy;
Chris Lattnere160c9b2009-01-27 05:06:01 +000050 const llvm::PointerType *IdTy;
51 const llvm::IntegerType *IntTy;
52 const llvm::PointerType *PtrTy;
53 const llvm::IntegerType *LongTy;
54 const llvm::PointerType *PtrToIntTy;
Daniel Dunbar5efccb12009-05-04 15:31:17 +000055 llvm::GlobalAlias *ClassPtrAlias;
56 llvm::GlobalAlias *MetaClassPtrAlias;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000057 std::vector<llvm::Constant*> Classes;
58 std::vector<llvm::Constant*> Categories;
59 std::vector<llvm::Constant*> ConstantStrings;
60 llvm::Function *LoadFunction;
61 llvm::StringMap<llvm::Constant*> ExistingProtocols;
62 typedef std::pair<std::string, std::string> TypedSelector;
63 std::map<TypedSelector, llvm::GlobalAlias*> TypedSelectors;
64 llvm::StringMap<llvm::GlobalAlias*> UntypedSelectors;
65 // Some zeros used for GEPs in lots of places.
66 llvm::Constant *Zeros[2];
67 llvm::Constant *NULLPtr;
68private:
69 llvm::Constant *GenerateIvarList(
70 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
71 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
72 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets);
73 llvm::Constant *GenerateMethodList(const std::string &ClassName,
74 const std::string &CategoryName,
Chris Lattnera4210072008-06-26 05:08:00 +000075 const llvm::SmallVectorImpl<Selector> &MethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000076 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
77 bool isClassMethodList);
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +000078 llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000079 llvm::Constant *GenerateProtocolList(
80 const llvm::SmallVectorImpl<std::string> &Protocols);
81 llvm::Constant *GenerateClassStructure(
82 llvm::Constant *MetaClass,
83 llvm::Constant *SuperClass,
84 unsigned info,
Chris Lattnerd002cc62008-06-26 04:47:04 +000085 const char *Name,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000086 llvm::Constant *Version,
87 llvm::Constant *InstanceSize,
88 llvm::Constant *IVars,
89 llvm::Constant *Methods,
90 llvm::Constant *Protocols);
91 llvm::Constant *GenerateProtocolMethodList(
92 const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
93 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes);
94 llvm::Constant *MakeConstantString(const std::string &Str, const std::string
95 &Name="");
96 llvm::Constant *MakeGlobal(const llvm::StructType *Ty,
97 std::vector<llvm::Constant*> &V, const std::string &Name="");
98 llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty,
99 std::vector<llvm::Constant*> &V, const std::string &Name="");
Chris Lattner0f984262008-03-01 08:50:34 +0000100public:
Chris Lattnerdce14062008-06-26 04:19:03 +0000101 CGObjCGNU(CodeGen::CodeGenModule &cgm);
Steve Naroff33fdb732009-03-31 16:53:37 +0000102 virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *);
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000103 virtual CodeGen::RValue
104 GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000105 QualType ResultType,
106 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000107 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000108 bool IsClassMessage,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000109 const CallArgList &CallArgs,
110 const ObjCMethodDecl *Method);
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000111 virtual CodeGen::RValue
112 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000113 QualType ResultType,
114 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000115 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +0000116 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000117 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000118 bool IsClassMessage,
119 const CallArgList &CallArgs);
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000120 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +0000121 const ObjCInterfaceDecl *OID);
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000122 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel);
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000123 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
124 *Method);
Chris Lattner8e67b632008-06-26 04:37:12 +0000125
Fariborz Jahanian679a5022009-01-10 21:06:09 +0000126 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
127 const ObjCContainerDecl *CD);
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000128 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
129 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000130 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000131 const ObjCProtocolDecl *PD);
132 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000133 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar49f66022008-09-24 03:38:44 +0000134 virtual llvm::Function *GetPropertyGetFunction();
135 virtual llvm::Function *GetPropertySetFunction();
Anders Carlsson2abd89c2008-08-31 04:05:03 +0000136 virtual llvm::Function *EnumerationMutationFunction();
Anders Carlsson64d5d6c2008-09-09 10:04:29 +0000137
Fariborz Jahanianbd71be42008-11-21 00:49:24 +0000138 virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
139 const Stmt &S);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +0000140 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
141 const ObjCAtThrowStmt &S);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +0000142 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6dc23172008-11-18 21:45:40 +0000143 llvm::Value *AddrWeakObj);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +0000144 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
145 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian58626502008-11-19 00:59:10 +0000146 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
147 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +0000148 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
149 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian58626502008-11-19 00:59:10 +0000150 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
151 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian598d3f62009-02-03 19:03:09 +0000152 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
153 QualType ObjectTy,
154 llvm::Value *BaseValue,
155 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +0000156 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +0000157 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +0000158 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +0000159 const ObjCIvarDecl *Ivar);
Chris Lattner0f984262008-03-01 08:50:34 +0000160};
161} // end anonymous namespace
162
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000163
164
165static std::string SymbolNameForClass(const std::string &ClassName) {
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000166 return "___objc_class_name_" + ClassName;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000167}
168
169static std::string SymbolNameForMethod(const std::string &ClassName, const
170 std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
171{
172 return "._objc_method_" + ClassName +"("+CategoryName+")"+
173 (isClassMethod ? "+" : "-") + MethodName;
174}
175
Chris Lattnerdce14062008-06-26 04:19:03 +0000176CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000177 : CGM(cgm), TheModule(CGM.getModule()), ClassPtrAlias(0),
178 MetaClassPtrAlias(0) {
Chris Lattnere160c9b2009-01-27 05:06:01 +0000179 IntTy = cast<llvm::IntegerType>(
180 CGM.getTypes().ConvertType(CGM.getContext().IntTy));
181 LongTy = cast<llvm::IntegerType>(
182 CGM.getTypes().ConvertType(CGM.getContext().LongTy));
Chris Lattnerdce14062008-06-26 04:19:03 +0000183
Sebastian Redl3a5013c2008-12-04 00:10:55 +0000184 Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000185 Zeros[1] = Zeros[0];
186 NULLPtr = llvm::ConstantPointerNull::get(
187 llvm::PointerType::getUnqual(llvm::Type::Int8Ty));
Chris Lattner391d77a2008-03-30 23:03:07 +0000188 // C string type. Used in lots of places.
189 PtrToInt8Ty =
190 llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
191 // Get the selector Type.
Chris Lattnere160c9b2009-01-27 05:06:01 +0000192 SelectorTy = cast<llvm::PointerType>(
193 CGM.getTypes().ConvertType(CGM.getContext().getObjCSelType()));
194
Chris Lattner391d77a2008-03-30 23:03:07 +0000195 PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
196 PtrTy = PtrToInt8Ty;
197
198 // Object type
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000199 IdTy = cast<llvm::PointerType>(
200 CGM.getTypes().ConvertType(CGM.getContext().getObjCIdType()));
Chris Lattner391d77a2008-03-30 23:03:07 +0000201
202 // IMP type
203 std::vector<const llvm::Type*> IMPArgs;
204 IMPArgs.push_back(IdTy);
205 IMPArgs.push_back(SelectorTy);
206 IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000207}
208// This has to perform the lookup every time, since posing and related
209// techniques can modify the name -> class mapping.
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000210llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder,
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +0000211 const ObjCInterfaceDecl *OID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000212 llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getNameAsString());
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +0000213 ClassName = Builder.CreateStructGEP(ClassName, 0);
214
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000215 std::vector<const llvm::Type*> Params(1, PtrToInt8Ty);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000216 llvm::Constant *ClassLookupFn =
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000217 CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy,
218 Params,
219 true),
220 "objc_lookup_class");
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000221 return Builder.CreateCall(ClassLookupFn, ClassName);
Chris Lattner391d77a2008-03-30 23:03:07 +0000222}
223
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000224llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel) {
Chris Lattner077bf5e2008-11-24 03:33:13 +0000225 llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()];
Chris Lattner8e67b632008-06-26 04:37:12 +0000226 if (US == 0)
227 US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy),
228 llvm::GlobalValue::InternalLinkage,
229 ".objc_untyped_selector_alias",
230 NULL, &TheModule);
231
232 return Builder.CreateLoad(US);
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000233}
234
235llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
236 *Method) {
237
238 std::string SelName = Method->getSelector().getAsString();
239 std::string SelTypes;
240 CGM.getContext().getObjCEncodingForMethodDecl(Method, SelTypes);
241 // Typed selectors
242 TypedSelector Selector = TypedSelector(SelName,
243 SelTypes);
244
245 // If it's already cached, return it.
246 if (TypedSelectors[Selector])
247 {
248 return Builder.CreateLoad(TypedSelectors[Selector]);
249 }
250
251 // If it isn't, cache it.
252 llvm::GlobalAlias *Sel = new llvm::GlobalAlias(
253 llvm::PointerType::getUnqual(SelectorTy),
254 llvm::GlobalValue::InternalLinkage, SelName,
255 NULL, &TheModule);
256 TypedSelectors[Selector] = Sel;
257
258 return Builder.CreateLoad(Sel);
Chris Lattner8e67b632008-06-26 04:37:12 +0000259}
260
Chris Lattner5e7dcc62008-06-26 04:44:19 +0000261llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str,
262 const std::string &Name) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000263 llvm::Constant * ConstStr = llvm::ConstantArray::get(Str);
264 ConstStr = new llvm::GlobalVariable(ConstStr->getType(), true,
265 llvm::GlobalValue::InternalLinkage,
266 ConstStr, Name, &TheModule);
267 return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
268}
269llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty,
270 std::vector<llvm::Constant*> &V, const std::string &Name) {
271 llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
272 return new llvm::GlobalVariable(Ty, false,
273 llvm::GlobalValue::InternalLinkage, C, Name, &TheModule);
274}
275llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
276 std::vector<llvm::Constant*> &V, const std::string &Name) {
277 llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
278 return new llvm::GlobalVariable(Ty, false,
279 llvm::GlobalValue::InternalLinkage, C, Name, &TheModule);
280}
281
282/// Generate an NSConstantString object.
283//TODO: In case there are any crazy people still using the GNU runtime without
284//an OpenStep implementation, this should let them select their own class for
285//constant strings.
Steve Naroff33fdb732009-03-31 16:53:37 +0000286llvm::Constant *CGObjCGNU::GenerateConstantString(const ObjCStringLiteral *SL) {
287 std::string Str(SL->getString()->getStrData(),
288 SL->getString()->getByteLength());
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000289 std::vector<llvm::Constant*> Ivars;
290 Ivars.push_back(NULLPtr);
Chris Lattner13fd7e52008-06-21 21:44:18 +0000291 Ivars.push_back(MakeConstantString(Str));
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000292 Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000293 llvm::Constant *ObjCStr = MakeGlobal(
294 llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL),
295 Ivars, ".objc_str");
296 ConstantStrings.push_back(
297 llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty));
298 return ObjCStr;
299}
300
301///Generates a message send where the super is the receiver. This is a message
302///send to self with special delivery semantics indicating which class's method
303///should be called.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000304CodeGen::RValue
305CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000306 QualType ResultType,
307 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000308 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +0000309 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000310 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000311 bool IsClassMessage,
312 const CallArgList &CallArgs) {
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000313 llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
314
315 CallArgList ActualArgs;
316
317 ActualArgs.push_back(
318 std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)),
319 CGF.getContext().getObjCIdType()));
320 ActualArgs.push_back(std::make_pair(RValue::get(cmd),
321 CGF.getContext().getObjCSelType()));
322 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
323
324 CodeGenTypes &Types = CGM.getTypes();
325 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
326 const llvm::FunctionType *impType = Types.GetFunctionType(FnInfo, false);
327
328
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000329 // Set up global aliases for the metaclass or class pointer if they do not
330 // already exist. These will are forward-references which will be set to
331 // pointers to the class and metaclass structure created for the runtime load
332 // function. To send a message to super, we look up the value of the
333 // super_class pointer from either the class or metaclass structure.
334 llvm::Value *ReceiverClass = 0;
335 if (IsClassMessage) {
336 if (!MetaClassPtrAlias) {
337 MetaClassPtrAlias = new llvm::GlobalAlias(IdTy,
Chris Lattnerc6e2ab02009-05-04 16:56:33 +0000338 llvm::GlobalValue::InternalLinkage, ".objc_metaclass_ref" +
339 Class->getNameAsString(), NULL, &TheModule);
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000340 }
341 ReceiverClass = MetaClassPtrAlias;
342 } else {
343 if (!ClassPtrAlias) {
344 ClassPtrAlias = new llvm::GlobalAlias(IdTy,
Chris Lattnerc6e2ab02009-05-04 16:56:33 +0000345 llvm::GlobalValue::InternalLinkage, ".objc_class_ref" +
346 Class->getNameAsString(), NULL, &TheModule);
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000347 }
348 ReceiverClass = ClassPtrAlias;
Chris Lattner71238f62009-04-25 23:19:45 +0000349 }
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000350 // Cast the pointer to a simplified version of the class structure
351 ReceiverClass = CGF.Builder.CreateBitCast(ReceiverClass,
352 llvm::PointerType::getUnqual(llvm::StructType::get(IdTy, IdTy, NULL)));
353 // Get the superclass pointer
354 ReceiverClass = CGF.Builder.CreateStructGEP(ReceiverClass, 1);
355 // Load the superclass pointer
356 ReceiverClass = CGF.Builder.CreateLoad(ReceiverClass);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000357 // Construct the structure used to look up the IMP
358 llvm::StructType *ObjCSuperTy = llvm::StructType::get(Receiver->getType(),
359 IdTy, NULL);
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000360 llvm::Value *ObjCSuper = CGF.Builder.CreateAlloca(ObjCSuperTy);
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000361
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000362 CGF.Builder.CreateStore(Receiver, CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000363 CGF.Builder.CreateStore(ReceiverClass,
364 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000365
366 // Get the IMP
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000367 std::vector<const llvm::Type*> Params;
368 Params.push_back(llvm::PointerType::getUnqual(ObjCSuperTy));
369 Params.push_back(SelectorTy);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000370 llvm::Constant *lookupFunction =
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000371 CGM.CreateRuntimeFunction(llvm::FunctionType::get(
372 llvm::PointerType::getUnqual(impType), Params, true),
373 "objc_msg_lookup_super");
374
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000375 llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000376 llvm::Value *imp = CGF.Builder.CreateCall(lookupFunction, lookupArgs,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000377 lookupArgs+2);
378
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000379 return CGF.EmitCall(FnInfo, imp, ActualArgs);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000380}
381
382/// Generate code for a message send expression.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000383CodeGen::RValue
384CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000385 QualType ResultType,
386 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000387 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000388 bool IsClassMessage,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000389 const CallArgList &CallArgs,
390 const ObjCMethodDecl *Method) {
391 llvm::Value *cmd;
392 if (Method)
393 cmd = GetSelector(CGF.Builder, Method);
394 else
395 cmd = GetSelector(CGF.Builder, Sel);
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000396 CallArgList ActualArgs;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000397
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000398 ActualArgs.push_back(
399 std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)),
400 CGF.getContext().getObjCIdType()));
401 ActualArgs.push_back(std::make_pair(RValue::get(cmd),
402 CGF.getContext().getObjCSelType()));
403 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
404
405 CodeGenTypes &Types = CGM.getTypes();
406 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
407 const llvm::FunctionType *impType = Types.GetFunctionType(FnInfo, false);
408
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000409 std::vector<const llvm::Type*> Params;
410 Params.push_back(Receiver->getType());
411 Params.push_back(SelectorTy);
Chris Lattner0f984262008-03-01 08:50:34 +0000412 llvm::Constant *lookupFunction =
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000413 CGM.CreateRuntimeFunction(llvm::FunctionType::get(
414 llvm::PointerType::getUnqual(impType), Params, true),
415 "objc_msg_lookup");
416
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000417 llvm::Value *imp = CGF.Builder.CreateCall2(lookupFunction, Receiver, cmd);
Chris Lattner3eae03e2008-05-06 00:56:42 +0000418
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000419 return CGF.EmitCall(FnInfo, imp, ActualArgs);
Chris Lattner0f984262008-03-01 08:50:34 +0000420}
421
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000422/// Generates a MethodList. Used in construction of a objc_class and
423/// objc_category structures.
424llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName,
Chris Lattnera4210072008-06-26 05:08:00 +0000425 const std::string &CategoryName,
426 const llvm::SmallVectorImpl<Selector> &MethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000427 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
428 bool isClassMethodList) {
429 // Get the method structure type.
430 llvm::StructType *ObjCMethodTy = llvm::StructType::get(
431 PtrToInt8Ty, // Really a selector, but the runtime creates it us.
432 PtrToInt8Ty, // Method types
433 llvm::PointerType::getUnqual(IMPTy), //Method pointer
434 NULL);
435 std::vector<llvm::Constant*> Methods;
436 std::vector<llvm::Constant*> Elements;
437 for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
438 Elements.clear();
Chris Lattner077bf5e2008-11-24 03:33:13 +0000439 llvm::Constant *C =
440 CGM.GetAddrOfConstantCString(MethodSels[i].getAsString());
Chris Lattnera4210072008-06-26 05:08:00 +0000441 Elements.push_back(llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000442 Elements.push_back(
443 llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
444 llvm::Constant *Method =
445 TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
Chris Lattner077bf5e2008-11-24 03:33:13 +0000446 MethodSels[i].getAsString(),
Chris Lattner550b8db2008-06-26 04:05:20 +0000447 isClassMethodList));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000448 Method = llvm::ConstantExpr::getBitCast(Method,
449 llvm::PointerType::getUnqual(IMPTy));
450 Elements.push_back(Method);
451 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements));
452 }
453
454 // Array of method structures
455 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
Chris Lattnera4210072008-06-26 05:08:00 +0000456 MethodSels.size());
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000457 llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy,
Chris Lattnerfba67632008-06-26 04:52:29 +0000458 Methods);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000459
460 // Structure containing list pointer, array and array count
461 llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields;
462 llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get();
463 llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy);
464 llvm::StructType *ObjCMethodListTy = llvm::StructType::get(NextPtrTy,
465 IntTy,
466 ObjCMethodArrayTy,
467 NULL);
468 // Refine next pointer type to concrete type
469 llvm::cast<llvm::OpaqueType>(
470 OpaqueNextTy.get())->refineAbstractTypeTo(ObjCMethodListTy);
471 ObjCMethodListTy = llvm::cast<llvm::StructType>(OpaqueNextTy.get());
472
473 Methods.clear();
474 Methods.push_back(llvm::ConstantPointerNull::get(
475 llvm::PointerType::getUnqual(ObjCMethodListTy)));
476 Methods.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty,
477 MethodTypes.size()));
478 Methods.push_back(MethodArray);
479
480 // Create an instance of the structure
481 return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list");
482}
483
484/// Generates an IvarList. Used in construction of a objc_class.
485llvm::Constant *CGObjCGNU::GenerateIvarList(
486 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
487 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
488 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) {
489 // Get the method structure type.
490 llvm::StructType *ObjCIvarTy = llvm::StructType::get(
491 PtrToInt8Ty,
492 PtrToInt8Ty,
493 IntTy,
494 NULL);
495 std::vector<llvm::Constant*> Ivars;
496 std::vector<llvm::Constant*> Elements;
497 for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
498 Elements.clear();
499 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarNames[i],
500 Zeros, 2));
501 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarTypes[i],
502 Zeros, 2));
503 Elements.push_back(IvarOffsets[i]);
504 Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements));
505 }
506
507 // Array of method structures
508 llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
509 IvarNames.size());
510
511
512 Elements.clear();
Chris Lattnere160c9b2009-01-27 05:06:01 +0000513 Elements.push_back(llvm::ConstantInt::get(IntTy, (int)IvarNames.size()));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000514 Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars));
515 // Structure containing array and array count
516 llvm::StructType *ObjCIvarListTy = llvm::StructType::get(IntTy,
517 ObjCIvarArrayTy,
518 NULL);
519
520 // Create an instance of the structure
521 return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list");
522}
523
524/// Generate a class structure
525llvm::Constant *CGObjCGNU::GenerateClassStructure(
526 llvm::Constant *MetaClass,
527 llvm::Constant *SuperClass,
528 unsigned info,
Chris Lattnerd002cc62008-06-26 04:47:04 +0000529 const char *Name,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000530 llvm::Constant *Version,
531 llvm::Constant *InstanceSize,
532 llvm::Constant *IVars,
533 llvm::Constant *Methods,
534 llvm::Constant *Protocols) {
535 // Set up the class structure
536 // Note: Several of these are char*s when they should be ids. This is
537 // because the runtime performs this translation on load.
538 llvm::StructType *ClassTy = llvm::StructType::get(
539 PtrToInt8Ty, // class_pointer
540 PtrToInt8Ty, // super_class
541 PtrToInt8Ty, // name
542 LongTy, // version
543 LongTy, // info
544 LongTy, // instance_size
545 IVars->getType(), // ivars
546 Methods->getType(), // methods
547 // These are all filled in by the runtime, so we pretend
548 PtrTy, // dtable
549 PtrTy, // subclass_list
550 PtrTy, // sibling_class
551 PtrTy, // protocols
552 PtrTy, // gc_object_type
553 NULL);
554 llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
555 llvm::Constant *NullP =
Chris Lattnere160c9b2009-01-27 05:06:01 +0000556 llvm::ConstantPointerNull::get(PtrTy);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000557 // Fill in the structure
558 std::vector<llvm::Constant*> Elements;
559 Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
560 Elements.push_back(SuperClass);
Chris Lattnerd002cc62008-06-26 04:47:04 +0000561 Elements.push_back(MakeConstantString(Name, ".class_name"));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000562 Elements.push_back(Zero);
563 Elements.push_back(llvm::ConstantInt::get(LongTy, info));
564 Elements.push_back(InstanceSize);
565 Elements.push_back(IVars);
566 Elements.push_back(Methods);
567 Elements.push_back(NullP);
568 Elements.push_back(NullP);
569 Elements.push_back(NullP);
570 Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
571 Elements.push_back(NullP);
572 // Create an instance of the structure
Chris Lattner1565e032008-07-21 06:31:05 +0000573 return MakeGlobal(ClassTy, Elements, SymbolNameForClass(Name));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000574}
575
576llvm::Constant *CGObjCGNU::GenerateProtocolMethodList(
577 const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
578 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes) {
579 // Get the method structure type.
580 llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(
581 PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
582 PtrToInt8Ty,
583 NULL);
584 std::vector<llvm::Constant*> Methods;
585 std::vector<llvm::Constant*> Elements;
586 for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
587 Elements.clear();
588 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(MethodNames[i],
589 Zeros, 2));
590 Elements.push_back(
591 llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
592 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements));
593 }
594 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
595 MethodNames.size());
596 llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy, Methods);
597 llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(
598 IntTy, ObjCMethodArrayTy, NULL);
599 Methods.clear();
600 Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
601 Methods.push_back(Array);
602 return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list");
603}
604// Create the protocol list structure used in classes, categories and so on
605llvm::Constant *CGObjCGNU::GenerateProtocolList(
606 const llvm::SmallVectorImpl<std::string> &Protocols) {
607 llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
608 Protocols.size());
609 llvm::StructType *ProtocolListTy = llvm::StructType::get(
610 PtrTy, //Should be a recurisve pointer, but it's always NULL here.
611 LongTy,//FIXME: Should be size_t
612 ProtocolArrayTy,
613 NULL);
614 std::vector<llvm::Constant*> Elements;
615 for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
616 iter != endIter ; iter++) {
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +0000617 llvm::Constant *protocol = ExistingProtocols[*iter];
618 if (!protocol)
619 protocol = GenerateEmptyProtocol(*iter);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000620 llvm::Constant *Ptr =
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +0000621 llvm::ConstantExpr::getBitCast(protocol, PtrToInt8Ty);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000622 Elements.push_back(Ptr);
623 }
624 llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
625 Elements);
626 Elements.clear();
627 Elements.push_back(NULLPtr);
Chris Lattnere160c9b2009-01-27 05:06:01 +0000628 Elements.push_back(llvm::ConstantInt::get(LongTy, Protocols.size()));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000629 Elements.push_back(ProtocolArray);
630 return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list");
631}
632
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000633llvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000634 const ObjCProtocolDecl *PD) {
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +0000635 llvm::Value *protocol = ExistingProtocols[PD->getNameAsString()];
636 const llvm::Type *T =
637 CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType());
638 return Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
639}
640
641llvm::Constant *CGObjCGNU::GenerateEmptyProtocol(
642 const std::string &ProtocolName) {
643 llvm::SmallVector<std::string, 0> EmptyStringVector;
644 llvm::SmallVector<llvm::Constant*, 0> EmptyConstantVector;
645
646 llvm::Constant *ProtocolList = GenerateProtocolList(EmptyStringVector);
647 llvm::Constant *InstanceMethodList =
648 GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector);
649 llvm::Constant *ClassMethodList =
650 GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector);
651 // Protocols are objects containing lists of the methods implemented and
652 // protocols adopted.
653 llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy,
654 PtrToInt8Ty,
655 ProtocolList->getType(),
656 InstanceMethodList->getType(),
657 ClassMethodList->getType(),
658 NULL);
659 std::vector<llvm::Constant*> Elements;
660 // The isa pointer must be set to a magic number so the runtime knows it's
661 // the correct layout.
662 Elements.push_back(llvm::ConstantExpr::getIntToPtr(
663 llvm::ConstantInt::get(llvm::Type::Int32Ty, ProtocolVersion), IdTy));
664 Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
665 Elements.push_back(ProtocolList);
666 Elements.push_back(InstanceMethodList);
667 Elements.push_back(ClassMethodList);
668 return MakeGlobal(ProtocolTy, Elements, ".objc_protocol");
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000669}
670
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000671void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
672 ASTContext &Context = CGM.getContext();
Chris Lattner8ec03f52008-11-24 03:54:41 +0000673 std::string ProtocolName = PD->getNameAsString();
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000674 llvm::SmallVector<std::string, 16> Protocols;
675 for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(),
676 E = PD->protocol_end(); PI != E; ++PI)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000677 Protocols.push_back((*PI)->getNameAsString());
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000678 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames;
679 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
Douglas Gregor6ab35242009-04-09 21:40:53 +0000680 for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(Context),
681 E = PD->instmeth_end(Context); iter != E; iter++) {
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000682 std::string TypeStr;
683 Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
684 InstanceMethodNames.push_back(
Chris Lattner077bf5e2008-11-24 03:33:13 +0000685 CGM.GetAddrOfConstantCString((*iter)->getSelector().getAsString()));
Daniel Dunbar61432932008-08-13 23:20:05 +0000686 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000687 }
688 // Collect information about class methods:
689 llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames;
690 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
Douglas Gregor6ab35242009-04-09 21:40:53 +0000691 for (ObjCProtocolDecl::classmeth_iterator
692 iter = PD->classmeth_begin(Context),
693 endIter = PD->classmeth_end(Context) ; iter != endIter ; iter++) {
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000694 std::string TypeStr;
695 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
696 ClassMethodNames.push_back(
Chris Lattner077bf5e2008-11-24 03:33:13 +0000697 CGM.GetAddrOfConstantCString((*iter)->getSelector().getAsString()));
Daniel Dunbar61432932008-08-13 23:20:05 +0000698 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000699 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000700
701 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
702 llvm::Constant *InstanceMethodList =
703 GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes);
704 llvm::Constant *ClassMethodList =
705 GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes);
706 // Protocols are objects containing lists of the methods implemented and
707 // protocols adopted.
708 llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy,
709 PtrToInt8Ty,
710 ProtocolList->getType(),
711 InstanceMethodList->getType(),
712 ClassMethodList->getType(),
713 NULL);
714 std::vector<llvm::Constant*> Elements;
715 // The isa pointer must be set to a magic number so the runtime knows it's
716 // the correct layout.
717 Elements.push_back(llvm::ConstantExpr::getIntToPtr(
718 llvm::ConstantInt::get(llvm::Type::Int32Ty, ProtocolVersion), IdTy));
719 Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
720 Elements.push_back(ProtocolList);
721 Elements.push_back(InstanceMethodList);
722 Elements.push_back(ClassMethodList);
723 ExistingProtocols[ProtocolName] =
724 llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
725 ".objc_protocol"), IdTy);
726}
727
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000728void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Chris Lattner8ec03f52008-11-24 03:54:41 +0000729 std::string ClassName = OCD->getClassInterface()->getNameAsString();
730 std::string CategoryName = OCD->getNameAsString();
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000731 // Collect information about instance methods
732 llvm::SmallVector<Selector, 16> InstanceMethodSels;
733 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
Douglas Gregor653f1b12009-04-23 01:02:12 +0000734 for (ObjCCategoryImplDecl::instmeth_iterator
735 iter = OCD->instmeth_begin(CGM.getContext()),
736 endIter = OCD->instmeth_end(CGM.getContext());
737 iter != endIter ; iter++) {
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000738 InstanceMethodSels.push_back((*iter)->getSelector());
739 std::string TypeStr;
740 CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
741 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
742 }
743
744 // Collect information about class methods
745 llvm::SmallVector<Selector, 16> ClassMethodSels;
746 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
Douglas Gregor653f1b12009-04-23 01:02:12 +0000747 for (ObjCCategoryImplDecl::classmeth_iterator
748 iter = OCD->classmeth_begin(CGM.getContext()),
749 endIter = OCD->classmeth_end(CGM.getContext());
750 iter != endIter ; iter++) {
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000751 ClassMethodSels.push_back((*iter)->getSelector());
752 std::string TypeStr;
753 CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
754 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
755 }
756
757 // Collect the names of referenced protocols
758 llvm::SmallVector<std::string, 16> Protocols;
759 const ObjCInterfaceDecl *ClassDecl = OCD->getClassInterface();
760 const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
761 for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
762 E = Protos.end(); I != E; ++I)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000763 Protocols.push_back((*I)->getNameAsString());
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000764
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000765 std::vector<llvm::Constant*> Elements;
766 Elements.push_back(MakeConstantString(CategoryName));
767 Elements.push_back(MakeConstantString(ClassName));
768 // Instance method list
769 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattnera4210072008-06-26 05:08:00 +0000770 ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000771 false), PtrTy));
772 // Class method list
773 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattnera4210072008-06-26 05:08:00 +0000774 ClassName, CategoryName, ClassMethodSels, ClassMethodTypes, true),
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000775 PtrTy));
776 // Protocol list
777 Elements.push_back(llvm::ConstantExpr::getBitCast(
778 GenerateProtocolList(Protocols), PtrTy));
779 Categories.push_back(llvm::ConstantExpr::getBitCast(
780 MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, PtrTy,
781 PtrTy, PtrTy, NULL), Elements), PtrTy));
782}
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000783
784void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
785 ASTContext &Context = CGM.getContext();
786
787 // Get the superclass name.
788 const ObjCInterfaceDecl * SuperClassDecl =
789 OID->getClassInterface()->getSuperClass();
Chris Lattner8ec03f52008-11-24 03:54:41 +0000790 std::string SuperClassName;
791 if (SuperClassDecl)
792 SuperClassName = SuperClassDecl->getNameAsString();
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000793
794 // Get the class name
Chris Lattner09dc6662009-04-01 02:00:48 +0000795 ObjCInterfaceDecl *ClassDecl =
796 const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
Chris Lattner8ec03f52008-11-24 03:54:41 +0000797 std::string ClassName = ClassDecl->getNameAsString();
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000798
Daniel Dunbar2bebbf02009-05-03 10:46:44 +0000799 // Get the size of instances.
800 int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8;
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000801
802 // Collect information about instance variables.
803 llvm::SmallVector<llvm::Constant*, 16> IvarNames;
804 llvm::SmallVector<llvm::Constant*, 16> IvarTypes;
805 llvm::SmallVector<llvm::Constant*, 16> IvarOffsets;
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000806 for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
807 endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
808 // Store the name
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000809 IvarNames.push_back(CGM.GetAddrOfConstantCString((*iter)
810 ->getNameAsString()));
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000811 // Get the type encoding for this ivar
812 std::string TypeStr;
Daniel Dunbar0d504c12008-10-17 20:21:44 +0000813 Context.getObjCEncodingForType((*iter)->getType(), TypeStr);
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000814 IvarTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
815 // Get the offset
Daniel Dunbarc8cbf192009-04-22 08:20:31 +0000816 uint64_t Offset = ComputeIvarBaseOffset(CGM, ClassDecl, *iter);
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000817 IvarOffsets.push_back(
Daniel Dunbarc8cbf192009-04-22 08:20:31 +0000818 llvm::ConstantInt::get(llvm::Type::Int32Ty, Offset));
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000819 }
820
821 // Collect information about instance methods
822 llvm::SmallVector<Selector, 16> InstanceMethodSels;
823 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
Douglas Gregor653f1b12009-04-23 01:02:12 +0000824 for (ObjCImplementationDecl::instmeth_iterator
825 iter = OID->instmeth_begin(CGM.getContext()),
826 endIter = OID->instmeth_end(CGM.getContext());
827 iter != endIter ; iter++) {
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000828 InstanceMethodSels.push_back((*iter)->getSelector());
829 std::string TypeStr;
830 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
831 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
832 }
833
834 // Collect information about class methods
835 llvm::SmallVector<Selector, 16> ClassMethodSels;
836 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
Douglas Gregor653f1b12009-04-23 01:02:12 +0000837 for (ObjCImplementationDecl::classmeth_iterator
838 iter = OID->classmeth_begin(CGM.getContext()),
839 endIter = OID->classmeth_end(CGM.getContext());
840 iter != endIter ; iter++) {
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000841 ClassMethodSels.push_back((*iter)->getSelector());
842 std::string TypeStr;
843 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
844 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
845 }
846 // Collect the names of referenced protocols
847 llvm::SmallVector<std::string, 16> Protocols;
848 const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
849 for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
850 E = Protos.end(); I != E; ++I)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000851 Protocols.push_back((*I)->getNameAsString());
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000852
853
854
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000855 // Get the superclass pointer.
856 llvm::Constant *SuperClass;
Chris Lattner8ec03f52008-11-24 03:54:41 +0000857 if (!SuperClassName.empty()) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000858 SuperClass = MakeConstantString(SuperClassName, ".super_class_name");
859 } else {
Chris Lattnere160c9b2009-01-27 05:06:01 +0000860 SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000861 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000862 // Empty vector used to construct empty method lists
863 llvm::SmallVector<llvm::Constant*, 1> empty;
864 // Generate the method and instance variable lists
865 llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
Chris Lattnera4210072008-06-26 05:08:00 +0000866 InstanceMethodSels, InstanceMethodTypes, false);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000867 llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
Chris Lattnera4210072008-06-26 05:08:00 +0000868 ClassMethodSels, ClassMethodTypes, true);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000869 llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
870 IvarOffsets);
871 //Generate metaclass for class methods
872 llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
Chris Lattner1565e032008-07-21 06:31:05 +0000873 NULLPtr, 0x2L, /*name*/"", 0, Zeros[0], GenerateIvarList(
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000874 empty, empty, empty), ClassMethodList, NULLPtr);
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000875
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000876 // Generate the class structure
Chris Lattner8ec03f52008-11-24 03:54:41 +0000877 llvm::Constant *ClassStruct =
878 GenerateClassStructure(MetaClassStruct, SuperClass, 0x1L,
879 ClassName.c_str(), 0,
Sebastian Redl3a5013c2008-12-04 00:10:55 +0000880 llvm::ConstantInt::get(LongTy, instanceSize), IvarList,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000881 MethodList, GenerateProtocolList(Protocols));
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000882
883 // Resolve the class aliases, if they exist.
884 if (ClassPtrAlias) {
885 ClassPtrAlias->setAliasee(
886 llvm::ConstantExpr::getBitCast(ClassStruct, IdTy));
887 ClassPtrAlias = 0;
888 }
889 if (MetaClassPtrAlias) {
890 MetaClassPtrAlias->setAliasee(
891 llvm::ConstantExpr::getBitCast(MetaClassStruct, IdTy));
892 MetaClassPtrAlias = 0;
893 }
894
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000895 // Add class structure to list to be added to the symtab later
896 ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty);
897 Classes.push_back(ClassStruct);
898}
899
900llvm::Function *CGObjCGNU::ModuleInitFunction() {
901 // Only emit an ObjC load function if no Objective-C stuff has been called
902 if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
903 ExistingProtocols.empty() && TypedSelectors.empty() &&
Anton Korobeynikov5f58b912008-06-01 15:14:46 +0000904 UntypedSelectors.empty())
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000905 return NULL;
Eli Friedman1b8956e2008-06-01 16:00:02 +0000906
Chris Lattnere160c9b2009-01-27 05:06:01 +0000907 const llvm::StructType *SelStructTy = dyn_cast<llvm::StructType>(
908 SelectorTy->getElementType());
909 const llvm::Type *SelStructPtrTy = SelectorTy;
910 bool isSelOpaque = false;
911 if (SelStructTy == 0) {
912 SelStructTy = llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, NULL);
913 SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy);
914 isSelOpaque = true;
915 }
916
Eli Friedman1b8956e2008-06-01 16:00:02 +0000917 // Name the ObjC types to make the IR a bit easier to read
Chris Lattnere160c9b2009-01-27 05:06:01 +0000918 TheModule.addTypeName(".objc_selector", SelStructPtrTy);
Eli Friedman1b8956e2008-06-01 16:00:02 +0000919 TheModule.addTypeName(".objc_id", IdTy);
920 TheModule.addTypeName(".objc_imp", IMPTy);
921
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000922 std::vector<llvm::Constant*> Elements;
Chris Lattner71238f62009-04-25 23:19:45 +0000923 llvm::Constant *Statics = NULLPtr;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000924 // Generate statics list:
Chris Lattner71238f62009-04-25 23:19:45 +0000925 if (ConstantStrings.size()) {
926 llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
927 ConstantStrings.size() + 1);
928 ConstantStrings.push_back(NULLPtr);
929 Elements.push_back(MakeConstantString("NSConstantString",
930 ".objc_static_class_name"));
931 Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy,
932 ConstantStrings));
933 llvm::StructType *StaticsListTy =
934 llvm::StructType::get(PtrToInt8Ty, StaticsArrayTy, NULL);
935 llvm::Type *StaticsListPtrTy = llvm::PointerType::getUnqual(StaticsListTy);
936 Statics = MakeGlobal(StaticsListTy, Elements, ".objc_statics");
937 llvm::ArrayType *StaticsListArrayTy =
938 llvm::ArrayType::get(StaticsListPtrTy, 2);
939 Elements.clear();
940 Elements.push_back(Statics);
941 Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
942 Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr");
943 Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
944 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000945 // Array of classes, categories, and constant objects
946 llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty,
947 Classes.size() + Categories.size() + 2);
Chris Lattnere160c9b2009-01-27 05:06:01 +0000948 llvm::StructType *SymTabTy = llvm::StructType::get(LongTy, SelStructPtrTy,
Chris Lattner630404b2008-06-26 04:10:42 +0000949 llvm::Type::Int16Ty,
950 llvm::Type::Int16Ty,
951 ClassListTy, NULL);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000952
953 Elements.clear();
954 // Pointer to an array of selectors used in this module.
955 std::vector<llvm::Constant*> Selectors;
956 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
957 iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end();
958 iter != iterEnd ; ++iter) {
Chris Lattner630404b2008-06-26 04:10:42 +0000959 Elements.push_back(MakeConstantString(iter->first.first, ".objc_sel_name"));
960 Elements.push_back(MakeConstantString(iter->first.second,
961 ".objc_sel_types"));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000962 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
963 Elements.clear();
964 }
965 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
966 iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
Chris Lattner630404b2008-06-26 04:10:42 +0000967 iter != iterEnd; ++iter) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000968 Elements.push_back(
Chris Lattner630404b2008-06-26 04:10:42 +0000969 MakeConstantString(iter->getKeyData(), ".objc_sel_name"));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000970 Elements.push_back(NULLPtr);
971 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
972 Elements.clear();
973 }
974 Elements.push_back(NULLPtr);
975 Elements.push_back(NULLPtr);
976 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
977 Elements.clear();
978 // Number of static selectors
979 Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() ));
980 llvm::Constant *SelectorList = MakeGlobal(
981 llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors,
982 ".objc_selector_list");
Chris Lattnere160c9b2009-01-27 05:06:01 +0000983 Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList,
984 SelStructPtrTy));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000985
986 // Now that all of the static selectors exist, create pointers to them.
987 int index = 0;
988 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
989 iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end();
990 iter != iterEnd; ++iter) {
991 llvm::Constant *Idxs[] = {Zeros[0],
992 llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]};
Chris Lattnere160c9b2009-01-27 05:06:01 +0000993 llvm::Constant *SelPtr = new llvm::GlobalVariable(SelStructPtrTy,
994 true, llvm::GlobalValue::InternalLinkage,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000995 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
996 ".objc_sel_ptr", &TheModule);
Chris Lattnere160c9b2009-01-27 05:06:01 +0000997 // If selectors are defined as an opaque type, cast the pointer to this
998 // type.
999 if (isSelOpaque) {
1000 SelPtr = llvm::ConstantExpr::getBitCast(SelPtr,
1001 llvm::PointerType::getUnqual(SelectorTy));
1002 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001003 (*iter).second->setAliasee(SelPtr);
1004 }
1005 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
1006 iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
1007 iter != iterEnd; iter++) {
1008 llvm::Constant *Idxs[] = {Zeros[0],
1009 llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]};
Chris Lattnere160c9b2009-01-27 05:06:01 +00001010 llvm::Constant *SelPtr = new llvm::GlobalVariable(SelStructPtrTy, true,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001011 llvm::GlobalValue::InternalLinkage,
1012 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
1013 ".objc_sel_ptr", &TheModule);
Chris Lattnere160c9b2009-01-27 05:06:01 +00001014 // If selectors are defined as an opaque type, cast the pointer to this
1015 // type.
1016 if (isSelOpaque) {
1017 SelPtr = llvm::ConstantExpr::getBitCast(SelPtr,
1018 llvm::PointerType::getUnqual(SelectorTy));
1019 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001020 (*iter).second->setAliasee(SelPtr);
1021 }
1022 // Number of classes defined.
1023 Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty,
1024 Classes.size()));
1025 // Number of categories defined
1026 Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty,
1027 Categories.size()));
1028 // Create an array of classes, then categories, then static object instances
1029 Classes.insert(Classes.end(), Categories.begin(), Categories.end());
1030 // NULL-terminated list of static object instances (mainly constant strings)
1031 Classes.push_back(Statics);
1032 Classes.push_back(NULLPtr);
1033 llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes);
1034 Elements.push_back(ClassList);
1035 // Construct the symbol table
1036 llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements);
1037
1038 // The symbol table is contained in a module which has some version-checking
1039 // constants
1040 llvm::StructType * ModuleTy = llvm::StructType::get(LongTy, LongTy,
1041 PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL);
1042 Elements.clear();
1043 // Runtime version used for compatibility checking.
1044 Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
Fariborz Jahanian91a0b512009-04-01 19:49:42 +00001045 // sizeof(ModuleTy)
1046 llvm::TargetData td = llvm::TargetData::TargetData(&TheModule);
1047 Elements.push_back(llvm::ConstantInt::get(LongTy, td.getTypeSizeInBits(ModuleTy)/8));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001048 //FIXME: Should be the path to the file where this module was declared
1049 Elements.push_back(NULLPtr);
1050 Elements.push_back(SymTab);
1051 llvm::Value *Module = MakeGlobal(ModuleTy, Elements);
1052
1053 // Create the load function calling the runtime entry point with the module
1054 // structure
1055 std::vector<const llvm::Type*> VoidArgs;
1056 llvm::Function * LoadFunction = llvm::Function::Create(
1057 llvm::FunctionType::get(llvm::Type::VoidTy, VoidArgs, false),
1058 llvm::GlobalValue::InternalLinkage, ".objc_load_function",
1059 &TheModule);
1060 llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", LoadFunction);
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001061 CGBuilderTy Builder;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001062 Builder.SetInsertPoint(EntryBB);
Fariborz Jahanian26c82942009-03-30 18:02:14 +00001063
1064 std::vector<const llvm::Type*> Params(1,
1065 llvm::PointerType::getUnqual(ModuleTy));
1066 llvm::Value *Register = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
1067 llvm::Type::VoidTy, Params, true), "__objc_exec_class");
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001068 Builder.CreateCall(Register, Module);
1069 Builder.CreateRetVoid();
1070 return LoadFunction;
1071}
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001072
Fariborz Jahanian679a5022009-01-10 21:06:09 +00001073llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD,
1074 const ObjCContainerDecl *CD) {
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001075 const ObjCCategoryImplDecl *OCD =
Steve Naroff3e0a5402009-01-08 19:41:02 +00001076 dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext());
Chris Lattner077bf5e2008-11-24 03:33:13 +00001077 std::string CategoryName = OCD ? OCD->getNameAsString() : "";
1078 std::string ClassName = OMD->getClassInterface()->getNameAsString();
1079 std::string MethodName = OMD->getSelector().getAsString();
Douglas Gregorf8d49f62009-01-09 17:18:27 +00001080 bool isClassMethod = !OMD->isInstanceMethod();
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001081
Daniel Dunbar541b63b2009-02-02 23:23:47 +00001082 CodeGenTypes &Types = CGM.getTypes();
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00001083 const llvm::FunctionType *MethodTy =
Daniel Dunbar541b63b2009-02-02 23:23:47 +00001084 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001085 std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
1086 MethodName, isClassMethod);
1087
Gabor Greif984d0b42008-04-06 20:42:52 +00001088 llvm::Function *Method = llvm::Function::Create(MethodTy,
Chris Lattner391d77a2008-03-30 23:03:07 +00001089 llvm::GlobalValue::InternalLinkage,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001090 FunctionName,
Chris Lattner391d77a2008-03-30 23:03:07 +00001091 &TheModule);
Chris Lattner391d77a2008-03-30 23:03:07 +00001092 return Method;
1093}
1094
Daniel Dunbar49f66022008-09-24 03:38:44 +00001095llvm::Function *CGObjCGNU::GetPropertyGetFunction() {
1096 return 0;
1097}
1098
1099llvm::Function *CGObjCGNU::GetPropertySetFunction() {
1100 return 0;
1101}
1102
1103llvm::Function *CGObjCGNU::EnumerationMutationFunction() {
Fariborz Jahanian26c82942009-03-30 18:02:14 +00001104 std::vector<const llvm::Type*> Params(1, IdTy);
1105 return cast<llvm::Function>(CGM.CreateRuntimeFunction(
1106 llvm::FunctionType::get(llvm::Type::VoidTy, Params, true),
1107 "objc_enumerationMutation"));
Anders Carlsson2abd89c2008-08-31 04:05:03 +00001108}
1109
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00001110void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1111 const Stmt &S) {
1112 CGF.ErrorUnsupported(&S, "@try/@synchronized statement");
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00001113}
1114
1115void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar49f66022008-09-24 03:38:44 +00001116 const ObjCAtThrowStmt &S) {
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00001117 CGF.ErrorUnsupported(&S, "@throw statement");
1118}
1119
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001120llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00001121 llvm::Value *AddrWeakObj)
1122{
1123 return 0;
1124}
1125
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001126void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1127 llvm::Value *src, llvm::Value *dst)
1128{
1129 return;
1130}
1131
Fariborz Jahanian58626502008-11-19 00:59:10 +00001132void CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1133 llvm::Value *src, llvm::Value *dst)
1134{
1135 return;
1136}
1137
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00001138void CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1139 llvm::Value *src, llvm::Value *dst)
1140{
1141 return;
1142}
1143
Fariborz Jahanian58626502008-11-19 00:59:10 +00001144void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1145 llvm::Value *src, llvm::Value *dst)
1146{
1147 return;
1148}
1149
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001150LValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1151 QualType ObjectTy,
1152 llvm::Value *BaseValue,
1153 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001154 unsigned CVRQualifiers) {
Daniel Dunbar525c9b72009-04-21 01:19:28 +00001155 const ObjCInterfaceDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl();
Daniel Dunbar97776872009-04-22 07:32:20 +00001156 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
1157 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00001158}
1159
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001160llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001161 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001162 const ObjCIvarDecl *Ivar) {
Daniel Dunbar97776872009-04-22 07:32:20 +00001163 uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar);
Daniel Dunbar84ad77a2009-04-22 09:39:34 +00001164 return llvm::ConstantInt::get(LongTy, Offset);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001165}
1166
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001167CodeGen::CGObjCRuntime *CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM){
Chris Lattnerdce14062008-06-26 04:19:03 +00001168 return new CGObjCGNU(CGM);
Chris Lattner0f984262008-03-01 08:50:34 +00001169}