blob: b64f365832ddc1f7af83f1ca0dd166680dd1a75d [file] [log] [blame]
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +00001//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
Chris Lattnera0fd5ee2008-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 Korobeynikovcd5d08d2008-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 Lattnera0fd5ee2008-03-01 08:50:34 +000014//
15//===----------------------------------------------------------------------===//
16
17#include "CGObjCRuntime.h"
Chris Lattner547907c2008-06-26 04:19:03 +000018#include "CodeGenModule.h"
Daniel Dunbara04840b2008-08-23 03:46:30 +000019#include "CodeGenFunction.h"
Chris Lattner547907c2008-06-26 04:19:03 +000020#include "clang/AST/ASTContext.h"
Daniel Dunbarde300732008-08-11 04:54:23 +000021#include "clang/AST/Decl.h"
Daniel Dunbar84bb85f2008-08-13 00:59:25 +000022#include "clang/AST/DeclObjC.h"
Chris Lattnera0fd5ee2008-03-01 08:50:34 +000023#include "llvm/Module.h"
Chris Lattnera0fd5ee2008-03-01 08:50:34 +000024#include "llvm/ADT/SmallVector.h"
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +000025#include "llvm/ADT/StringMap.h"
Daniel Dunbarac93e472008-08-15 22:20:32 +000026#include "llvm/Support/Compiler.h"
27#include "llvm/Support/IRBuilder.h"
28#include "llvm/Target/TargetData.h"
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +000029#include <map>
Chris Lattner547907c2008-06-26 04:19:03 +000030using namespace clang;
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +000031using llvm::dyn_cast;
32
33// The version of the runtime that this class targets. Must match the version
34// in the runtime.
35static const int RuntimeVersion = 8;
36static const int ProtocolVersion = 2;
Chris Lattnera0fd5ee2008-03-01 08:50:34 +000037
Chris Lattnera0fd5ee2008-03-01 08:50:34 +000038namespace {
Chris Lattner547907c2008-06-26 04:19:03 +000039class CGObjCGNU : public CodeGen::CGObjCRuntime {
Chris Lattnera0fd5ee2008-03-01 08:50:34 +000040private:
Chris Lattner547907c2008-06-26 04:19:03 +000041 CodeGen::CodeGenModule &CGM;
Chris Lattnera0fd5ee2008-03-01 08:50:34 +000042 llvm::Module &TheModule;
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +000043 const llvm::StructType *SelStructTy;
Chris Lattnerb326b172008-03-30 23:03:07 +000044 const llvm::Type *SelectorTy;
45 const llvm::Type *PtrToInt8Ty;
46 const llvm::Type *IMPTy;
47 const llvm::Type *IdTy;
48 const llvm::Type *IntTy;
49 const llvm::Type *PtrTy;
50 const llvm::Type *LongTy;
51 const llvm::Type *PtrToIntTy;
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +000052 std::vector<llvm::Constant*> Classes;
53 std::vector<llvm::Constant*> Categories;
54 std::vector<llvm::Constant*> ConstantStrings;
55 llvm::Function *LoadFunction;
56 llvm::StringMap<llvm::Constant*> ExistingProtocols;
57 typedef std::pair<std::string, std::string> TypedSelector;
58 std::map<TypedSelector, llvm::GlobalAlias*> TypedSelectors;
59 llvm::StringMap<llvm::GlobalAlias*> UntypedSelectors;
60 // Some zeros used for GEPs in lots of places.
61 llvm::Constant *Zeros[2];
62 llvm::Constant *NULLPtr;
63private:
64 llvm::Constant *GenerateIvarList(
65 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
66 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
67 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets);
68 llvm::Constant *GenerateMethodList(const std::string &ClassName,
69 const std::string &CategoryName,
Chris Lattner578279d2008-06-26 05:08:00 +000070 const llvm::SmallVectorImpl<Selector> &MethodSels,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +000071 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
72 bool isClassMethodList);
73 llvm::Constant *GenerateProtocolList(
74 const llvm::SmallVectorImpl<std::string> &Protocols);
75 llvm::Constant *GenerateClassStructure(
76 llvm::Constant *MetaClass,
77 llvm::Constant *SuperClass,
78 unsigned info,
Chris Lattnerad9c3f32008-06-26 04:47:04 +000079 const char *Name,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +000080 llvm::Constant *Version,
81 llvm::Constant *InstanceSize,
82 llvm::Constant *IVars,
83 llvm::Constant *Methods,
84 llvm::Constant *Protocols);
85 llvm::Constant *GenerateProtocolMethodList(
86 const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
87 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes);
88 llvm::Constant *MakeConstantString(const std::string &Str, const std::string
89 &Name="");
90 llvm::Constant *MakeGlobal(const llvm::StructType *Ty,
91 std::vector<llvm::Constant*> &V, const std::string &Name="");
92 llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty,
93 std::vector<llvm::Constant*> &V, const std::string &Name="");
Chris Lattnera0fd5ee2008-03-01 08:50:34 +000094public:
Chris Lattner547907c2008-06-26 04:19:03 +000095 CGObjCGNU(CodeGen::CodeGenModule &cgm);
Daniel Dunbardaf4ad42008-08-12 00:12:39 +000096 virtual llvm::Constant *GenerateConstantString(const std::string &String);
Daniel Dunbara04840b2008-08-23 03:46:30 +000097 virtual CodeGen::RValue
98 GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
99 const ObjCMessageExpr *E,
100 llvm::Value *Receiver);
101 virtual CodeGen::RValue
102 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
103 const ObjCMessageExpr *E,
104 const ObjCInterfaceDecl *Super,
105 llvm::Value *Receiver);
Daniel Dunbar434627a2008-08-16 00:25:02 +0000106 virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
107 const ObjCInterfaceDecl *OID);
Chris Lattnerfaf23db2008-08-08 19:57:58 +0000108 virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel);
Chris Lattnerd71288e2008-06-26 04:37:12 +0000109
Daniel Dunbarac93e472008-08-15 22:20:32 +0000110 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD);
111 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
112 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Chris Lattnerfaf23db2008-08-08 19:57:58 +0000113 virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder<> &Builder,
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000114 const ObjCProtocolDecl *PD);
115 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000116 virtual llvm::Function *ModuleInitFunction();
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000117};
118} // end anonymous namespace
119
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000120
121
122static std::string SymbolNameForClass(const std::string &ClassName) {
123 return ".objc_class_" + ClassName;
124}
125
126static std::string SymbolNameForMethod(const std::string &ClassName, const
127 std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
128{
129 return "._objc_method_" + ClassName +"("+CategoryName+")"+
130 (isClassMethod ? "+" : "-") + MethodName;
131}
132
Chris Lattner547907c2008-06-26 04:19:03 +0000133CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
134 : CGM(cgm), TheModule(CGM.getModule()) {
135 IntTy = CGM.getTypes().ConvertType(CGM.getContext().IntTy);
136 LongTy = CGM.getTypes().ConvertType(CGM.getContext().LongTy);
137
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000138 Zeros[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
139 Zeros[1] = Zeros[0];
140 NULLPtr = llvm::ConstantPointerNull::get(
141 llvm::PointerType::getUnqual(llvm::Type::Int8Ty));
Chris Lattnerb326b172008-03-30 23:03:07 +0000142 // C string type. Used in lots of places.
143 PtrToInt8Ty =
144 llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
145 // Get the selector Type.
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000146 SelStructTy = llvm::StructType::get(
Chris Lattnerb326b172008-03-30 23:03:07 +0000147 PtrToInt8Ty,
148 PtrToInt8Ty,
149 NULL);
150 SelectorTy = llvm::PointerType::getUnqual(SelStructTy);
151 PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
152 PtrTy = PtrToInt8Ty;
153
154 // Object type
155 llvm::PATypeHolder OpaqueObjTy = llvm::OpaqueType::get();
156 llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy);
157 IdTy = llvm::StructType::get(OpaqueIdTy, NULL);
158 llvm::cast<llvm::OpaqueType>(OpaqueObjTy.get())->refineAbstractTypeTo(IdTy);
159 IdTy = llvm::cast<llvm::StructType>(OpaqueObjTy.get());
160 IdTy = llvm::PointerType::getUnqual(IdTy);
161
162 // IMP type
163 std::vector<const llvm::Type*> IMPArgs;
164 IMPArgs.push_back(IdTy);
165 IMPArgs.push_back(SelectorTy);
166 IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000167}
168// This has to perform the lookup every time, since posing and related
169// techniques can modify the name -> class mapping.
Daniel Dunbar434627a2008-08-16 00:25:02 +0000170llvm::Value *CGObjCGNU::GetClass(llvm::IRBuilder<> &Builder,
171 const ObjCInterfaceDecl *OID) {
172 llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getName());
173 ClassName = Builder.CreateStructGEP(ClassName, 0);
174
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000175 llvm::Constant *ClassLookupFn =
176 TheModule.getOrInsertFunction("objc_lookup_class", IdTy, PtrToInt8Ty,
177 NULL);
178 return Builder.CreateCall(ClassLookupFn, ClassName);
Chris Lattnerb326b172008-03-30 23:03:07 +0000179}
180
Chris Lattnerd71288e2008-06-26 04:37:12 +0000181/// GetSelector - Return the pointer to the unique'd string for this selector.
Chris Lattnerfaf23db2008-08-08 19:57:58 +0000182llvm::Value *CGObjCGNU::GetSelector(llvm::IRBuilder<> &Builder, Selector Sel) {
Chris Lattnerd71288e2008-06-26 04:37:12 +0000183 // FIXME: uniquing on the string is wasteful, unique on Sel instead!
184 llvm::GlobalAlias *&US = UntypedSelectors[Sel.getName()];
185 if (US == 0)
186 US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy),
187 llvm::GlobalValue::InternalLinkage,
188 ".objc_untyped_selector_alias",
189 NULL, &TheModule);
190
191 return Builder.CreateLoad(US);
192
193}
194
Chris Lattnera5b18882008-06-26 04:44:19 +0000195llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str,
196 const std::string &Name) {
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000197 llvm::Constant * ConstStr = llvm::ConstantArray::get(Str);
198 ConstStr = new llvm::GlobalVariable(ConstStr->getType(), true,
199 llvm::GlobalValue::InternalLinkage,
200 ConstStr, Name, &TheModule);
201 return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
202}
203llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty,
204 std::vector<llvm::Constant*> &V, const std::string &Name) {
205 llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
206 return new llvm::GlobalVariable(Ty, false,
207 llvm::GlobalValue::InternalLinkage, C, Name, &TheModule);
208}
209llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
210 std::vector<llvm::Constant*> &V, const std::string &Name) {
211 llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
212 return new llvm::GlobalVariable(Ty, false,
213 llvm::GlobalValue::InternalLinkage, C, Name, &TheModule);
214}
215
216/// Generate an NSConstantString object.
217//TODO: In case there are any crazy people still using the GNU runtime without
218//an OpenStep implementation, this should let them select their own class for
219//constant strings.
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000220llvm::Constant *CGObjCGNU::GenerateConstantString(const std::string &Str) {
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000221 std::vector<llvm::Constant*> Ivars;
222 Ivars.push_back(NULLPtr);
Chris Lattnerbac12452008-06-21 21:44:18 +0000223 Ivars.push_back(MakeConstantString(Str));
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000224 Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000225 llvm::Constant *ObjCStr = MakeGlobal(
226 llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL),
227 Ivars, ".objc_str");
228 ConstantStrings.push_back(
229 llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty));
230 return ObjCStr;
231}
232
233///Generates a message send where the super is the receiver. This is a message
234///send to self with special delivery semantics indicating which class's method
235///should be called.
Daniel Dunbara04840b2008-08-23 03:46:30 +0000236CodeGen::RValue
237CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
238 const ObjCMessageExpr *E,
239 const ObjCInterfaceDecl *SuperClass,
240 llvm::Value *Receiver) {
241 const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000242 // TODO: This should be cached, not looked up every time.
Daniel Dunbara04840b2008-08-23 03:46:30 +0000243 llvm::Value *ReceiverClass = GetClass(CGF.Builder, SuperClass);
244 llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000245 std::vector<const llvm::Type*> impArgTypes;
246 impArgTypes.push_back(Receiver->getType());
Chris Lattnerb326b172008-03-30 23:03:07 +0000247 impArgTypes.push_back(SelectorTy);
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000248
249 // Avoid an explicit cast on the IMP by getting a version that has the right
250 // return type.
251 llvm::FunctionType *impType = llvm::FunctionType::get(ReturnTy, impArgTypes,
252 true);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000253 // Construct the structure used to look up the IMP
254 llvm::StructType *ObjCSuperTy = llvm::StructType::get(Receiver->getType(),
255 IdTy, NULL);
Daniel Dunbara04840b2008-08-23 03:46:30 +0000256 llvm::Value *ObjCSuper = CGF.Builder.CreateAlloca(ObjCSuperTy);
Eli Friedman2e630542008-06-13 23:01:12 +0000257 // FIXME: volatility
Daniel Dunbara04840b2008-08-23 03:46:30 +0000258 CGF.Builder.CreateStore(Receiver, CGF.Builder.CreateStructGEP(ObjCSuper, 0));
259 CGF.Builder.CreateStore(ReceiverClass, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000260
261 // Get the IMP
262 llvm::Constant *lookupFunction =
263 TheModule.getOrInsertFunction("objc_msg_lookup_super",
264 llvm::PointerType::getUnqual(impType),
265 llvm::PointerType::getUnqual(ObjCSuperTy),
266 SelectorTy, NULL);
267 llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
Daniel Dunbara04840b2008-08-23 03:46:30 +0000268 llvm::Value *imp = CGF.Builder.CreateCall(lookupFunction, lookupArgs,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000269 lookupArgs+2);
270
271 // Call the method
Daniel Dunbara04840b2008-08-23 03:46:30 +0000272 llvm::Value *Args[2];
273 Args[0] = Receiver;
274 Args[1] = cmd;
275 return CGF.EmitCallExprExt(imp, E->getType(), E->arg_begin(), E->arg_end(),
276 Args, 2);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000277}
278
279/// Generate code for a message send expression.
Daniel Dunbara04840b2008-08-23 03:46:30 +0000280CodeGen::RValue
281CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
282 const ObjCMessageExpr *E,
283 llvm::Value *Receiver) {
284 const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
285 llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000286
287 // Look up the method implementation.
288 std::vector<const llvm::Type*> impArgTypes;
289 const llvm::Type *RetTy;
290 //TODO: Revisit this when LLVM supports aggregate return types.
291 if (ReturnTy->isSingleValueType() && ReturnTy != llvm::Type::VoidTy) {
292 RetTy = ReturnTy;
293 } else {
294 // For struct returns allocate the space in the caller and pass it up to
295 // the sender.
296 RetTy = llvm::Type::VoidTy;
297 impArgTypes.push_back(llvm::PointerType::getUnqual(ReturnTy));
298 }
299 impArgTypes.push_back(Receiver->getType());
300 impArgTypes.push_back(SelectorTy);
301
302 // Avoid an explicit cast on the IMP by getting a version that has the right
303 // return type.
304 llvm::FunctionType *impType = llvm::FunctionType::get(RetTy, impArgTypes,
305 true);
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000306
307 llvm::Constant *lookupFunction =
308 TheModule.getOrInsertFunction("objc_msg_lookup",
Chris Lattnerb326b172008-03-30 23:03:07 +0000309 llvm::PointerType::getUnqual(impType),
310 Receiver->getType(), SelectorTy, NULL);
Daniel Dunbara04840b2008-08-23 03:46:30 +0000311 llvm::Value *imp = CGF.Builder.CreateCall2(lookupFunction, Receiver, cmd);
Chris Lattner7db5e942008-05-06 00:56:42 +0000312
313 // Call the method.
Daniel Dunbara04840b2008-08-23 03:46:30 +0000314 llvm::Value *Args[2];
315 Args[0] = Receiver;
316 Args[1] = cmd;
317 return CGF.EmitCallExprExt(imp, E->getType(), E->arg_begin(), E->arg_end(),
318 Args, 2);
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000319}
320
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000321/// Generates a MethodList. Used in construction of a objc_class and
322/// objc_category structures.
323llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName,
Chris Lattner578279d2008-06-26 05:08:00 +0000324 const std::string &CategoryName,
325 const llvm::SmallVectorImpl<Selector> &MethodSels,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000326 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
327 bool isClassMethodList) {
328 // Get the method structure type.
329 llvm::StructType *ObjCMethodTy = llvm::StructType::get(
330 PtrToInt8Ty, // Really a selector, but the runtime creates it us.
331 PtrToInt8Ty, // Method types
332 llvm::PointerType::getUnqual(IMPTy), //Method pointer
333 NULL);
334 std::vector<llvm::Constant*> Methods;
335 std::vector<llvm::Constant*> Elements;
336 for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
337 Elements.clear();
Daniel Dunbar31fe9c32008-08-13 23:20:05 +0000338 llvm::Constant *C = CGM.GetAddrOfConstantCString(MethodSels[i].getName());
Chris Lattner578279d2008-06-26 05:08:00 +0000339 Elements.push_back(llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000340 Elements.push_back(
341 llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
342 llvm::Constant *Method =
343 TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
Chris Lattner578279d2008-06-26 05:08:00 +0000344 MethodSels[i].getName(),
Chris Lattnere7581092008-06-26 04:05:20 +0000345 isClassMethodList));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000346 Method = llvm::ConstantExpr::getBitCast(Method,
347 llvm::PointerType::getUnqual(IMPTy));
348 Elements.push_back(Method);
349 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements));
350 }
351
352 // Array of method structures
353 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
Chris Lattner578279d2008-06-26 05:08:00 +0000354 MethodSels.size());
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000355 llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy,
Chris Lattnerbcb3e862008-06-26 04:52:29 +0000356 Methods);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000357
358 // Structure containing list pointer, array and array count
359 llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields;
360 llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get();
361 llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy);
362 llvm::StructType *ObjCMethodListTy = llvm::StructType::get(NextPtrTy,
363 IntTy,
364 ObjCMethodArrayTy,
365 NULL);
366 // Refine next pointer type to concrete type
367 llvm::cast<llvm::OpaqueType>(
368 OpaqueNextTy.get())->refineAbstractTypeTo(ObjCMethodListTy);
369 ObjCMethodListTy = llvm::cast<llvm::StructType>(OpaqueNextTy.get());
370
371 Methods.clear();
372 Methods.push_back(llvm::ConstantPointerNull::get(
373 llvm::PointerType::getUnqual(ObjCMethodListTy)));
374 Methods.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty,
375 MethodTypes.size()));
376 Methods.push_back(MethodArray);
377
378 // Create an instance of the structure
379 return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list");
380}
381
382/// Generates an IvarList. Used in construction of a objc_class.
383llvm::Constant *CGObjCGNU::GenerateIvarList(
384 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
385 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
386 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) {
387 // Get the method structure type.
388 llvm::StructType *ObjCIvarTy = llvm::StructType::get(
389 PtrToInt8Ty,
390 PtrToInt8Ty,
391 IntTy,
392 NULL);
393 std::vector<llvm::Constant*> Ivars;
394 std::vector<llvm::Constant*> Elements;
395 for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
396 Elements.clear();
397 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarNames[i],
398 Zeros, 2));
399 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarTypes[i],
400 Zeros, 2));
401 Elements.push_back(IvarOffsets[i]);
402 Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements));
403 }
404
405 // Array of method structures
406 llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
407 IvarNames.size());
408
409
410 Elements.clear();
411 Elements.push_back(llvm::ConstantInt::get(
412 llvm::cast<llvm::IntegerType>(IntTy), (int)IvarNames.size()));
413 Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars));
414 // Structure containing array and array count
415 llvm::StructType *ObjCIvarListTy = llvm::StructType::get(IntTy,
416 ObjCIvarArrayTy,
417 NULL);
418
419 // Create an instance of the structure
420 return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list");
421}
422
423/// Generate a class structure
424llvm::Constant *CGObjCGNU::GenerateClassStructure(
425 llvm::Constant *MetaClass,
426 llvm::Constant *SuperClass,
427 unsigned info,
Chris Lattnerad9c3f32008-06-26 04:47:04 +0000428 const char *Name,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000429 llvm::Constant *Version,
430 llvm::Constant *InstanceSize,
431 llvm::Constant *IVars,
432 llvm::Constant *Methods,
433 llvm::Constant *Protocols) {
434 // Set up the class structure
435 // Note: Several of these are char*s when they should be ids. This is
436 // because the runtime performs this translation on load.
437 llvm::StructType *ClassTy = llvm::StructType::get(
438 PtrToInt8Ty, // class_pointer
439 PtrToInt8Ty, // super_class
440 PtrToInt8Ty, // name
441 LongTy, // version
442 LongTy, // info
443 LongTy, // instance_size
444 IVars->getType(), // ivars
445 Methods->getType(), // methods
446 // These are all filled in by the runtime, so we pretend
447 PtrTy, // dtable
448 PtrTy, // subclass_list
449 PtrTy, // sibling_class
450 PtrTy, // protocols
451 PtrTy, // gc_object_type
452 NULL);
453 llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
454 llvm::Constant *NullP =
455 llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(PtrTy));
456 // Fill in the structure
457 std::vector<llvm::Constant*> Elements;
458 Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
459 Elements.push_back(SuperClass);
Chris Lattnerad9c3f32008-06-26 04:47:04 +0000460 Elements.push_back(MakeConstantString(Name, ".class_name"));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000461 Elements.push_back(Zero);
462 Elements.push_back(llvm::ConstantInt::get(LongTy, info));
463 Elements.push_back(InstanceSize);
464 Elements.push_back(IVars);
465 Elements.push_back(Methods);
466 Elements.push_back(NullP);
467 Elements.push_back(NullP);
468 Elements.push_back(NullP);
469 Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
470 Elements.push_back(NullP);
471 // Create an instance of the structure
Chris Lattner4d018542008-07-21 06:31:05 +0000472 return MakeGlobal(ClassTy, Elements, SymbolNameForClass(Name));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000473}
474
475llvm::Constant *CGObjCGNU::GenerateProtocolMethodList(
476 const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
477 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes) {
478 // Get the method structure type.
479 llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(
480 PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
481 PtrToInt8Ty,
482 NULL);
483 std::vector<llvm::Constant*> Methods;
484 std::vector<llvm::Constant*> Elements;
485 for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
486 Elements.clear();
487 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(MethodNames[i],
488 Zeros, 2));
489 Elements.push_back(
490 llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
491 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements));
492 }
493 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
494 MethodNames.size());
495 llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy, Methods);
496 llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(
497 IntTy, ObjCMethodArrayTy, NULL);
498 Methods.clear();
499 Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
500 Methods.push_back(Array);
501 return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list");
502}
503// Create the protocol list structure used in classes, categories and so on
504llvm::Constant *CGObjCGNU::GenerateProtocolList(
505 const llvm::SmallVectorImpl<std::string> &Protocols) {
506 llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
507 Protocols.size());
508 llvm::StructType *ProtocolListTy = llvm::StructType::get(
509 PtrTy, //Should be a recurisve pointer, but it's always NULL here.
510 LongTy,//FIXME: Should be size_t
511 ProtocolArrayTy,
512 NULL);
513 std::vector<llvm::Constant*> Elements;
514 for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
515 iter != endIter ; iter++) {
516 llvm::Constant *Ptr =
517 llvm::ConstantExpr::getBitCast(ExistingProtocols[*iter], PtrToInt8Ty);
518 Elements.push_back(Ptr);
519 }
520 llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
521 Elements);
522 Elements.clear();
523 Elements.push_back(NULLPtr);
524 Elements.push_back(llvm::ConstantInt::get(
525 llvm::cast<llvm::IntegerType>(LongTy), Protocols.size()));
526 Elements.push_back(ProtocolArray);
527 return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list");
528}
529
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000530llvm::Value *CGObjCGNU::GenerateProtocolRef(llvm::IRBuilder<> &Builder,
531 const ObjCProtocolDecl *PD) {
532 return ExistingProtocols[PD->getName()];
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000533}
534
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000535void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
536 ASTContext &Context = CGM.getContext();
537 const char *ProtocolName = PD->getName();
538 llvm::SmallVector<std::string, 16> Protocols;
539 for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(),
540 E = PD->protocol_end(); PI != E; ++PI)
541 Protocols.push_back((*PI)->getName());
542 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames;
543 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
544 for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(),
545 E = PD->instmeth_end(); iter != E; iter++) {
546 std::string TypeStr;
547 Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
548 InstanceMethodNames.push_back(
Daniel Dunbar31fe9c32008-08-13 23:20:05 +0000549 CGM.GetAddrOfConstantCString((*iter)->getSelector().getName()));
550 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000551 }
552 // Collect information about class methods:
553 llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames;
554 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
555 for (ObjCProtocolDecl::classmeth_iterator iter = PD->classmeth_begin(),
556 endIter = PD->classmeth_end() ; iter != endIter ; iter++) {
557 std::string TypeStr;
558 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
559 ClassMethodNames.push_back(
Daniel Dunbar31fe9c32008-08-13 23:20:05 +0000560 CGM.GetAddrOfConstantCString((*iter)->getSelector().getName()));
561 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000562 }
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000563
564 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
565 llvm::Constant *InstanceMethodList =
566 GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes);
567 llvm::Constant *ClassMethodList =
568 GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes);
569 // Protocols are objects containing lists of the methods implemented and
570 // protocols adopted.
571 llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy,
572 PtrToInt8Ty,
573 ProtocolList->getType(),
574 InstanceMethodList->getType(),
575 ClassMethodList->getType(),
576 NULL);
577 std::vector<llvm::Constant*> Elements;
578 // The isa pointer must be set to a magic number so the runtime knows it's
579 // the correct layout.
580 Elements.push_back(llvm::ConstantExpr::getIntToPtr(
581 llvm::ConstantInt::get(llvm::Type::Int32Ty, ProtocolVersion), IdTy));
582 Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
583 Elements.push_back(ProtocolList);
584 Elements.push_back(InstanceMethodList);
585 Elements.push_back(ClassMethodList);
586 ExistingProtocols[ProtocolName] =
587 llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
588 ".objc_protocol"), IdTy);
589}
590
Daniel Dunbarac93e472008-08-15 22:20:32 +0000591void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
592 const char *ClassName = OCD->getClassInterface()->getName();
593 const char *CategoryName = OCD->getName();
594 // Collect information about instance methods
595 llvm::SmallVector<Selector, 16> InstanceMethodSels;
596 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
597 for (ObjCCategoryDecl::instmeth_iterator iter = OCD->instmeth_begin(),
598 endIter = OCD->instmeth_end() ; iter != endIter ; iter++) {
599 InstanceMethodSels.push_back((*iter)->getSelector());
600 std::string TypeStr;
601 CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
602 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
603 }
604
605 // Collect information about class methods
606 llvm::SmallVector<Selector, 16> ClassMethodSels;
607 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
608 for (ObjCCategoryDecl::classmeth_iterator iter = OCD->classmeth_begin(),
609 endIter = OCD->classmeth_end() ; iter != endIter ; iter++) {
610 ClassMethodSels.push_back((*iter)->getSelector());
611 std::string TypeStr;
612 CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
613 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
614 }
615
616 // Collect the names of referenced protocols
617 llvm::SmallVector<std::string, 16> Protocols;
618 const ObjCInterfaceDecl *ClassDecl = OCD->getClassInterface();
619 const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
620 for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
621 E = Protos.end(); I != E; ++I)
622 Protocols.push_back((*I)->getName());
623
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000624 std::vector<llvm::Constant*> Elements;
625 Elements.push_back(MakeConstantString(CategoryName));
626 Elements.push_back(MakeConstantString(ClassName));
627 // Instance method list
628 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattner578279d2008-06-26 05:08:00 +0000629 ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000630 false), PtrTy));
631 // Class method list
632 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattner578279d2008-06-26 05:08:00 +0000633 ClassName, CategoryName, ClassMethodSels, ClassMethodTypes, true),
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000634 PtrTy));
635 // Protocol list
636 Elements.push_back(llvm::ConstantExpr::getBitCast(
637 GenerateProtocolList(Protocols), PtrTy));
638 Categories.push_back(llvm::ConstantExpr::getBitCast(
639 MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, PtrTy,
640 PtrTy, PtrTy, NULL), Elements), PtrTy));
641}
Daniel Dunbarac93e472008-08-15 22:20:32 +0000642
643void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
644 ASTContext &Context = CGM.getContext();
645
646 // Get the superclass name.
647 const ObjCInterfaceDecl * SuperClassDecl =
648 OID->getClassInterface()->getSuperClass();
649 const char * SuperClassName = NULL;
650 if (SuperClassDecl) {
651 SuperClassName = SuperClassDecl->getName();
652 }
653
654 // Get the class name
655 ObjCInterfaceDecl * ClassDecl = (ObjCInterfaceDecl*)OID->getClassInterface();
656 const char * ClassName = ClassDecl->getName();
657
658 // Get the size of instances. For runtimes that support late-bound instances
659 // this should probably be something different (size just of instance
660 // varaibles in this class, not superclasses?).
661 int instanceSize = 0;
662 const llvm::Type *ObjTy = 0;
663 if (!LateBoundIVars()) {
664 ObjTy = CGM.getTypes().ConvertType(Context.getObjCInterfaceType(ClassDecl));
665 instanceSize = CGM.getTargetData().getABITypeSize(ObjTy);
666 } else {
667 // This is required by newer ObjC runtimes.
668 assert(0 && "Late-bound instance variables not yet supported");
669 }
670
671 // Collect information about instance variables.
672 llvm::SmallVector<llvm::Constant*, 16> IvarNames;
673 llvm::SmallVector<llvm::Constant*, 16> IvarTypes;
674 llvm::SmallVector<llvm::Constant*, 16> IvarOffsets;
675 const llvm::StructLayout *Layout =
676 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(ObjTy));
677 ObjTy = llvm::PointerType::getUnqual(ObjTy);
678 for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
679 endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
680 // Store the name
681 IvarNames.push_back(CGM.GetAddrOfConstantCString((*iter)->getName()));
682 // Get the type encoding for this ivar
683 std::string TypeStr;
684 llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes;
685 Context.getObjCEncodingForType((*iter)->getType(), TypeStr,
686 EncodingRecordTypes);
687 IvarTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
688 // Get the offset
689 int offset =
690 (int)Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(*iter));
691 IvarOffsets.push_back(
692 llvm::ConstantInt::get(llvm::Type::Int32Ty, offset));
693 }
694
695 // Collect information about instance methods
696 llvm::SmallVector<Selector, 16> InstanceMethodSels;
697 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
698 for (ObjCImplementationDecl::instmeth_iterator iter = OID->instmeth_begin(),
699 endIter = OID->instmeth_end() ; iter != endIter ; iter++) {
700 InstanceMethodSels.push_back((*iter)->getSelector());
701 std::string TypeStr;
702 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
703 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
704 }
705
706 // Collect information about class methods
707 llvm::SmallVector<Selector, 16> ClassMethodSels;
708 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
709 for (ObjCImplementationDecl::classmeth_iterator iter = OID->classmeth_begin(),
710 endIter = OID->classmeth_end() ; iter != endIter ; iter++) {
711 ClassMethodSels.push_back((*iter)->getSelector());
712 std::string TypeStr;
713 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
714 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
715 }
716 // Collect the names of referenced protocols
717 llvm::SmallVector<std::string, 16> Protocols;
718 const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
719 for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
720 E = Protos.end(); I != E; ++I)
721 Protocols.push_back((*I)->getName());
722
723
724
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000725 // Get the superclass pointer.
726 llvm::Constant *SuperClass;
727 if (SuperClassName) {
728 SuperClass = MakeConstantString(SuperClassName, ".super_class_name");
729 } else {
730 SuperClass = llvm::ConstantPointerNull::get(
731 llvm::cast<llvm::PointerType>(PtrToInt8Ty));
732 }
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000733 // Empty vector used to construct empty method lists
734 llvm::SmallVector<llvm::Constant*, 1> empty;
735 // Generate the method and instance variable lists
736 llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
Chris Lattner578279d2008-06-26 05:08:00 +0000737 InstanceMethodSels, InstanceMethodTypes, false);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000738 llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
Chris Lattner578279d2008-06-26 05:08:00 +0000739 ClassMethodSels, ClassMethodTypes, true);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000740 llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
741 IvarOffsets);
742 //Generate metaclass for class methods
743 llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
Chris Lattner4d018542008-07-21 06:31:05 +0000744 NULLPtr, 0x2L, /*name*/"", 0, Zeros[0], GenerateIvarList(
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000745 empty, empty, empty), ClassMethodList, NULLPtr);
746 // Generate the class structure
747 llvm::Constant *ClassStruct = GenerateClassStructure(MetaClassStruct,
Chris Lattnerad9c3f32008-06-26 04:47:04 +0000748 SuperClass, 0x1L, ClassName, 0,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000749 llvm::ConstantInt::get(llvm::Type::Int32Ty, instanceSize), IvarList,
750 MethodList, GenerateProtocolList(Protocols));
751 // Add class structure to list to be added to the symtab later
752 ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty);
753 Classes.push_back(ClassStruct);
754}
755
756llvm::Function *CGObjCGNU::ModuleInitFunction() {
757 // Only emit an ObjC load function if no Objective-C stuff has been called
758 if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
759 ExistingProtocols.empty() && TypedSelectors.empty() &&
Anton Korobeynikovb41e4972008-06-01 15:14:46 +0000760 UntypedSelectors.empty())
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000761 return NULL;
Eli Friedman7719bc82008-06-01 16:00:02 +0000762
763 // Name the ObjC types to make the IR a bit easier to read
764 TheModule.addTypeName(".objc_selector", SelectorTy);
765 TheModule.addTypeName(".objc_id", IdTy);
766 TheModule.addTypeName(".objc_imp", IMPTy);
767
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000768 std::vector<llvm::Constant*> Elements;
769 // Generate statics list:
770 llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
771 ConstantStrings.size() + 1);
772 ConstantStrings.push_back(NULLPtr);
773 Elements.push_back(MakeConstantString("NSConstantString",
774 ".objc_static_class_name"));
775 Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy, ConstantStrings));
776 llvm::StructType *StaticsListTy =
777 llvm::StructType::get(PtrToInt8Ty, StaticsArrayTy, NULL);
Chris Lattneref843042008-06-26 04:10:42 +0000778 llvm::Type *StaticsListPtrTy = llvm::PointerType::getUnqual(StaticsListTy);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000779 llvm::Constant *Statics =
780 MakeGlobal(StaticsListTy, Elements, ".objc_statics");
Chris Lattner60eaae82008-06-24 17:01:28 +0000781 llvm::ArrayType *StaticsListArrayTy =
Chris Lattneref843042008-06-26 04:10:42 +0000782 llvm::ArrayType::get(StaticsListPtrTy, 2);
Chris Lattner60eaae82008-06-24 17:01:28 +0000783 Elements.clear();
784 Elements.push_back(Statics);
Chris Lattneref843042008-06-26 04:10:42 +0000785 Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
Chris Lattner60eaae82008-06-24 17:01:28 +0000786 Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr");
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000787 Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
788 // Array of classes, categories, and constant objects
789 llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty,
790 Classes.size() + Categories.size() + 2);
Chris Lattneref843042008-06-26 04:10:42 +0000791 llvm::StructType *SymTabTy = llvm::StructType::get(LongTy, SelectorTy,
792 llvm::Type::Int16Ty,
793 llvm::Type::Int16Ty,
794 ClassListTy, NULL);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000795
796 Elements.clear();
797 // Pointer to an array of selectors used in this module.
798 std::vector<llvm::Constant*> Selectors;
799 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
800 iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end();
801 iter != iterEnd ; ++iter) {
Chris Lattneref843042008-06-26 04:10:42 +0000802 Elements.push_back(MakeConstantString(iter->first.first, ".objc_sel_name"));
803 Elements.push_back(MakeConstantString(iter->first.second,
804 ".objc_sel_types"));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000805 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
806 Elements.clear();
807 }
808 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
809 iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
Chris Lattneref843042008-06-26 04:10:42 +0000810 iter != iterEnd; ++iter) {
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000811 Elements.push_back(
Chris Lattneref843042008-06-26 04:10:42 +0000812 MakeConstantString(iter->getKeyData(), ".objc_sel_name"));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000813 Elements.push_back(NULLPtr);
814 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
815 Elements.clear();
816 }
817 Elements.push_back(NULLPtr);
818 Elements.push_back(NULLPtr);
819 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
820 Elements.clear();
821 // Number of static selectors
822 Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() ));
823 llvm::Constant *SelectorList = MakeGlobal(
824 llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors,
825 ".objc_selector_list");
826 Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList, SelectorTy));
827
828 // Now that all of the static selectors exist, create pointers to them.
829 int index = 0;
830 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
831 iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end();
832 iter != iterEnd; ++iter) {
833 llvm::Constant *Idxs[] = {Zeros[0],
834 llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]};
835 llvm::GlobalVariable *SelPtr = new llvm::GlobalVariable(SelectorTy, true,
836 llvm::GlobalValue::InternalLinkage,
837 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
838 ".objc_sel_ptr", &TheModule);
839 (*iter).second->setAliasee(SelPtr);
840 }
841 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
842 iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
843 iter != iterEnd; iter++) {
844 llvm::Constant *Idxs[] = {Zeros[0],
845 llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]};
846 llvm::GlobalVariable *SelPtr = new llvm::GlobalVariable(SelectorTy, true,
847 llvm::GlobalValue::InternalLinkage,
848 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
849 ".objc_sel_ptr", &TheModule);
850 (*iter).second->setAliasee(SelPtr);
851 }
852 // Number of classes defined.
853 Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty,
854 Classes.size()));
855 // Number of categories defined
856 Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty,
857 Categories.size()));
858 // Create an array of classes, then categories, then static object instances
859 Classes.insert(Classes.end(), Categories.begin(), Categories.end());
860 // NULL-terminated list of static object instances (mainly constant strings)
861 Classes.push_back(Statics);
862 Classes.push_back(NULLPtr);
863 llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes);
864 Elements.push_back(ClassList);
865 // Construct the symbol table
866 llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements);
867
868 // The symbol table is contained in a module which has some version-checking
869 // constants
870 llvm::StructType * ModuleTy = llvm::StructType::get(LongTy, LongTy,
871 PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL);
872 Elements.clear();
873 // Runtime version used for compatibility checking.
874 Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
875 //FIXME: Should be sizeof(ModuleTy)
876 Elements.push_back(llvm::ConstantInt::get(LongTy, 16));
877 //FIXME: Should be the path to the file where this module was declared
878 Elements.push_back(NULLPtr);
879 Elements.push_back(SymTab);
880 llvm::Value *Module = MakeGlobal(ModuleTy, Elements);
881
882 // Create the load function calling the runtime entry point with the module
883 // structure
884 std::vector<const llvm::Type*> VoidArgs;
885 llvm::Function * LoadFunction = llvm::Function::Create(
886 llvm::FunctionType::get(llvm::Type::VoidTy, VoidArgs, false),
887 llvm::GlobalValue::InternalLinkage, ".objc_load_function",
888 &TheModule);
889 llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", LoadFunction);
Chris Lattnerfaf23db2008-08-08 19:57:58 +0000890 llvm::IRBuilder<> Builder;
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000891 Builder.SetInsertPoint(EntryBB);
892 llvm::Value *Register = TheModule.getOrInsertFunction("__objc_exec_class",
893 llvm::Type::VoidTy, llvm::PointerType::getUnqual(ModuleTy), NULL);
894 Builder.CreateCall(Register, Module);
895 Builder.CreateRetVoid();
896 return LoadFunction;
897}
Daniel Dunbarac93e472008-08-15 22:20:32 +0000898
899llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD) {
900 const llvm::Type *ReturnTy =
901 CGM.getTypes().ConvertReturnType(OMD->getResultType());
902 const ObjCCategoryImplDecl *OCD =
903 dyn_cast<ObjCCategoryImplDecl>(OMD->getMethodContext());
904 const std::string &CategoryName = OCD ? OCD->getName() : "";
905 const llvm::Type *SelfTy = llvm::PointerType::getUnqual(llvm::Type::Int32Ty);
906 const std::string &ClassName = OMD->getClassInterface()->getName();
907 const std::string &MethodName = OMD->getSelector().getName();
908 unsigned ArgC = OMD->param_size();
909 bool isClassMethod = !OMD->isInstance();
910 bool isVarArg = OMD->isVariadic();
911
912 llvm::SmallVector<const llvm::Type *, 16> ArgTy;
913 for (unsigned i=0 ; i<OMD->param_size() ; i++) {
914 const llvm::Type *Ty =
915 CGM.getTypes().ConvertType(OMD->getParamDecl(i)->getType());
916 if (Ty->isFirstClassType())
917 ArgTy.push_back(Ty);
918 else
919 ArgTy.push_back(llvm::PointerType::getUnqual(Ty));
920 }
921
Chris Lattnerb326b172008-03-30 23:03:07 +0000922 std::vector<const llvm::Type*> Args;
Chris Lattner6ee20e32008-06-24 17:04:18 +0000923 if (!ReturnTy->isSingleValueType() && ReturnTy != llvm::Type::VoidTy) {
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000924 Args.push_back(llvm::PointerType::getUnqual(ReturnTy));
925 ReturnTy = llvm::Type::VoidTy;
926 }
Chris Lattnerb326b172008-03-30 23:03:07 +0000927 Args.push_back(SelfTy);
928 Args.push_back(SelectorTy);
Daniel Dunbarac93e472008-08-15 22:20:32 +0000929 Args.insert(Args.end(), ArgTy.begin(), ArgTy.begin()+ArgC);
Chris Lattnerb326b172008-03-30 23:03:07 +0000930
931 llvm::FunctionType *MethodTy = llvm::FunctionType::get(ReturnTy,
932 Args,
933 isVarArg);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000934 std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
935 MethodName, isClassMethod);
936
Gabor Greif815e2c12008-04-06 20:42:52 +0000937 llvm::Function *Method = llvm::Function::Create(MethodTy,
Chris Lattnerb326b172008-03-30 23:03:07 +0000938 llvm::GlobalValue::InternalLinkage,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000939 FunctionName,
Chris Lattnerb326b172008-03-30 23:03:07 +0000940 &TheModule);
Chris Lattnerb326b172008-03-30 23:03:07 +0000941 return Method;
942}
943
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000944CodeGen::CGObjCRuntime *CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM){
Chris Lattner547907c2008-06-26 04:19:03 +0000945 return new CGObjCGNU(CGM);
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000946}