blob: 2bbbb46cd0b8b0589ebd3474f928df8251741455 [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"
Chris Lattner0f984262008-03-01 08:50:34 +000023#include "llvm/Module.h"
Chris Lattner0f984262008-03-01 08:50:34 +000024#include "llvm/ADT/SmallVector.h"
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000025#include "llvm/ADT/StringMap.h"
Daniel Dunbar7ded7f42008-08-15 22:20:32 +000026#include "llvm/Support/Compiler.h"
27#include "llvm/Support/IRBuilder.h"
28#include "llvm/Target/TargetData.h"
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000029#include <map>
Chris Lattnerdce14062008-06-26 04:19:03 +000030using namespace clang;
Daniel Dunbar46f45b92008-09-09 01:06:48 +000031using namespace CodeGen;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000032using llvm::dyn_cast;
33
34// The version of the runtime that this class targets. Must match the version
35// in the runtime.
36static const int RuntimeVersion = 8;
37static const int ProtocolVersion = 2;
Chris Lattner0f984262008-03-01 08:50:34 +000038
Chris Lattner0f984262008-03-01 08:50:34 +000039namespace {
Chris Lattnerdce14062008-06-26 04:19:03 +000040class CGObjCGNU : public CodeGen::CGObjCRuntime {
Chris Lattner0f984262008-03-01 08:50:34 +000041private:
Chris Lattnerdce14062008-06-26 04:19:03 +000042 CodeGen::CodeGenModule &CGM;
Chris Lattner0f984262008-03-01 08:50:34 +000043 llvm::Module &TheModule;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000044 const llvm::StructType *SelStructTy;
Chris Lattner391d77a2008-03-30 23:03:07 +000045 const llvm::Type *SelectorTy;
46 const llvm::Type *PtrToInt8Ty;
47 const llvm::Type *IMPTy;
48 const llvm::Type *IdTy;
49 const llvm::Type *IntTy;
50 const llvm::Type *PtrTy;
51 const llvm::Type *LongTy;
52 const llvm::Type *PtrToIntTy;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000053 std::vector<llvm::Constant*> Classes;
54 std::vector<llvm::Constant*> Categories;
55 std::vector<llvm::Constant*> ConstantStrings;
56 llvm::Function *LoadFunction;
57 llvm::StringMap<llvm::Constant*> ExistingProtocols;
58 typedef std::pair<std::string, std::string> TypedSelector;
59 std::map<TypedSelector, llvm::GlobalAlias*> TypedSelectors;
60 llvm::StringMap<llvm::GlobalAlias*> UntypedSelectors;
61 // Some zeros used for GEPs in lots of places.
62 llvm::Constant *Zeros[2];
63 llvm::Constant *NULLPtr;
64private:
65 llvm::Constant *GenerateIvarList(
66 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
67 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
68 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets);
69 llvm::Constant *GenerateMethodList(const std::string &ClassName,
70 const std::string &CategoryName,
Chris Lattnera4210072008-06-26 05:08:00 +000071 const llvm::SmallVectorImpl<Selector> &MethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000072 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
73 bool isClassMethodList);
74 llvm::Constant *GenerateProtocolList(
75 const llvm::SmallVectorImpl<std::string> &Protocols);
76 llvm::Constant *GenerateClassStructure(
77 llvm::Constant *MetaClass,
78 llvm::Constant *SuperClass,
79 unsigned info,
Chris Lattnerd002cc62008-06-26 04:47:04 +000080 const char *Name,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000081 llvm::Constant *Version,
82 llvm::Constant *InstanceSize,
83 llvm::Constant *IVars,
84 llvm::Constant *Methods,
85 llvm::Constant *Protocols);
86 llvm::Constant *GenerateProtocolMethodList(
87 const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
88 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes);
89 llvm::Constant *MakeConstantString(const std::string &Str, const std::string
90 &Name="");
91 llvm::Constant *MakeGlobal(const llvm::StructType *Ty,
92 std::vector<llvm::Constant*> &V, const std::string &Name="");
93 llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty,
94 std::vector<llvm::Constant*> &V, const std::string &Name="");
Chris Lattner0f984262008-03-01 08:50:34 +000095public:
Chris Lattnerdce14062008-06-26 04:19:03 +000096 CGObjCGNU(CodeGen::CodeGenModule &cgm);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000097 virtual llvm::Constant *GenerateConstantString(const std::string &String);
Daniel Dunbar8f2926b2008-08-23 03:46:30 +000098 virtual CodeGen::RValue
99 GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000100 QualType ResultType,
101 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000102 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000103 bool IsClassMessage,
104 const CallArgList &CallArgs);
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000105 virtual CodeGen::RValue
106 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000107 QualType ResultType,
108 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000109 const ObjCInterfaceDecl *Class,
110 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000111 bool IsClassMessage,
112 const CallArgList &CallArgs);
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +0000113 virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
114 const ObjCInterfaceDecl *OID);
Chris Lattner85e35682008-08-08 19:57:58 +0000115 virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel);
Chris Lattner8e67b632008-06-26 04:37:12 +0000116
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000117 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD);
118 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
119 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Chris Lattner85e35682008-08-08 19:57:58 +0000120 virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder<> &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000121 const ObjCProtocolDecl *PD);
122 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000123 virtual llvm::Function *ModuleInitFunction();
Anders Carlsson2abd89c2008-08-31 04:05:03 +0000124 virtual llvm::Function *EnumerationMutationFunction();
Chris Lattner0f984262008-03-01 08:50:34 +0000125};
126} // end anonymous namespace
127
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000128
129
130static std::string SymbolNameForClass(const std::string &ClassName) {
131 return ".objc_class_" + ClassName;
132}
133
134static std::string SymbolNameForMethod(const std::string &ClassName, const
135 std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
136{
137 return "._objc_method_" + ClassName +"("+CategoryName+")"+
138 (isClassMethod ? "+" : "-") + MethodName;
139}
140
Chris Lattnerdce14062008-06-26 04:19:03 +0000141CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
142 : CGM(cgm), TheModule(CGM.getModule()) {
143 IntTy = CGM.getTypes().ConvertType(CGM.getContext().IntTy);
144 LongTy = CGM.getTypes().ConvertType(CGM.getContext().LongTy);
145
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000146 Zeros[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
147 Zeros[1] = Zeros[0];
148 NULLPtr = llvm::ConstantPointerNull::get(
149 llvm::PointerType::getUnqual(llvm::Type::Int8Ty));
Chris Lattner391d77a2008-03-30 23:03:07 +0000150 // C string type. Used in lots of places.
151 PtrToInt8Ty =
152 llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
153 // Get the selector Type.
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000154 SelStructTy = llvm::StructType::get(
Chris Lattner391d77a2008-03-30 23:03:07 +0000155 PtrToInt8Ty,
156 PtrToInt8Ty,
157 NULL);
158 SelectorTy = llvm::PointerType::getUnqual(SelStructTy);
159 PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
160 PtrTy = PtrToInt8Ty;
161
162 // Object type
163 llvm::PATypeHolder OpaqueObjTy = llvm::OpaqueType::get();
164 llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy);
165 IdTy = llvm::StructType::get(OpaqueIdTy, NULL);
166 llvm::cast<llvm::OpaqueType>(OpaqueObjTy.get())->refineAbstractTypeTo(IdTy);
167 IdTy = llvm::cast<llvm::StructType>(OpaqueObjTy.get());
168 IdTy = llvm::PointerType::getUnqual(IdTy);
169
170 // IMP type
171 std::vector<const llvm::Type*> IMPArgs;
172 IMPArgs.push_back(IdTy);
173 IMPArgs.push_back(SelectorTy);
174 IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000175}
176// This has to perform the lookup every time, since posing and related
177// techniques can modify the name -> class mapping.
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +0000178llvm::Value *CGObjCGNU::GetClass(llvm::IRBuilder<> &Builder,
179 const ObjCInterfaceDecl *OID) {
180 llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getName());
181 ClassName = Builder.CreateStructGEP(ClassName, 0);
182
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000183 llvm::Constant *ClassLookupFn =
184 TheModule.getOrInsertFunction("objc_lookup_class", IdTy, PtrToInt8Ty,
185 NULL);
186 return Builder.CreateCall(ClassLookupFn, ClassName);
Chris Lattner391d77a2008-03-30 23:03:07 +0000187}
188
Chris Lattner8e67b632008-06-26 04:37:12 +0000189/// GetSelector - Return the pointer to the unique'd string for this selector.
Chris Lattner85e35682008-08-08 19:57:58 +0000190llvm::Value *CGObjCGNU::GetSelector(llvm::IRBuilder<> &Builder, Selector Sel) {
Chris Lattner8e67b632008-06-26 04:37:12 +0000191 // FIXME: uniquing on the string is wasteful, unique on Sel instead!
192 llvm::GlobalAlias *&US = UntypedSelectors[Sel.getName()];
193 if (US == 0)
194 US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy),
195 llvm::GlobalValue::InternalLinkage,
196 ".objc_untyped_selector_alias",
197 NULL, &TheModule);
198
199 return Builder.CreateLoad(US);
200
201}
202
Chris Lattner5e7dcc62008-06-26 04:44:19 +0000203llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str,
204 const std::string &Name) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000205 llvm::Constant * ConstStr = llvm::ConstantArray::get(Str);
206 ConstStr = new llvm::GlobalVariable(ConstStr->getType(), true,
207 llvm::GlobalValue::InternalLinkage,
208 ConstStr, Name, &TheModule);
209 return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
210}
211llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty,
212 std::vector<llvm::Constant*> &V, const std::string &Name) {
213 llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
214 return new llvm::GlobalVariable(Ty, false,
215 llvm::GlobalValue::InternalLinkage, C, Name, &TheModule);
216}
217llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
218 std::vector<llvm::Constant*> &V, const std::string &Name) {
219 llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
220 return new llvm::GlobalVariable(Ty, false,
221 llvm::GlobalValue::InternalLinkage, C, Name, &TheModule);
222}
223
224/// Generate an NSConstantString object.
225//TODO: In case there are any crazy people still using the GNU runtime without
226//an OpenStep implementation, this should let them select their own class for
227//constant strings.
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000228llvm::Constant *CGObjCGNU::GenerateConstantString(const std::string &Str) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000229 std::vector<llvm::Constant*> Ivars;
230 Ivars.push_back(NULLPtr);
Chris Lattner13fd7e52008-06-21 21:44:18 +0000231 Ivars.push_back(MakeConstantString(Str));
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000232 Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000233 llvm::Constant *ObjCStr = MakeGlobal(
234 llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL),
235 Ivars, ".objc_str");
236 ConstantStrings.push_back(
237 llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty));
238 return ObjCStr;
239}
240
241///Generates a message send where the super is the receiver. This is a message
242///send to self with special delivery semantics indicating which class's method
243///should be called.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000244CodeGen::RValue
245CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000246 QualType ResultType,
247 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000248 const ObjCInterfaceDecl *Class,
249 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000250 bool IsClassMessage,
251 const CallArgList &CallArgs) {
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000252 const ObjCInterfaceDecl *SuperClass = Class->getSuperClass();
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000253 const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000254 // TODO: This should be cached, not looked up every time.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000255 llvm::Value *ReceiverClass = GetClass(CGF.Builder, SuperClass);
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000256 llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
Chris Lattner0f984262008-03-01 08:50:34 +0000257 std::vector<const llvm::Type*> impArgTypes;
258 impArgTypes.push_back(Receiver->getType());
Chris Lattner391d77a2008-03-30 23:03:07 +0000259 impArgTypes.push_back(SelectorTy);
Chris Lattner0f984262008-03-01 08:50:34 +0000260
261 // Avoid an explicit cast on the IMP by getting a version that has the right
262 // return type.
263 llvm::FunctionType *impType = llvm::FunctionType::get(ReturnTy, impArgTypes,
264 true);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000265 // Construct the structure used to look up the IMP
266 llvm::StructType *ObjCSuperTy = llvm::StructType::get(Receiver->getType(),
267 IdTy, NULL);
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000268 llvm::Value *ObjCSuper = CGF.Builder.CreateAlloca(ObjCSuperTy);
Eli Friedman1e692ac2008-06-13 23:01:12 +0000269 // FIXME: volatility
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000270 CGF.Builder.CreateStore(Receiver, CGF.Builder.CreateStructGEP(ObjCSuper, 0));
271 CGF.Builder.CreateStore(ReceiverClass, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000272
273 // Get the IMP
274 llvm::Constant *lookupFunction =
275 TheModule.getOrInsertFunction("objc_msg_lookup_super",
276 llvm::PointerType::getUnqual(impType),
277 llvm::PointerType::getUnqual(ObjCSuperTy),
278 SelectorTy, NULL);
279 llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000280 llvm::Value *imp = CGF.Builder.CreateCall(lookupFunction, lookupArgs,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000281 lookupArgs+2);
282
283 // Call the method
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000284 CallArgList ActualArgs;
Daniel Dunbar46f45b92008-09-09 01:06:48 +0000285 ActualArgs.push_back(std::make_pair(RValue::get(Receiver),
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000286 CGF.getContext().getObjCIdType()));
Daniel Dunbar46f45b92008-09-09 01:06:48 +0000287 ActualArgs.push_back(std::make_pair(RValue::get(cmd),
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000288 CGF.getContext().getObjCSelType()));
289 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000290 return CGF.EmitCall(imp, ResultType, ActualArgs);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000291}
292
293/// Generate code for a message send expression.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000294CodeGen::RValue
295CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000296 QualType ResultType,
297 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000298 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000299 bool IsClassMessage,
300 const CallArgList &CallArgs) {
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000301 const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
302 llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000303
304 // Look up the method implementation.
305 std::vector<const llvm::Type*> impArgTypes;
306 const llvm::Type *RetTy;
307 //TODO: Revisit this when LLVM supports aggregate return types.
308 if (ReturnTy->isSingleValueType() && ReturnTy != llvm::Type::VoidTy) {
309 RetTy = ReturnTy;
310 } else {
311 // For struct returns allocate the space in the caller and pass it up to
312 // the sender.
313 RetTy = llvm::Type::VoidTy;
314 impArgTypes.push_back(llvm::PointerType::getUnqual(ReturnTy));
315 }
316 impArgTypes.push_back(Receiver->getType());
317 impArgTypes.push_back(SelectorTy);
318
319 // Avoid an explicit cast on the IMP by getting a version that has the right
320 // return type.
321 llvm::FunctionType *impType = llvm::FunctionType::get(RetTy, impArgTypes,
322 true);
Chris Lattner0f984262008-03-01 08:50:34 +0000323
324 llvm::Constant *lookupFunction =
325 TheModule.getOrInsertFunction("objc_msg_lookup",
Chris Lattner391d77a2008-03-30 23:03:07 +0000326 llvm::PointerType::getUnqual(impType),
327 Receiver->getType(), SelectorTy, NULL);
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000328 llvm::Value *imp = CGF.Builder.CreateCall2(lookupFunction, Receiver, cmd);
Chris Lattner3eae03e2008-05-06 00:56:42 +0000329
330 // Call the method.
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000331 CallArgList ActualArgs;
Daniel Dunbar46f45b92008-09-09 01:06:48 +0000332 ActualArgs.push_back(std::make_pair(RValue::get(Receiver),
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000333 CGF.getContext().getObjCIdType()));
Daniel Dunbar46f45b92008-09-09 01:06:48 +0000334 ActualArgs.push_back(std::make_pair(RValue::get(cmd),
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000335 CGF.getContext().getObjCSelType()));
336 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000337 return CGF.EmitCall(imp, ResultType, ActualArgs);
Chris Lattner0f984262008-03-01 08:50:34 +0000338}
339
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000340/// Generates a MethodList. Used in construction of a objc_class and
341/// objc_category structures.
342llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName,
Chris Lattnera4210072008-06-26 05:08:00 +0000343 const std::string &CategoryName,
344 const llvm::SmallVectorImpl<Selector> &MethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000345 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
346 bool isClassMethodList) {
347 // Get the method structure type.
348 llvm::StructType *ObjCMethodTy = llvm::StructType::get(
349 PtrToInt8Ty, // Really a selector, but the runtime creates it us.
350 PtrToInt8Ty, // Method types
351 llvm::PointerType::getUnqual(IMPTy), //Method pointer
352 NULL);
353 std::vector<llvm::Constant*> Methods;
354 std::vector<llvm::Constant*> Elements;
355 for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
356 Elements.clear();
Daniel Dunbar61432932008-08-13 23:20:05 +0000357 llvm::Constant *C = CGM.GetAddrOfConstantCString(MethodSels[i].getName());
Chris Lattnera4210072008-06-26 05:08:00 +0000358 Elements.push_back(llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000359 Elements.push_back(
360 llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
361 llvm::Constant *Method =
362 TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
Chris Lattnera4210072008-06-26 05:08:00 +0000363 MethodSels[i].getName(),
Chris Lattner550b8db2008-06-26 04:05:20 +0000364 isClassMethodList));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000365 Method = llvm::ConstantExpr::getBitCast(Method,
366 llvm::PointerType::getUnqual(IMPTy));
367 Elements.push_back(Method);
368 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements));
369 }
370
371 // Array of method structures
372 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
Chris Lattnera4210072008-06-26 05:08:00 +0000373 MethodSels.size());
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000374 llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy,
Chris Lattnerfba67632008-06-26 04:52:29 +0000375 Methods);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000376
377 // Structure containing list pointer, array and array count
378 llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields;
379 llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get();
380 llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy);
381 llvm::StructType *ObjCMethodListTy = llvm::StructType::get(NextPtrTy,
382 IntTy,
383 ObjCMethodArrayTy,
384 NULL);
385 // Refine next pointer type to concrete type
386 llvm::cast<llvm::OpaqueType>(
387 OpaqueNextTy.get())->refineAbstractTypeTo(ObjCMethodListTy);
388 ObjCMethodListTy = llvm::cast<llvm::StructType>(OpaqueNextTy.get());
389
390 Methods.clear();
391 Methods.push_back(llvm::ConstantPointerNull::get(
392 llvm::PointerType::getUnqual(ObjCMethodListTy)));
393 Methods.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty,
394 MethodTypes.size()));
395 Methods.push_back(MethodArray);
396
397 // Create an instance of the structure
398 return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list");
399}
400
401/// Generates an IvarList. Used in construction of a objc_class.
402llvm::Constant *CGObjCGNU::GenerateIvarList(
403 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
404 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
405 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) {
406 // Get the method structure type.
407 llvm::StructType *ObjCIvarTy = llvm::StructType::get(
408 PtrToInt8Ty,
409 PtrToInt8Ty,
410 IntTy,
411 NULL);
412 std::vector<llvm::Constant*> Ivars;
413 std::vector<llvm::Constant*> Elements;
414 for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
415 Elements.clear();
416 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarNames[i],
417 Zeros, 2));
418 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarTypes[i],
419 Zeros, 2));
420 Elements.push_back(IvarOffsets[i]);
421 Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements));
422 }
423
424 // Array of method structures
425 llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
426 IvarNames.size());
427
428
429 Elements.clear();
430 Elements.push_back(llvm::ConstantInt::get(
431 llvm::cast<llvm::IntegerType>(IntTy), (int)IvarNames.size()));
432 Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars));
433 // Structure containing array and array count
434 llvm::StructType *ObjCIvarListTy = llvm::StructType::get(IntTy,
435 ObjCIvarArrayTy,
436 NULL);
437
438 // Create an instance of the structure
439 return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list");
440}
441
442/// Generate a class structure
443llvm::Constant *CGObjCGNU::GenerateClassStructure(
444 llvm::Constant *MetaClass,
445 llvm::Constant *SuperClass,
446 unsigned info,
Chris Lattnerd002cc62008-06-26 04:47:04 +0000447 const char *Name,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000448 llvm::Constant *Version,
449 llvm::Constant *InstanceSize,
450 llvm::Constant *IVars,
451 llvm::Constant *Methods,
452 llvm::Constant *Protocols) {
453 // Set up the class structure
454 // Note: Several of these are char*s when they should be ids. This is
455 // because the runtime performs this translation on load.
456 llvm::StructType *ClassTy = llvm::StructType::get(
457 PtrToInt8Ty, // class_pointer
458 PtrToInt8Ty, // super_class
459 PtrToInt8Ty, // name
460 LongTy, // version
461 LongTy, // info
462 LongTy, // instance_size
463 IVars->getType(), // ivars
464 Methods->getType(), // methods
465 // These are all filled in by the runtime, so we pretend
466 PtrTy, // dtable
467 PtrTy, // subclass_list
468 PtrTy, // sibling_class
469 PtrTy, // protocols
470 PtrTy, // gc_object_type
471 NULL);
472 llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
473 llvm::Constant *NullP =
474 llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(PtrTy));
475 // Fill in the structure
476 std::vector<llvm::Constant*> Elements;
477 Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
478 Elements.push_back(SuperClass);
Chris Lattnerd002cc62008-06-26 04:47:04 +0000479 Elements.push_back(MakeConstantString(Name, ".class_name"));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000480 Elements.push_back(Zero);
481 Elements.push_back(llvm::ConstantInt::get(LongTy, info));
482 Elements.push_back(InstanceSize);
483 Elements.push_back(IVars);
484 Elements.push_back(Methods);
485 Elements.push_back(NullP);
486 Elements.push_back(NullP);
487 Elements.push_back(NullP);
488 Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
489 Elements.push_back(NullP);
490 // Create an instance of the structure
Chris Lattner1565e032008-07-21 06:31:05 +0000491 return MakeGlobal(ClassTy, Elements, SymbolNameForClass(Name));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000492}
493
494llvm::Constant *CGObjCGNU::GenerateProtocolMethodList(
495 const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
496 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes) {
497 // Get the method structure type.
498 llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(
499 PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
500 PtrToInt8Ty,
501 NULL);
502 std::vector<llvm::Constant*> Methods;
503 std::vector<llvm::Constant*> Elements;
504 for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
505 Elements.clear();
506 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(MethodNames[i],
507 Zeros, 2));
508 Elements.push_back(
509 llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
510 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements));
511 }
512 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
513 MethodNames.size());
514 llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy, Methods);
515 llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(
516 IntTy, ObjCMethodArrayTy, NULL);
517 Methods.clear();
518 Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
519 Methods.push_back(Array);
520 return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list");
521}
522// Create the protocol list structure used in classes, categories and so on
523llvm::Constant *CGObjCGNU::GenerateProtocolList(
524 const llvm::SmallVectorImpl<std::string> &Protocols) {
525 llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
526 Protocols.size());
527 llvm::StructType *ProtocolListTy = llvm::StructType::get(
528 PtrTy, //Should be a recurisve pointer, but it's always NULL here.
529 LongTy,//FIXME: Should be size_t
530 ProtocolArrayTy,
531 NULL);
532 std::vector<llvm::Constant*> Elements;
533 for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
534 iter != endIter ; iter++) {
535 llvm::Constant *Ptr =
536 llvm::ConstantExpr::getBitCast(ExistingProtocols[*iter], PtrToInt8Ty);
537 Elements.push_back(Ptr);
538 }
539 llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
540 Elements);
541 Elements.clear();
542 Elements.push_back(NULLPtr);
543 Elements.push_back(llvm::ConstantInt::get(
544 llvm::cast<llvm::IntegerType>(LongTy), Protocols.size()));
545 Elements.push_back(ProtocolArray);
546 return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list");
547}
548
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000549llvm::Value *CGObjCGNU::GenerateProtocolRef(llvm::IRBuilder<> &Builder,
550 const ObjCProtocolDecl *PD) {
551 return ExistingProtocols[PD->getName()];
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000552}
553
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000554void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
555 ASTContext &Context = CGM.getContext();
556 const char *ProtocolName = PD->getName();
557 llvm::SmallVector<std::string, 16> Protocols;
558 for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(),
559 E = PD->protocol_end(); PI != E; ++PI)
560 Protocols.push_back((*PI)->getName());
561 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames;
562 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
563 for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(),
564 E = PD->instmeth_end(); iter != E; iter++) {
565 std::string TypeStr;
566 Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
567 InstanceMethodNames.push_back(
Daniel Dunbar61432932008-08-13 23:20:05 +0000568 CGM.GetAddrOfConstantCString((*iter)->getSelector().getName()));
569 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000570 }
571 // Collect information about class methods:
572 llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames;
573 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
574 for (ObjCProtocolDecl::classmeth_iterator iter = PD->classmeth_begin(),
575 endIter = PD->classmeth_end() ; iter != endIter ; iter++) {
576 std::string TypeStr;
577 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
578 ClassMethodNames.push_back(
Daniel Dunbar61432932008-08-13 23:20:05 +0000579 CGM.GetAddrOfConstantCString((*iter)->getSelector().getName()));
580 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000581 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000582
583 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
584 llvm::Constant *InstanceMethodList =
585 GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes);
586 llvm::Constant *ClassMethodList =
587 GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes);
588 // Protocols are objects containing lists of the methods implemented and
589 // protocols adopted.
590 llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy,
591 PtrToInt8Ty,
592 ProtocolList->getType(),
593 InstanceMethodList->getType(),
594 ClassMethodList->getType(),
595 NULL);
596 std::vector<llvm::Constant*> Elements;
597 // The isa pointer must be set to a magic number so the runtime knows it's
598 // the correct layout.
599 Elements.push_back(llvm::ConstantExpr::getIntToPtr(
600 llvm::ConstantInt::get(llvm::Type::Int32Ty, ProtocolVersion), IdTy));
601 Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
602 Elements.push_back(ProtocolList);
603 Elements.push_back(InstanceMethodList);
604 Elements.push_back(ClassMethodList);
605 ExistingProtocols[ProtocolName] =
606 llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
607 ".objc_protocol"), IdTy);
608}
609
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000610void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
611 const char *ClassName = OCD->getClassInterface()->getName();
612 const char *CategoryName = OCD->getName();
613 // Collect information about instance methods
614 llvm::SmallVector<Selector, 16> InstanceMethodSels;
615 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
616 for (ObjCCategoryDecl::instmeth_iterator iter = OCD->instmeth_begin(),
617 endIter = OCD->instmeth_end() ; iter != endIter ; iter++) {
618 InstanceMethodSels.push_back((*iter)->getSelector());
619 std::string TypeStr;
620 CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
621 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
622 }
623
624 // Collect information about class methods
625 llvm::SmallVector<Selector, 16> ClassMethodSels;
626 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
627 for (ObjCCategoryDecl::classmeth_iterator iter = OCD->classmeth_begin(),
628 endIter = OCD->classmeth_end() ; iter != endIter ; iter++) {
629 ClassMethodSels.push_back((*iter)->getSelector());
630 std::string TypeStr;
631 CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
632 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
633 }
634
635 // Collect the names of referenced protocols
636 llvm::SmallVector<std::string, 16> Protocols;
637 const ObjCInterfaceDecl *ClassDecl = OCD->getClassInterface();
638 const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
639 for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
640 E = Protos.end(); I != E; ++I)
641 Protocols.push_back((*I)->getName());
642
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000643 std::vector<llvm::Constant*> Elements;
644 Elements.push_back(MakeConstantString(CategoryName));
645 Elements.push_back(MakeConstantString(ClassName));
646 // Instance method list
647 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattnera4210072008-06-26 05:08:00 +0000648 ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000649 false), PtrTy));
650 // Class method list
651 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattnera4210072008-06-26 05:08:00 +0000652 ClassName, CategoryName, ClassMethodSels, ClassMethodTypes, true),
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000653 PtrTy));
654 // Protocol list
655 Elements.push_back(llvm::ConstantExpr::getBitCast(
656 GenerateProtocolList(Protocols), PtrTy));
657 Categories.push_back(llvm::ConstantExpr::getBitCast(
658 MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, PtrTy,
659 PtrTy, PtrTy, NULL), Elements), PtrTy));
660}
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000661
662void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
663 ASTContext &Context = CGM.getContext();
664
665 // Get the superclass name.
666 const ObjCInterfaceDecl * SuperClassDecl =
667 OID->getClassInterface()->getSuperClass();
668 const char * SuperClassName = NULL;
669 if (SuperClassDecl) {
670 SuperClassName = SuperClassDecl->getName();
671 }
672
673 // Get the class name
674 ObjCInterfaceDecl * ClassDecl = (ObjCInterfaceDecl*)OID->getClassInterface();
675 const char * ClassName = ClassDecl->getName();
676
677 // Get the size of instances. For runtimes that support late-bound instances
678 // this should probably be something different (size just of instance
679 // varaibles in this class, not superclasses?).
680 int instanceSize = 0;
681 const llvm::Type *ObjTy = 0;
682 if (!LateBoundIVars()) {
683 ObjTy = CGM.getTypes().ConvertType(Context.getObjCInterfaceType(ClassDecl));
684 instanceSize = CGM.getTargetData().getABITypeSize(ObjTy);
685 } else {
686 // This is required by newer ObjC runtimes.
687 assert(0 && "Late-bound instance variables not yet supported");
688 }
689
690 // Collect information about instance variables.
691 llvm::SmallVector<llvm::Constant*, 16> IvarNames;
692 llvm::SmallVector<llvm::Constant*, 16> IvarTypes;
693 llvm::SmallVector<llvm::Constant*, 16> IvarOffsets;
694 const llvm::StructLayout *Layout =
695 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(ObjTy));
696 ObjTy = llvm::PointerType::getUnqual(ObjTy);
697 for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
698 endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
699 // Store the name
700 IvarNames.push_back(CGM.GetAddrOfConstantCString((*iter)->getName()));
701 // Get the type encoding for this ivar
702 std::string TypeStr;
703 llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes;
704 Context.getObjCEncodingForType((*iter)->getType(), TypeStr,
705 EncodingRecordTypes);
706 IvarTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
707 // Get the offset
708 int offset =
709 (int)Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(*iter));
710 IvarOffsets.push_back(
711 llvm::ConstantInt::get(llvm::Type::Int32Ty, offset));
712 }
713
714 // Collect information about instance methods
715 llvm::SmallVector<Selector, 16> InstanceMethodSels;
716 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
717 for (ObjCImplementationDecl::instmeth_iterator iter = OID->instmeth_begin(),
718 endIter = OID->instmeth_end() ; iter != endIter ; iter++) {
719 InstanceMethodSels.push_back((*iter)->getSelector());
720 std::string TypeStr;
721 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
722 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
723 }
724
725 // Collect information about class methods
726 llvm::SmallVector<Selector, 16> ClassMethodSels;
727 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
728 for (ObjCImplementationDecl::classmeth_iterator iter = OID->classmeth_begin(),
729 endIter = OID->classmeth_end() ; iter != endIter ; iter++) {
730 ClassMethodSels.push_back((*iter)->getSelector());
731 std::string TypeStr;
732 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
733 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
734 }
735 // Collect the names of referenced protocols
736 llvm::SmallVector<std::string, 16> Protocols;
737 const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
738 for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
739 E = Protos.end(); I != E; ++I)
740 Protocols.push_back((*I)->getName());
741
742
743
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000744 // Get the superclass pointer.
745 llvm::Constant *SuperClass;
746 if (SuperClassName) {
747 SuperClass = MakeConstantString(SuperClassName, ".super_class_name");
748 } else {
749 SuperClass = llvm::ConstantPointerNull::get(
750 llvm::cast<llvm::PointerType>(PtrToInt8Ty));
751 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000752 // Empty vector used to construct empty method lists
753 llvm::SmallVector<llvm::Constant*, 1> empty;
754 // Generate the method and instance variable lists
755 llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
Chris Lattnera4210072008-06-26 05:08:00 +0000756 InstanceMethodSels, InstanceMethodTypes, false);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000757 llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
Chris Lattnera4210072008-06-26 05:08:00 +0000758 ClassMethodSels, ClassMethodTypes, true);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000759 llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
760 IvarOffsets);
761 //Generate metaclass for class methods
762 llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
Chris Lattner1565e032008-07-21 06:31:05 +0000763 NULLPtr, 0x2L, /*name*/"", 0, Zeros[0], GenerateIvarList(
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000764 empty, empty, empty), ClassMethodList, NULLPtr);
765 // Generate the class structure
766 llvm::Constant *ClassStruct = GenerateClassStructure(MetaClassStruct,
Chris Lattnerd002cc62008-06-26 04:47:04 +0000767 SuperClass, 0x1L, ClassName, 0,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000768 llvm::ConstantInt::get(llvm::Type::Int32Ty, instanceSize), IvarList,
769 MethodList, GenerateProtocolList(Protocols));
770 // Add class structure to list to be added to the symtab later
771 ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty);
772 Classes.push_back(ClassStruct);
773}
774
775llvm::Function *CGObjCGNU::ModuleInitFunction() {
776 // Only emit an ObjC load function if no Objective-C stuff has been called
777 if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
778 ExistingProtocols.empty() && TypedSelectors.empty() &&
Anton Korobeynikov5f58b912008-06-01 15:14:46 +0000779 UntypedSelectors.empty())
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000780 return NULL;
Eli Friedman1b8956e2008-06-01 16:00:02 +0000781
782 // Name the ObjC types to make the IR a bit easier to read
783 TheModule.addTypeName(".objc_selector", SelectorTy);
784 TheModule.addTypeName(".objc_id", IdTy);
785 TheModule.addTypeName(".objc_imp", IMPTy);
786
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000787 std::vector<llvm::Constant*> Elements;
788 // Generate statics list:
789 llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
790 ConstantStrings.size() + 1);
791 ConstantStrings.push_back(NULLPtr);
792 Elements.push_back(MakeConstantString("NSConstantString",
793 ".objc_static_class_name"));
794 Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy, ConstantStrings));
795 llvm::StructType *StaticsListTy =
796 llvm::StructType::get(PtrToInt8Ty, StaticsArrayTy, NULL);
Chris Lattner630404b2008-06-26 04:10:42 +0000797 llvm::Type *StaticsListPtrTy = llvm::PointerType::getUnqual(StaticsListTy);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000798 llvm::Constant *Statics =
799 MakeGlobal(StaticsListTy, Elements, ".objc_statics");
Chris Lattner4e0b2642008-06-24 17:01:28 +0000800 llvm::ArrayType *StaticsListArrayTy =
Chris Lattner630404b2008-06-26 04:10:42 +0000801 llvm::ArrayType::get(StaticsListPtrTy, 2);
Chris Lattner4e0b2642008-06-24 17:01:28 +0000802 Elements.clear();
803 Elements.push_back(Statics);
Chris Lattner630404b2008-06-26 04:10:42 +0000804 Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
Chris Lattner4e0b2642008-06-24 17:01:28 +0000805 Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr");
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000806 Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
807 // Array of classes, categories, and constant objects
808 llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty,
809 Classes.size() + Categories.size() + 2);
Chris Lattner630404b2008-06-26 04:10:42 +0000810 llvm::StructType *SymTabTy = llvm::StructType::get(LongTy, SelectorTy,
811 llvm::Type::Int16Ty,
812 llvm::Type::Int16Ty,
813 ClassListTy, NULL);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000814
815 Elements.clear();
816 // Pointer to an array of selectors used in this module.
817 std::vector<llvm::Constant*> Selectors;
818 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
819 iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end();
820 iter != iterEnd ; ++iter) {
Chris Lattner630404b2008-06-26 04:10:42 +0000821 Elements.push_back(MakeConstantString(iter->first.first, ".objc_sel_name"));
822 Elements.push_back(MakeConstantString(iter->first.second,
823 ".objc_sel_types"));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000824 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
825 Elements.clear();
826 }
827 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
828 iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
Chris Lattner630404b2008-06-26 04:10:42 +0000829 iter != iterEnd; ++iter) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000830 Elements.push_back(
Chris Lattner630404b2008-06-26 04:10:42 +0000831 MakeConstantString(iter->getKeyData(), ".objc_sel_name"));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000832 Elements.push_back(NULLPtr);
833 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
834 Elements.clear();
835 }
836 Elements.push_back(NULLPtr);
837 Elements.push_back(NULLPtr);
838 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
839 Elements.clear();
840 // Number of static selectors
841 Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() ));
842 llvm::Constant *SelectorList = MakeGlobal(
843 llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors,
844 ".objc_selector_list");
845 Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList, SelectorTy));
846
847 // Now that all of the static selectors exist, create pointers to them.
848 int index = 0;
849 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
850 iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end();
851 iter != iterEnd; ++iter) {
852 llvm::Constant *Idxs[] = {Zeros[0],
853 llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]};
854 llvm::GlobalVariable *SelPtr = new llvm::GlobalVariable(SelectorTy, true,
855 llvm::GlobalValue::InternalLinkage,
856 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
857 ".objc_sel_ptr", &TheModule);
858 (*iter).second->setAliasee(SelPtr);
859 }
860 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
861 iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
862 iter != iterEnd; iter++) {
863 llvm::Constant *Idxs[] = {Zeros[0],
864 llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]};
865 llvm::GlobalVariable *SelPtr = new llvm::GlobalVariable(SelectorTy, true,
866 llvm::GlobalValue::InternalLinkage,
867 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
868 ".objc_sel_ptr", &TheModule);
869 (*iter).second->setAliasee(SelPtr);
870 }
871 // Number of classes defined.
872 Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty,
873 Classes.size()));
874 // Number of categories defined
875 Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty,
876 Categories.size()));
877 // Create an array of classes, then categories, then static object instances
878 Classes.insert(Classes.end(), Categories.begin(), Categories.end());
879 // NULL-terminated list of static object instances (mainly constant strings)
880 Classes.push_back(Statics);
881 Classes.push_back(NULLPtr);
882 llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes);
883 Elements.push_back(ClassList);
884 // Construct the symbol table
885 llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements);
886
887 // The symbol table is contained in a module which has some version-checking
888 // constants
889 llvm::StructType * ModuleTy = llvm::StructType::get(LongTy, LongTy,
890 PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL);
891 Elements.clear();
892 // Runtime version used for compatibility checking.
893 Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
894 //FIXME: Should be sizeof(ModuleTy)
895 Elements.push_back(llvm::ConstantInt::get(LongTy, 16));
896 //FIXME: Should be the path to the file where this module was declared
897 Elements.push_back(NULLPtr);
898 Elements.push_back(SymTab);
899 llvm::Value *Module = MakeGlobal(ModuleTy, Elements);
900
901 // Create the load function calling the runtime entry point with the module
902 // structure
903 std::vector<const llvm::Type*> VoidArgs;
904 llvm::Function * LoadFunction = llvm::Function::Create(
905 llvm::FunctionType::get(llvm::Type::VoidTy, VoidArgs, false),
906 llvm::GlobalValue::InternalLinkage, ".objc_load_function",
907 &TheModule);
908 llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", LoadFunction);
Chris Lattner85e35682008-08-08 19:57:58 +0000909 llvm::IRBuilder<> Builder;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000910 Builder.SetInsertPoint(EntryBB);
911 llvm::Value *Register = TheModule.getOrInsertFunction("__objc_exec_class",
912 llvm::Type::VoidTy, llvm::PointerType::getUnqual(ModuleTy), NULL);
913 Builder.CreateCall(Register, Module);
914 Builder.CreateRetVoid();
915 return LoadFunction;
916}
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000917
918llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD) {
919 const llvm::Type *ReturnTy =
920 CGM.getTypes().ConvertReturnType(OMD->getResultType());
921 const ObjCCategoryImplDecl *OCD =
922 dyn_cast<ObjCCategoryImplDecl>(OMD->getMethodContext());
923 const std::string &CategoryName = OCD ? OCD->getName() : "";
924 const llvm::Type *SelfTy = llvm::PointerType::getUnqual(llvm::Type::Int32Ty);
925 const std::string &ClassName = OMD->getClassInterface()->getName();
926 const std::string &MethodName = OMD->getSelector().getName();
927 unsigned ArgC = OMD->param_size();
928 bool isClassMethod = !OMD->isInstance();
929 bool isVarArg = OMD->isVariadic();
930
931 llvm::SmallVector<const llvm::Type *, 16> ArgTy;
932 for (unsigned i=0 ; i<OMD->param_size() ; i++) {
933 const llvm::Type *Ty =
934 CGM.getTypes().ConvertType(OMD->getParamDecl(i)->getType());
935 if (Ty->isFirstClassType())
936 ArgTy.push_back(Ty);
937 else
938 ArgTy.push_back(llvm::PointerType::getUnqual(Ty));
939 }
940
Chris Lattner391d77a2008-03-30 23:03:07 +0000941 std::vector<const llvm::Type*> Args;
Chris Lattner8fdf3282008-06-24 17:04:18 +0000942 if (!ReturnTy->isSingleValueType() && ReturnTy != llvm::Type::VoidTy) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000943 Args.push_back(llvm::PointerType::getUnqual(ReturnTy));
944 ReturnTy = llvm::Type::VoidTy;
945 }
Chris Lattner391d77a2008-03-30 23:03:07 +0000946 Args.push_back(SelfTy);
947 Args.push_back(SelectorTy);
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000948 Args.insert(Args.end(), ArgTy.begin(), ArgTy.begin()+ArgC);
Chris Lattner391d77a2008-03-30 23:03:07 +0000949
950 llvm::FunctionType *MethodTy = llvm::FunctionType::get(ReturnTy,
951 Args,
952 isVarArg);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000953 std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
954 MethodName, isClassMethod);
955
Gabor Greif984d0b42008-04-06 20:42:52 +0000956 llvm::Function *Method = llvm::Function::Create(MethodTy,
Chris Lattner391d77a2008-03-30 23:03:07 +0000957 llvm::GlobalValue::InternalLinkage,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000958 FunctionName,
Chris Lattner391d77a2008-03-30 23:03:07 +0000959 &TheModule);
Chris Lattner391d77a2008-03-30 23:03:07 +0000960 return Method;
961}
962
Anders Carlsson2abd89c2008-08-31 04:05:03 +0000963llvm::Function *CGObjCGNU::EnumerationMutationFunction()
964{
965 assert(0 && "No enumeration mutation function in the GNU runtime!");
966
967 return 0;
968}
969
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000970CodeGen::CGObjCRuntime *CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM){
Chris Lattnerdce14062008-06-26 04:19:03 +0000971 return new CGObjCGNU(CGM);
Chris Lattner0f984262008-03-01 08:50:34 +0000972}