blob: 91b8587e1afd1596d47ac13eae00bc42c7e54936 [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"
Daniel Dunbarac93e472008-08-15 22:20:32 +000027#include "llvm/Target/TargetData.h"
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +000028#include <map>
Chris Lattner547907c2008-06-26 04:19:03 +000029using namespace clang;
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +000030using namespace CodeGen;
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,
Daniel Dunbardd851282008-08-30 05:35:15 +000099 QualType ResultType,
100 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000101 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000102 bool IsClassMessage,
103 const CallArgList &CallArgs);
Daniel Dunbara04840b2008-08-23 03:46:30 +0000104 virtual CodeGen::RValue
105 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000106 QualType ResultType,
107 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000108 const ObjCInterfaceDecl *Class,
109 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000110 bool IsClassMessage,
111 const CallArgList &CallArgs);
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000112 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar434627a2008-08-16 00:25:02 +0000113 const ObjCInterfaceDecl *OID);
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000114 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel);
Chris Lattnerd71288e2008-06-26 04:37:12 +0000115
Daniel Dunbarac93e472008-08-15 22:20:32 +0000116 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD);
117 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
118 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000119 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000120 const ObjCProtocolDecl *PD);
121 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000122 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbarf7103722008-09-24 03:38:44 +0000123 virtual llvm::Function *GetPropertyGetFunction();
124 virtual llvm::Function *GetPropertySetFunction();
Anders Carlsson58d16242008-08-31 04:05:03 +0000125 virtual llvm::Function *EnumerationMutationFunction();
Anders Carlssonb01a2112008-09-09 10:04:29 +0000126
127 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
128 const ObjCAtTryStmt &S);
129 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
130 const ObjCAtThrowStmt &S);
Chris Lattnerdd978702008-11-15 21:26:17 +0000131 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
132 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanian252d87f2008-11-18 22:37:34 +0000133 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian3305ad32008-11-18 21:45:40 +0000134 llvm::Value *AddrWeakObj);
Fariborz Jahanian252d87f2008-11-18 22:37:34 +0000135 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
136 llvm::Value *src, llvm::Value *dst);
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000137};
138} // end anonymous namespace
139
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000140
141
142static std::string SymbolNameForClass(const std::string &ClassName) {
143 return ".objc_class_" + ClassName;
144}
145
146static std::string SymbolNameForMethod(const std::string &ClassName, const
147 std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
148{
149 return "._objc_method_" + ClassName +"("+CategoryName+")"+
150 (isClassMethod ? "+" : "-") + MethodName;
151}
152
Chris Lattner547907c2008-06-26 04:19:03 +0000153CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
154 : CGM(cgm), TheModule(CGM.getModule()) {
155 IntTy = CGM.getTypes().ConvertType(CGM.getContext().IntTy);
156 LongTy = CGM.getTypes().ConvertType(CGM.getContext().LongTy);
157
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000158 Zeros[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
159 Zeros[1] = Zeros[0];
160 NULLPtr = llvm::ConstantPointerNull::get(
161 llvm::PointerType::getUnqual(llvm::Type::Int8Ty));
Chris Lattnerb326b172008-03-30 23:03:07 +0000162 // C string type. Used in lots of places.
163 PtrToInt8Ty =
164 llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
165 // Get the selector Type.
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000166 SelStructTy = llvm::StructType::get(
Chris Lattnerb326b172008-03-30 23:03:07 +0000167 PtrToInt8Ty,
168 PtrToInt8Ty,
169 NULL);
170 SelectorTy = llvm::PointerType::getUnqual(SelStructTy);
171 PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
172 PtrTy = PtrToInt8Ty;
173
174 // Object type
175 llvm::PATypeHolder OpaqueObjTy = llvm::OpaqueType::get();
176 llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy);
177 IdTy = llvm::StructType::get(OpaqueIdTy, NULL);
178 llvm::cast<llvm::OpaqueType>(OpaqueObjTy.get())->refineAbstractTypeTo(IdTy);
179 IdTy = llvm::cast<llvm::StructType>(OpaqueObjTy.get());
180 IdTy = llvm::PointerType::getUnqual(IdTy);
181
182 // IMP type
183 std::vector<const llvm::Type*> IMPArgs;
184 IMPArgs.push_back(IdTy);
185 IMPArgs.push_back(SelectorTy);
186 IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000187}
188// This has to perform the lookup every time, since posing and related
189// techniques can modify the name -> class mapping.
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000190llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder,
Daniel Dunbar434627a2008-08-16 00:25:02 +0000191 const ObjCInterfaceDecl *OID) {
192 llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getName());
193 ClassName = Builder.CreateStructGEP(ClassName, 0);
194
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000195 llvm::Constant *ClassLookupFn =
196 TheModule.getOrInsertFunction("objc_lookup_class", IdTy, PtrToInt8Ty,
197 NULL);
198 return Builder.CreateCall(ClassLookupFn, ClassName);
Chris Lattnerb326b172008-03-30 23:03:07 +0000199}
200
Chris Lattnerd71288e2008-06-26 04:37:12 +0000201/// GetSelector - Return the pointer to the unique'd string for this selector.
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000202llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel) {
Chris Lattnerd71288e2008-06-26 04:37:12 +0000203 // FIXME: uniquing on the string is wasteful, unique on Sel instead!
204 llvm::GlobalAlias *&US = UntypedSelectors[Sel.getName()];
205 if (US == 0)
206 US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy),
207 llvm::GlobalValue::InternalLinkage,
208 ".objc_untyped_selector_alias",
209 NULL, &TheModule);
210
211 return Builder.CreateLoad(US);
212
213}
214
Chris Lattnera5b18882008-06-26 04:44:19 +0000215llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str,
216 const std::string &Name) {
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000217 llvm::Constant * ConstStr = llvm::ConstantArray::get(Str);
218 ConstStr = new llvm::GlobalVariable(ConstStr->getType(), true,
219 llvm::GlobalValue::InternalLinkage,
220 ConstStr, Name, &TheModule);
221 return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
222}
223llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty,
224 std::vector<llvm::Constant*> &V, const std::string &Name) {
225 llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
226 return new llvm::GlobalVariable(Ty, false,
227 llvm::GlobalValue::InternalLinkage, C, Name, &TheModule);
228}
229llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
230 std::vector<llvm::Constant*> &V, const std::string &Name) {
231 llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
232 return new llvm::GlobalVariable(Ty, false,
233 llvm::GlobalValue::InternalLinkage, C, Name, &TheModule);
234}
235
236/// Generate an NSConstantString object.
237//TODO: In case there are any crazy people still using the GNU runtime without
238//an OpenStep implementation, this should let them select their own class for
239//constant strings.
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000240llvm::Constant *CGObjCGNU::GenerateConstantString(const std::string &Str) {
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000241 std::vector<llvm::Constant*> Ivars;
242 Ivars.push_back(NULLPtr);
Chris Lattnerbac12452008-06-21 21:44:18 +0000243 Ivars.push_back(MakeConstantString(Str));
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000244 Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000245 llvm::Constant *ObjCStr = MakeGlobal(
246 llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL),
247 Ivars, ".objc_str");
248 ConstantStrings.push_back(
249 llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty));
250 return ObjCStr;
251}
252
253///Generates a message send where the super is the receiver. This is a message
254///send to self with special delivery semantics indicating which class's method
255///should be called.
Daniel Dunbara04840b2008-08-23 03:46:30 +0000256CodeGen::RValue
257CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000258 QualType ResultType,
259 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000260 const ObjCInterfaceDecl *Class,
261 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000262 bool IsClassMessage,
263 const CallArgList &CallArgs) {
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000264 const ObjCInterfaceDecl *SuperClass = Class->getSuperClass();
Daniel Dunbardd851282008-08-30 05:35:15 +0000265 const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000266 // TODO: This should be cached, not looked up every time.
Daniel Dunbara04840b2008-08-23 03:46:30 +0000267 llvm::Value *ReceiverClass = GetClass(CGF.Builder, SuperClass);
Daniel Dunbardd851282008-08-30 05:35:15 +0000268 llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000269 std::vector<const llvm::Type*> impArgTypes;
270 impArgTypes.push_back(Receiver->getType());
Chris Lattnerb326b172008-03-30 23:03:07 +0000271 impArgTypes.push_back(SelectorTy);
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000272
273 // Avoid an explicit cast on the IMP by getting a version that has the right
274 // return type.
275 llvm::FunctionType *impType = llvm::FunctionType::get(ReturnTy, impArgTypes,
276 true);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000277 // Construct the structure used to look up the IMP
278 llvm::StructType *ObjCSuperTy = llvm::StructType::get(Receiver->getType(),
279 IdTy, NULL);
Daniel Dunbara04840b2008-08-23 03:46:30 +0000280 llvm::Value *ObjCSuper = CGF.Builder.CreateAlloca(ObjCSuperTy);
Eli Friedman2e630542008-06-13 23:01:12 +0000281 // FIXME: volatility
Daniel Dunbara04840b2008-08-23 03:46:30 +0000282 CGF.Builder.CreateStore(Receiver, CGF.Builder.CreateStructGEP(ObjCSuper, 0));
283 CGF.Builder.CreateStore(ReceiverClass, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000284
285 // Get the IMP
286 llvm::Constant *lookupFunction =
287 TheModule.getOrInsertFunction("objc_msg_lookup_super",
288 llvm::PointerType::getUnqual(impType),
289 llvm::PointerType::getUnqual(ObjCSuperTy),
290 SelectorTy, NULL);
291 llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
Daniel Dunbara04840b2008-08-23 03:46:30 +0000292 llvm::Value *imp = CGF.Builder.CreateCall(lookupFunction, lookupArgs,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000293 lookupArgs+2);
294
295 // Call the method
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000296 CallArgList ActualArgs;
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +0000297 ActualArgs.push_back(std::make_pair(RValue::get(Receiver),
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000298 CGF.getContext().getObjCIdType()));
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +0000299 ActualArgs.push_back(std::make_pair(RValue::get(cmd),
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000300 CGF.getContext().getObjCSelType()));
301 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbardd851282008-08-30 05:35:15 +0000302 return CGF.EmitCall(imp, ResultType, ActualArgs);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000303}
304
305/// Generate code for a message send expression.
Daniel Dunbara04840b2008-08-23 03:46:30 +0000306CodeGen::RValue
307CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000308 QualType ResultType,
309 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000310 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000311 bool IsClassMessage,
312 const CallArgList &CallArgs) {
Daniel Dunbardd851282008-08-30 05:35:15 +0000313 const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
314 llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000315
316 // Look up the method implementation.
317 std::vector<const llvm::Type*> impArgTypes;
318 const llvm::Type *RetTy;
319 //TODO: Revisit this when LLVM supports aggregate return types.
320 if (ReturnTy->isSingleValueType() && ReturnTy != llvm::Type::VoidTy) {
321 RetTy = ReturnTy;
322 } else {
323 // For struct returns allocate the space in the caller and pass it up to
324 // the sender.
325 RetTy = llvm::Type::VoidTy;
326 impArgTypes.push_back(llvm::PointerType::getUnqual(ReturnTy));
327 }
328 impArgTypes.push_back(Receiver->getType());
329 impArgTypes.push_back(SelectorTy);
330
331 // Avoid an explicit cast on the IMP by getting a version that has the right
332 // return type.
333 llvm::FunctionType *impType = llvm::FunctionType::get(RetTy, impArgTypes,
334 true);
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000335
336 llvm::Constant *lookupFunction =
337 TheModule.getOrInsertFunction("objc_msg_lookup",
Chris Lattnerb326b172008-03-30 23:03:07 +0000338 llvm::PointerType::getUnqual(impType),
339 Receiver->getType(), SelectorTy, NULL);
Daniel Dunbara04840b2008-08-23 03:46:30 +0000340 llvm::Value *imp = CGF.Builder.CreateCall2(lookupFunction, Receiver, cmd);
Chris Lattner7db5e942008-05-06 00:56:42 +0000341
342 // Call the method.
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000343 CallArgList ActualArgs;
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +0000344 ActualArgs.push_back(std::make_pair(RValue::get(Receiver),
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000345 CGF.getContext().getObjCIdType()));
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +0000346 ActualArgs.push_back(std::make_pair(RValue::get(cmd),
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000347 CGF.getContext().getObjCSelType()));
348 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbardd851282008-08-30 05:35:15 +0000349 return CGF.EmitCall(imp, ResultType, ActualArgs);
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000350}
351
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000352/// Generates a MethodList. Used in construction of a objc_class and
353/// objc_category structures.
354llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName,
Chris Lattner578279d2008-06-26 05:08:00 +0000355 const std::string &CategoryName,
356 const llvm::SmallVectorImpl<Selector> &MethodSels,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000357 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
358 bool isClassMethodList) {
359 // Get the method structure type.
360 llvm::StructType *ObjCMethodTy = llvm::StructType::get(
361 PtrToInt8Ty, // Really a selector, but the runtime creates it us.
362 PtrToInt8Ty, // Method types
363 llvm::PointerType::getUnqual(IMPTy), //Method pointer
364 NULL);
365 std::vector<llvm::Constant*> Methods;
366 std::vector<llvm::Constant*> Elements;
367 for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
368 Elements.clear();
Daniel Dunbar31fe9c32008-08-13 23:20:05 +0000369 llvm::Constant *C = CGM.GetAddrOfConstantCString(MethodSels[i].getName());
Chris Lattner578279d2008-06-26 05:08:00 +0000370 Elements.push_back(llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000371 Elements.push_back(
372 llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
373 llvm::Constant *Method =
374 TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
Chris Lattner578279d2008-06-26 05:08:00 +0000375 MethodSels[i].getName(),
Chris Lattnere7581092008-06-26 04:05:20 +0000376 isClassMethodList));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000377 Method = llvm::ConstantExpr::getBitCast(Method,
378 llvm::PointerType::getUnqual(IMPTy));
379 Elements.push_back(Method);
380 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements));
381 }
382
383 // Array of method structures
384 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
Chris Lattner578279d2008-06-26 05:08:00 +0000385 MethodSels.size());
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000386 llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy,
Chris Lattnerbcb3e862008-06-26 04:52:29 +0000387 Methods);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000388
389 // Structure containing list pointer, array and array count
390 llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields;
391 llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get();
392 llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy);
393 llvm::StructType *ObjCMethodListTy = llvm::StructType::get(NextPtrTy,
394 IntTy,
395 ObjCMethodArrayTy,
396 NULL);
397 // Refine next pointer type to concrete type
398 llvm::cast<llvm::OpaqueType>(
399 OpaqueNextTy.get())->refineAbstractTypeTo(ObjCMethodListTy);
400 ObjCMethodListTy = llvm::cast<llvm::StructType>(OpaqueNextTy.get());
401
402 Methods.clear();
403 Methods.push_back(llvm::ConstantPointerNull::get(
404 llvm::PointerType::getUnqual(ObjCMethodListTy)));
405 Methods.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty,
406 MethodTypes.size()));
407 Methods.push_back(MethodArray);
408
409 // Create an instance of the structure
410 return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list");
411}
412
413/// Generates an IvarList. Used in construction of a objc_class.
414llvm::Constant *CGObjCGNU::GenerateIvarList(
415 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
416 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
417 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) {
418 // Get the method structure type.
419 llvm::StructType *ObjCIvarTy = llvm::StructType::get(
420 PtrToInt8Ty,
421 PtrToInt8Ty,
422 IntTy,
423 NULL);
424 std::vector<llvm::Constant*> Ivars;
425 std::vector<llvm::Constant*> Elements;
426 for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
427 Elements.clear();
428 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarNames[i],
429 Zeros, 2));
430 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarTypes[i],
431 Zeros, 2));
432 Elements.push_back(IvarOffsets[i]);
433 Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements));
434 }
435
436 // Array of method structures
437 llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
438 IvarNames.size());
439
440
441 Elements.clear();
442 Elements.push_back(llvm::ConstantInt::get(
443 llvm::cast<llvm::IntegerType>(IntTy), (int)IvarNames.size()));
444 Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars));
445 // Structure containing array and array count
446 llvm::StructType *ObjCIvarListTy = llvm::StructType::get(IntTy,
447 ObjCIvarArrayTy,
448 NULL);
449
450 // Create an instance of the structure
451 return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list");
452}
453
454/// Generate a class structure
455llvm::Constant *CGObjCGNU::GenerateClassStructure(
456 llvm::Constant *MetaClass,
457 llvm::Constant *SuperClass,
458 unsigned info,
Chris Lattnerad9c3f32008-06-26 04:47:04 +0000459 const char *Name,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000460 llvm::Constant *Version,
461 llvm::Constant *InstanceSize,
462 llvm::Constant *IVars,
463 llvm::Constant *Methods,
464 llvm::Constant *Protocols) {
465 // Set up the class structure
466 // Note: Several of these are char*s when they should be ids. This is
467 // because the runtime performs this translation on load.
468 llvm::StructType *ClassTy = llvm::StructType::get(
469 PtrToInt8Ty, // class_pointer
470 PtrToInt8Ty, // super_class
471 PtrToInt8Ty, // name
472 LongTy, // version
473 LongTy, // info
474 LongTy, // instance_size
475 IVars->getType(), // ivars
476 Methods->getType(), // methods
477 // These are all filled in by the runtime, so we pretend
478 PtrTy, // dtable
479 PtrTy, // subclass_list
480 PtrTy, // sibling_class
481 PtrTy, // protocols
482 PtrTy, // gc_object_type
483 NULL);
484 llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
485 llvm::Constant *NullP =
486 llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(PtrTy));
487 // Fill in the structure
488 std::vector<llvm::Constant*> Elements;
489 Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
490 Elements.push_back(SuperClass);
Chris Lattnerad9c3f32008-06-26 04:47:04 +0000491 Elements.push_back(MakeConstantString(Name, ".class_name"));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000492 Elements.push_back(Zero);
493 Elements.push_back(llvm::ConstantInt::get(LongTy, info));
494 Elements.push_back(InstanceSize);
495 Elements.push_back(IVars);
496 Elements.push_back(Methods);
497 Elements.push_back(NullP);
498 Elements.push_back(NullP);
499 Elements.push_back(NullP);
500 Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
501 Elements.push_back(NullP);
502 // Create an instance of the structure
Chris Lattner4d018542008-07-21 06:31:05 +0000503 return MakeGlobal(ClassTy, Elements, SymbolNameForClass(Name));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000504}
505
506llvm::Constant *CGObjCGNU::GenerateProtocolMethodList(
507 const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
508 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes) {
509 // Get the method structure type.
510 llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(
511 PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
512 PtrToInt8Ty,
513 NULL);
514 std::vector<llvm::Constant*> Methods;
515 std::vector<llvm::Constant*> Elements;
516 for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
517 Elements.clear();
518 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(MethodNames[i],
519 Zeros, 2));
520 Elements.push_back(
521 llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
522 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements));
523 }
524 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
525 MethodNames.size());
526 llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy, Methods);
527 llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(
528 IntTy, ObjCMethodArrayTy, NULL);
529 Methods.clear();
530 Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
531 Methods.push_back(Array);
532 return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list");
533}
534// Create the protocol list structure used in classes, categories and so on
535llvm::Constant *CGObjCGNU::GenerateProtocolList(
536 const llvm::SmallVectorImpl<std::string> &Protocols) {
537 llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
538 Protocols.size());
539 llvm::StructType *ProtocolListTy = llvm::StructType::get(
540 PtrTy, //Should be a recurisve pointer, but it's always NULL here.
541 LongTy,//FIXME: Should be size_t
542 ProtocolArrayTy,
543 NULL);
544 std::vector<llvm::Constant*> Elements;
545 for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
546 iter != endIter ; iter++) {
547 llvm::Constant *Ptr =
548 llvm::ConstantExpr::getBitCast(ExistingProtocols[*iter], PtrToInt8Ty);
549 Elements.push_back(Ptr);
550 }
551 llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
552 Elements);
553 Elements.clear();
554 Elements.push_back(NULLPtr);
555 Elements.push_back(llvm::ConstantInt::get(
556 llvm::cast<llvm::IntegerType>(LongTy), Protocols.size()));
557 Elements.push_back(ProtocolArray);
558 return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list");
559}
560
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000561llvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000562 const ObjCProtocolDecl *PD) {
563 return ExistingProtocols[PD->getName()];
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000564}
565
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000566void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
567 ASTContext &Context = CGM.getContext();
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000568 const char *ProtocolName = PD->getIdentifierName();
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000569 llvm::SmallVector<std::string, 16> Protocols;
570 for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(),
571 E = PD->protocol_end(); PI != E; ++PI)
572 Protocols.push_back((*PI)->getName());
573 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames;
574 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
575 for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(),
576 E = PD->instmeth_end(); iter != E; iter++) {
577 std::string TypeStr;
578 Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
579 InstanceMethodNames.push_back(
Daniel Dunbar31fe9c32008-08-13 23:20:05 +0000580 CGM.GetAddrOfConstantCString((*iter)->getSelector().getName()));
581 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000582 }
583 // Collect information about class methods:
584 llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames;
585 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
586 for (ObjCProtocolDecl::classmeth_iterator iter = PD->classmeth_begin(),
587 endIter = PD->classmeth_end() ; iter != endIter ; iter++) {
588 std::string TypeStr;
589 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
590 ClassMethodNames.push_back(
Daniel Dunbar31fe9c32008-08-13 23:20:05 +0000591 CGM.GetAddrOfConstantCString((*iter)->getSelector().getName()));
592 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000593 }
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000594
595 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
596 llvm::Constant *InstanceMethodList =
597 GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes);
598 llvm::Constant *ClassMethodList =
599 GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes);
600 // Protocols are objects containing lists of the methods implemented and
601 // protocols adopted.
602 llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy,
603 PtrToInt8Ty,
604 ProtocolList->getType(),
605 InstanceMethodList->getType(),
606 ClassMethodList->getType(),
607 NULL);
608 std::vector<llvm::Constant*> Elements;
609 // The isa pointer must be set to a magic number so the runtime knows it's
610 // the correct layout.
611 Elements.push_back(llvm::ConstantExpr::getIntToPtr(
612 llvm::ConstantInt::get(llvm::Type::Int32Ty, ProtocolVersion), IdTy));
613 Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
614 Elements.push_back(ProtocolList);
615 Elements.push_back(InstanceMethodList);
616 Elements.push_back(ClassMethodList);
617 ExistingProtocols[ProtocolName] =
618 llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
619 ".objc_protocol"), IdTy);
620}
621
Daniel Dunbarac93e472008-08-15 22:20:32 +0000622void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000623 const char *ClassName = OCD->getClassInterface()->getIdentifierName();
624 const char *CategoryName = OCD->getIdentifierName();
Daniel Dunbarac93e472008-08-15 22:20:32 +0000625 // Collect information about instance methods
626 llvm::SmallVector<Selector, 16> InstanceMethodSels;
627 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
628 for (ObjCCategoryDecl::instmeth_iterator iter = OCD->instmeth_begin(),
629 endIter = OCD->instmeth_end() ; iter != endIter ; iter++) {
630 InstanceMethodSels.push_back((*iter)->getSelector());
631 std::string TypeStr;
632 CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
633 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
634 }
635
636 // Collect information about class methods
637 llvm::SmallVector<Selector, 16> ClassMethodSels;
638 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
639 for (ObjCCategoryDecl::classmeth_iterator iter = OCD->classmeth_begin(),
640 endIter = OCD->classmeth_end() ; iter != endIter ; iter++) {
641 ClassMethodSels.push_back((*iter)->getSelector());
642 std::string TypeStr;
643 CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
644 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
645 }
646
647 // Collect the names of referenced protocols
648 llvm::SmallVector<std::string, 16> Protocols;
649 const ObjCInterfaceDecl *ClassDecl = OCD->getClassInterface();
650 const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
651 for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
652 E = Protos.end(); I != E; ++I)
653 Protocols.push_back((*I)->getName());
654
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000655 std::vector<llvm::Constant*> Elements;
656 Elements.push_back(MakeConstantString(CategoryName));
657 Elements.push_back(MakeConstantString(ClassName));
658 // Instance method list
659 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattner578279d2008-06-26 05:08:00 +0000660 ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000661 false), PtrTy));
662 // Class method list
663 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattner578279d2008-06-26 05:08:00 +0000664 ClassName, CategoryName, ClassMethodSels, ClassMethodTypes, true),
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000665 PtrTy));
666 // Protocol list
667 Elements.push_back(llvm::ConstantExpr::getBitCast(
668 GenerateProtocolList(Protocols), PtrTy));
669 Categories.push_back(llvm::ConstantExpr::getBitCast(
670 MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, PtrTy,
671 PtrTy, PtrTy, NULL), Elements), PtrTy));
672}
Daniel Dunbarac93e472008-08-15 22:20:32 +0000673
674void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
675 ASTContext &Context = CGM.getContext();
676
677 // Get the superclass name.
678 const ObjCInterfaceDecl * SuperClassDecl =
679 OID->getClassInterface()->getSuperClass();
680 const char * SuperClassName = NULL;
681 if (SuperClassDecl) {
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000682 SuperClassName = SuperClassDecl->getIdentifierName();
Daniel Dunbarac93e472008-08-15 22:20:32 +0000683 }
684
685 // Get the class name
686 ObjCInterfaceDecl * ClassDecl = (ObjCInterfaceDecl*)OID->getClassInterface();
Douglas Gregor24afd4a2008-11-17 14:58:09 +0000687 const char * ClassName = ClassDecl->getIdentifierName();
Daniel Dunbarac93e472008-08-15 22:20:32 +0000688
689 // Get the size of instances. For runtimes that support late-bound instances
690 // this should probably be something different (size just of instance
691 // varaibles in this class, not superclasses?).
692 int instanceSize = 0;
693 const llvm::Type *ObjTy = 0;
694 if (!LateBoundIVars()) {
695 ObjTy = CGM.getTypes().ConvertType(Context.getObjCInterfaceType(ClassDecl));
696 instanceSize = CGM.getTargetData().getABITypeSize(ObjTy);
697 } else {
698 // This is required by newer ObjC runtimes.
699 assert(0 && "Late-bound instance variables not yet supported");
700 }
701
702 // Collect information about instance variables.
703 llvm::SmallVector<llvm::Constant*, 16> IvarNames;
704 llvm::SmallVector<llvm::Constant*, 16> IvarTypes;
705 llvm::SmallVector<llvm::Constant*, 16> IvarOffsets;
706 const llvm::StructLayout *Layout =
707 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(ObjTy));
708 ObjTy = llvm::PointerType::getUnqual(ObjTy);
709 for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
710 endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
711 // Store the name
712 IvarNames.push_back(CGM.GetAddrOfConstantCString((*iter)->getName()));
713 // Get the type encoding for this ivar
714 std::string TypeStr;
Daniel Dunbarc9197cd2008-10-17 20:21:44 +0000715 Context.getObjCEncodingForType((*iter)->getType(), TypeStr);
Daniel Dunbarac93e472008-08-15 22:20:32 +0000716 IvarTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
717 // Get the offset
718 int offset =
719 (int)Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(*iter));
720 IvarOffsets.push_back(
721 llvm::ConstantInt::get(llvm::Type::Int32Ty, offset));
722 }
723
724 // Collect information about instance methods
725 llvm::SmallVector<Selector, 16> InstanceMethodSels;
726 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
727 for (ObjCImplementationDecl::instmeth_iterator iter = OID->instmeth_begin(),
728 endIter = OID->instmeth_end() ; iter != endIter ; iter++) {
729 InstanceMethodSels.push_back((*iter)->getSelector());
730 std::string TypeStr;
731 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
732 InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
733 }
734
735 // Collect information about class methods
736 llvm::SmallVector<Selector, 16> ClassMethodSels;
737 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
738 for (ObjCImplementationDecl::classmeth_iterator iter = OID->classmeth_begin(),
739 endIter = OID->classmeth_end() ; iter != endIter ; iter++) {
740 ClassMethodSels.push_back((*iter)->getSelector());
741 std::string TypeStr;
742 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
743 ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
744 }
745 // Collect the names of referenced protocols
746 llvm::SmallVector<std::string, 16> Protocols;
747 const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
748 for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
749 E = Protos.end(); I != E; ++I)
750 Protocols.push_back((*I)->getName());
751
752
753
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000754 // Get the superclass pointer.
755 llvm::Constant *SuperClass;
756 if (SuperClassName) {
757 SuperClass = MakeConstantString(SuperClassName, ".super_class_name");
758 } else {
759 SuperClass = llvm::ConstantPointerNull::get(
760 llvm::cast<llvm::PointerType>(PtrToInt8Ty));
761 }
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000762 // Empty vector used to construct empty method lists
763 llvm::SmallVector<llvm::Constant*, 1> empty;
764 // Generate the method and instance variable lists
765 llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
Chris Lattner578279d2008-06-26 05:08:00 +0000766 InstanceMethodSels, InstanceMethodTypes, false);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000767 llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
Chris Lattner578279d2008-06-26 05:08:00 +0000768 ClassMethodSels, ClassMethodTypes, true);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000769 llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
770 IvarOffsets);
771 //Generate metaclass for class methods
772 llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
Chris Lattner4d018542008-07-21 06:31:05 +0000773 NULLPtr, 0x2L, /*name*/"", 0, Zeros[0], GenerateIvarList(
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000774 empty, empty, empty), ClassMethodList, NULLPtr);
775 // Generate the class structure
776 llvm::Constant *ClassStruct = GenerateClassStructure(MetaClassStruct,
Chris Lattnerad9c3f32008-06-26 04:47:04 +0000777 SuperClass, 0x1L, ClassName, 0,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000778 llvm::ConstantInt::get(llvm::Type::Int32Ty, instanceSize), IvarList,
779 MethodList, GenerateProtocolList(Protocols));
780 // Add class structure to list to be added to the symtab later
781 ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty);
782 Classes.push_back(ClassStruct);
783}
784
785llvm::Function *CGObjCGNU::ModuleInitFunction() {
786 // Only emit an ObjC load function if no Objective-C stuff has been called
787 if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
788 ExistingProtocols.empty() && TypedSelectors.empty() &&
Anton Korobeynikovb41e4972008-06-01 15:14:46 +0000789 UntypedSelectors.empty())
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000790 return NULL;
Eli Friedman7719bc82008-06-01 16:00:02 +0000791
792 // Name the ObjC types to make the IR a bit easier to read
793 TheModule.addTypeName(".objc_selector", SelectorTy);
794 TheModule.addTypeName(".objc_id", IdTy);
795 TheModule.addTypeName(".objc_imp", IMPTy);
796
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000797 std::vector<llvm::Constant*> Elements;
798 // Generate statics list:
799 llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
800 ConstantStrings.size() + 1);
801 ConstantStrings.push_back(NULLPtr);
802 Elements.push_back(MakeConstantString("NSConstantString",
803 ".objc_static_class_name"));
804 Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy, ConstantStrings));
805 llvm::StructType *StaticsListTy =
806 llvm::StructType::get(PtrToInt8Ty, StaticsArrayTy, NULL);
Chris Lattneref843042008-06-26 04:10:42 +0000807 llvm::Type *StaticsListPtrTy = llvm::PointerType::getUnqual(StaticsListTy);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000808 llvm::Constant *Statics =
809 MakeGlobal(StaticsListTy, Elements, ".objc_statics");
Chris Lattner60eaae82008-06-24 17:01:28 +0000810 llvm::ArrayType *StaticsListArrayTy =
Chris Lattneref843042008-06-26 04:10:42 +0000811 llvm::ArrayType::get(StaticsListPtrTy, 2);
Chris Lattner60eaae82008-06-24 17:01:28 +0000812 Elements.clear();
813 Elements.push_back(Statics);
Chris Lattneref843042008-06-26 04:10:42 +0000814 Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
Chris Lattner60eaae82008-06-24 17:01:28 +0000815 Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr");
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000816 Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
817 // Array of classes, categories, and constant objects
818 llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty,
819 Classes.size() + Categories.size() + 2);
Chris Lattneref843042008-06-26 04:10:42 +0000820 llvm::StructType *SymTabTy = llvm::StructType::get(LongTy, SelectorTy,
821 llvm::Type::Int16Ty,
822 llvm::Type::Int16Ty,
823 ClassListTy, NULL);
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000824
825 Elements.clear();
826 // Pointer to an array of selectors used in this module.
827 std::vector<llvm::Constant*> Selectors;
828 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
829 iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end();
830 iter != iterEnd ; ++iter) {
Chris Lattneref843042008-06-26 04:10:42 +0000831 Elements.push_back(MakeConstantString(iter->first.first, ".objc_sel_name"));
832 Elements.push_back(MakeConstantString(iter->first.second,
833 ".objc_sel_types"));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000834 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
835 Elements.clear();
836 }
837 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
838 iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
Chris Lattneref843042008-06-26 04:10:42 +0000839 iter != iterEnd; ++iter) {
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000840 Elements.push_back(
Chris Lattneref843042008-06-26 04:10:42 +0000841 MakeConstantString(iter->getKeyData(), ".objc_sel_name"));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000842 Elements.push_back(NULLPtr);
843 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
844 Elements.clear();
845 }
846 Elements.push_back(NULLPtr);
847 Elements.push_back(NULLPtr);
848 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
849 Elements.clear();
850 // Number of static selectors
851 Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() ));
852 llvm::Constant *SelectorList = MakeGlobal(
853 llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors,
854 ".objc_selector_list");
855 Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList, SelectorTy));
856
857 // Now that all of the static selectors exist, create pointers to them.
858 int index = 0;
859 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
860 iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end();
861 iter != iterEnd; ++iter) {
862 llvm::Constant *Idxs[] = {Zeros[0],
863 llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]};
864 llvm::GlobalVariable *SelPtr = new llvm::GlobalVariable(SelectorTy, true,
865 llvm::GlobalValue::InternalLinkage,
866 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
867 ".objc_sel_ptr", &TheModule);
868 (*iter).second->setAliasee(SelPtr);
869 }
870 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
871 iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
872 iter != iterEnd; iter++) {
873 llvm::Constant *Idxs[] = {Zeros[0],
874 llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]};
875 llvm::GlobalVariable *SelPtr = new llvm::GlobalVariable(SelectorTy, true,
876 llvm::GlobalValue::InternalLinkage,
877 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
878 ".objc_sel_ptr", &TheModule);
879 (*iter).second->setAliasee(SelPtr);
880 }
881 // Number of classes defined.
882 Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty,
883 Classes.size()));
884 // Number of categories defined
885 Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty,
886 Categories.size()));
887 // Create an array of classes, then categories, then static object instances
888 Classes.insert(Classes.end(), Categories.begin(), Categories.end());
889 // NULL-terminated list of static object instances (mainly constant strings)
890 Classes.push_back(Statics);
891 Classes.push_back(NULLPtr);
892 llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes);
893 Elements.push_back(ClassList);
894 // Construct the symbol table
895 llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements);
896
897 // The symbol table is contained in a module which has some version-checking
898 // constants
899 llvm::StructType * ModuleTy = llvm::StructType::get(LongTy, LongTy,
900 PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL);
901 Elements.clear();
902 // Runtime version used for compatibility checking.
903 Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
904 //FIXME: Should be sizeof(ModuleTy)
905 Elements.push_back(llvm::ConstantInt::get(LongTy, 16));
906 //FIXME: Should be the path to the file where this module was declared
907 Elements.push_back(NULLPtr);
908 Elements.push_back(SymTab);
909 llvm::Value *Module = MakeGlobal(ModuleTy, Elements);
910
911 // Create the load function calling the runtime entry point with the module
912 // structure
913 std::vector<const llvm::Type*> VoidArgs;
914 llvm::Function * LoadFunction = llvm::Function::Create(
915 llvm::FunctionType::get(llvm::Type::VoidTy, VoidArgs, false),
916 llvm::GlobalValue::InternalLinkage, ".objc_load_function",
917 &TheModule);
918 llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", LoadFunction);
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000919 CGBuilderTy Builder;
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000920 Builder.SetInsertPoint(EntryBB);
921 llvm::Value *Register = TheModule.getOrInsertFunction("__objc_exec_class",
922 llvm::Type::VoidTy, llvm::PointerType::getUnqual(ModuleTy), NULL);
923 Builder.CreateCall(Register, Module);
924 Builder.CreateRetVoid();
925 return LoadFunction;
926}
Daniel Dunbarac93e472008-08-15 22:20:32 +0000927
928llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD) {
Daniel Dunbarac93e472008-08-15 22:20:32 +0000929 const ObjCCategoryImplDecl *OCD =
930 dyn_cast<ObjCCategoryImplDecl>(OMD->getMethodContext());
931 const std::string &CategoryName = OCD ? OCD->getName() : "";
Daniel Dunbarac93e472008-08-15 22:20:32 +0000932 const std::string &ClassName = OMD->getClassInterface()->getName();
933 const std::string &MethodName = OMD->getSelector().getName();
Daniel Dunbarac93e472008-08-15 22:20:32 +0000934 bool isClassMethod = !OMD->isInstance();
Daniel Dunbarac93e472008-08-15 22:20:32 +0000935
Daniel Dunbar3ad1f072008-09-10 04:01:49 +0000936 const llvm::FunctionType *MethodTy =
937 CGM.getTypes().GetFunctionType(CGFunctionInfo(OMD, CGM.getContext()));
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000938 std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
939 MethodName, isClassMethod);
940
Gabor Greif815e2c12008-04-06 20:42:52 +0000941 llvm::Function *Method = llvm::Function::Create(MethodTy,
Chris Lattnerb326b172008-03-30 23:03:07 +0000942 llvm::GlobalValue::InternalLinkage,
Anton Korobeynikovcd5d08d2008-06-01 14:13:53 +0000943 FunctionName,
Chris Lattnerb326b172008-03-30 23:03:07 +0000944 &TheModule);
Chris Lattnerb326b172008-03-30 23:03:07 +0000945 return Method;
946}
947
Daniel Dunbarf7103722008-09-24 03:38:44 +0000948llvm::Function *CGObjCGNU::GetPropertyGetFunction() {
949 return 0;
950}
951
952llvm::Function *CGObjCGNU::GetPropertySetFunction() {
953 return 0;
954}
955
956llvm::Function *CGObjCGNU::EnumerationMutationFunction() {
Anders Carlsson58d16242008-08-31 04:05:03 +0000957 return 0;
958}
959
Anders Carlssonb01a2112008-09-09 10:04:29 +0000960void CGObjCGNU::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbarf7103722008-09-24 03:38:44 +0000961 const ObjCAtTryStmt &S) {
Anders Carlssonb01a2112008-09-09 10:04:29 +0000962 CGF.ErrorUnsupported(&S, "@try statement");
963}
964
965void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbarf7103722008-09-24 03:38:44 +0000966 const ObjCAtThrowStmt &S) {
Anders Carlssonb01a2112008-09-09 10:04:29 +0000967 CGF.ErrorUnsupported(&S, "@throw statement");
968}
969
Chris Lattnerdd978702008-11-15 21:26:17 +0000970void CGObjCGNU::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
971 const ObjCAtSynchronizedStmt &S) {
972 CGF.ErrorUnsupported(&S, "@synchronized statement");
973}
974
Fariborz Jahanian252d87f2008-11-18 22:37:34 +0000975llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian3305ad32008-11-18 21:45:40 +0000976 llvm::Value *AddrWeakObj)
977{
978 return 0;
979}
980
Fariborz Jahanian252d87f2008-11-18 22:37:34 +0000981void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
982 llvm::Value *src, llvm::Value *dst)
983{
984 return;
985}
986
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000987CodeGen::CGObjCRuntime *CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM){
Chris Lattner547907c2008-06-26 04:19:03 +0000988 return new CGObjCGNU(CGM);
Chris Lattnera0fd5ee2008-03-01 08:50:34 +0000989}