blob: d77ae0593929cc6ee4027dec75d71f71141233e9 [file] [log] [blame]
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
Chris Lattner0f984262008-03-01 08:50:34 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000010// This provides Objective-C code generation targetting the GNU runtime. The
11// class in this file generates structures used by the GNU Objective-C runtime
12// library. These structures are defined in objc/objc.h and objc/objc-api.h in
13// the GNU runtime distribution.
Chris Lattner0f984262008-03-01 08:50:34 +000014//
15//===----------------------------------------------------------------------===//
16
17#include "CGObjCRuntime.h"
Chris Lattnerdce14062008-06-26 04:19:03 +000018#include "CodeGenModule.h"
19#include "clang/AST/ASTContext.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000020#include "clang/AST/Decl.h"
Chris Lattner0f984262008-03-01 08:50:34 +000021#include "llvm/Module.h"
22#include "llvm/Support/Compiler.h"
Chris Lattner50b36742008-04-13 07:32:11 +000023#include "llvm/Support/IRBuilder.h"
Chris Lattner0f984262008-03-01 08:50:34 +000024#include "llvm/ADT/SmallVector.h"
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000025#include "llvm/ADT/StringMap.h"
26#include <map>
Chris Lattnerdce14062008-06-26 04:19:03 +000027using namespace clang;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000028using llvm::dyn_cast;
29
30// The version of the runtime that this class targets. Must match the version
31// in the runtime.
32static const int RuntimeVersion = 8;
33static const int ProtocolVersion = 2;
Chris Lattner0f984262008-03-01 08:50:34 +000034
Chris Lattner0f984262008-03-01 08:50:34 +000035namespace {
Chris Lattnerdce14062008-06-26 04:19:03 +000036class CGObjCGNU : public CodeGen::CGObjCRuntime {
Chris Lattner0f984262008-03-01 08:50:34 +000037private:
Chris Lattnerdce14062008-06-26 04:19:03 +000038 CodeGen::CodeGenModule &CGM;
Chris Lattner0f984262008-03-01 08:50:34 +000039 llvm::Module &TheModule;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000040 const llvm::StructType *SelStructTy;
Chris Lattner391d77a2008-03-30 23:03:07 +000041 const llvm::Type *SelectorTy;
42 const llvm::Type *PtrToInt8Ty;
43 const llvm::Type *IMPTy;
44 const llvm::Type *IdTy;
45 const llvm::Type *IntTy;
46 const llvm::Type *PtrTy;
47 const llvm::Type *LongTy;
48 const llvm::Type *PtrToIntTy;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000049 std::vector<llvm::Constant*> Classes;
50 std::vector<llvm::Constant*> Categories;
51 std::vector<llvm::Constant*> ConstantStrings;
52 llvm::Function *LoadFunction;
53 llvm::StringMap<llvm::Constant*> ExistingProtocols;
54 typedef std::pair<std::string, std::string> TypedSelector;
55 std::map<TypedSelector, llvm::GlobalAlias*> TypedSelectors;
56 llvm::StringMap<llvm::GlobalAlias*> UntypedSelectors;
57 // Some zeros used for GEPs in lots of places.
58 llvm::Constant *Zeros[2];
59 llvm::Constant *NULLPtr;
60private:
61 llvm::Constant *GenerateIvarList(
62 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
63 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
64 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets);
65 llvm::Constant *GenerateMethodList(const std::string &ClassName,
66 const std::string &CategoryName,
Chris Lattnera4210072008-06-26 05:08:00 +000067 const llvm::SmallVectorImpl<Selector> &MethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000068 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
69 bool isClassMethodList);
70 llvm::Constant *GenerateProtocolList(
71 const llvm::SmallVectorImpl<std::string> &Protocols);
72 llvm::Constant *GenerateClassStructure(
73 llvm::Constant *MetaClass,
74 llvm::Constant *SuperClass,
75 unsigned info,
Chris Lattnerd002cc62008-06-26 04:47:04 +000076 const char *Name,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000077 llvm::Constant *Version,
78 llvm::Constant *InstanceSize,
79 llvm::Constant *IVars,
80 llvm::Constant *Methods,
81 llvm::Constant *Protocols);
82 llvm::Constant *GenerateProtocolMethodList(
83 const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
84 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes);
85 llvm::Constant *MakeConstantString(const std::string &Str, const std::string
86 &Name="");
87 llvm::Constant *MakeGlobal(const llvm::StructType *Ty,
88 std::vector<llvm::Constant*> &V, const std::string &Name="");
89 llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty,
90 std::vector<llvm::Constant*> &V, const std::string &Name="");
Chris Lattner0f984262008-03-01 08:50:34 +000091public:
Chris Lattnerdce14062008-06-26 04:19:03 +000092 CGObjCGNU(CodeGen::CodeGenModule &cgm);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000093 virtual llvm::Constant *GenerateConstantString(const char *String,
94 const size_t length);
Chris Lattner85e35682008-08-08 19:57:58 +000095 virtual llvm::Value *GenerateMessageSend(llvm::IRBuilder<> &Builder,
Chris Lattner0f984262008-03-01 08:50:34 +000096 const llvm::Type *ReturnTy,
Chris Lattner391d77a2008-03-30 23:03:07 +000097 llvm::Value *Sender,
Chris Lattner0f984262008-03-01 08:50:34 +000098 llvm::Value *Receiver,
Chris Lattner9384c762008-06-26 04:42:20 +000099 Selector Sel,
Chris Lattner0f984262008-03-01 08:50:34 +0000100 llvm::Value** ArgV,
101 unsigned ArgC);
Chris Lattner85e35682008-08-08 19:57:58 +0000102 virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
Chris Lattner8e67b632008-06-26 04:37:12 +0000103 const llvm::Type *ReturnTy,
104 llvm::Value *Sender,
105 const char *SuperClassName,
106 llvm::Value *Receiver,
107 Selector Sel,
108 llvm::Value** ArgV,
109 unsigned ArgC);
Chris Lattner85e35682008-08-08 19:57:58 +0000110 virtual llvm::Value *LookupClass(llvm::IRBuilder<> &Builder,
Chris Lattner9384c762008-06-26 04:42:20 +0000111 llvm::Value *ClassName);
Chris Lattner85e35682008-08-08 19:57:58 +0000112 virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel);
Chris Lattner8e67b632008-06-26 04:37:12 +0000113
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000114 virtual llvm::Function *MethodPreamble(
115 const std::string &ClassName,
116 const std::string &CategoryName,
117 const std::string &MethodName,
118 const llvm::Type *ReturnTy,
119 const llvm::Type *SelfTy,
120 const llvm::Type **ArgTy,
121 unsigned ArgC,
122 bool isClassMethod,
123 bool isVarArg);
124 virtual void GenerateCategory(const char *ClassName, const char *CategoryName,
Chris Lattnera4210072008-06-26 05:08:00 +0000125 const llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000126 const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes,
Chris Lattnera4210072008-06-26 05:08:00 +0000127 const llvm::SmallVectorImpl<Selector> &ClassMethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000128 const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes,
129 const llvm::SmallVectorImpl<std::string> &Protocols);
130 virtual void GenerateClass(
131 const char *ClassName,
132 const char *SuperClassName,
133 const int instanceSize,
134 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
135 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
136 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets,
Chris Lattnera4210072008-06-26 05:08:00 +0000137 const llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000138 const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes,
Chris Lattnera4210072008-06-26 05:08:00 +0000139 const llvm::SmallVectorImpl<Selector> &ClassMethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000140 const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes,
141 const llvm::SmallVectorImpl<std::string> &Protocols);
Chris Lattner85e35682008-08-08 19:57:58 +0000142 virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder<> &Builder,
143 const char *ProtocolName);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000144 virtual void GenerateProtocol(const char *ProtocolName,
145 const llvm::SmallVectorImpl<std::string> &Protocols,
146 const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodNames,
147 const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes,
148 const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodNames,
149 const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes);
150 virtual llvm::Function *ModuleInitFunction();
Chris Lattner0f984262008-03-01 08:50:34 +0000151};
152} // end anonymous namespace
153
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000154
155
156static std::string SymbolNameForClass(const std::string &ClassName) {
157 return ".objc_class_" + ClassName;
158}
159
160static std::string SymbolNameForMethod(const std::string &ClassName, const
161 std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
162{
163 return "._objc_method_" + ClassName +"("+CategoryName+")"+
164 (isClassMethod ? "+" : "-") + MethodName;
165}
166
Chris Lattnerdce14062008-06-26 04:19:03 +0000167CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
168 : CGM(cgm), TheModule(CGM.getModule()) {
169 IntTy = CGM.getTypes().ConvertType(CGM.getContext().IntTy);
170 LongTy = CGM.getTypes().ConvertType(CGM.getContext().LongTy);
171
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000172 Zeros[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
173 Zeros[1] = Zeros[0];
174 NULLPtr = llvm::ConstantPointerNull::get(
175 llvm::PointerType::getUnqual(llvm::Type::Int8Ty));
Chris Lattner391d77a2008-03-30 23:03:07 +0000176 // C string type. Used in lots of places.
177 PtrToInt8Ty =
178 llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
179 // Get the selector Type.
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000180 SelStructTy = llvm::StructType::get(
Chris Lattner391d77a2008-03-30 23:03:07 +0000181 PtrToInt8Ty,
182 PtrToInt8Ty,
183 NULL);
184 SelectorTy = llvm::PointerType::getUnqual(SelStructTy);
185 PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
186 PtrTy = PtrToInt8Ty;
187
188 // Object type
189 llvm::PATypeHolder OpaqueObjTy = llvm::OpaqueType::get();
190 llvm::Type *OpaqueIdTy = llvm::PointerType::getUnqual(OpaqueObjTy);
191 IdTy = llvm::StructType::get(OpaqueIdTy, NULL);
192 llvm::cast<llvm::OpaqueType>(OpaqueObjTy.get())->refineAbstractTypeTo(IdTy);
193 IdTy = llvm::cast<llvm::StructType>(OpaqueObjTy.get());
194 IdTy = llvm::PointerType::getUnqual(IdTy);
195
196 // IMP type
197 std::vector<const llvm::Type*> IMPArgs;
198 IMPArgs.push_back(IdTy);
199 IMPArgs.push_back(SelectorTy);
200 IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000201}
202// This has to perform the lookup every time, since posing and related
203// techniques can modify the name -> class mapping.
Chris Lattner85e35682008-08-08 19:57:58 +0000204llvm::Value *CGObjCGNU::LookupClass(llvm::IRBuilder<> &Builder,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000205 llvm::Value *ClassName) {
206 llvm::Constant *ClassLookupFn =
207 TheModule.getOrInsertFunction("objc_lookup_class", IdTy, PtrToInt8Ty,
208 NULL);
209 return Builder.CreateCall(ClassLookupFn, ClassName);
Chris Lattner391d77a2008-03-30 23:03:07 +0000210}
211
Chris Lattner8e67b632008-06-26 04:37:12 +0000212/// GetSelector - Return the pointer to the unique'd string for this selector.
Chris Lattner85e35682008-08-08 19:57:58 +0000213llvm::Value *CGObjCGNU::GetSelector(llvm::IRBuilder<> &Builder, Selector Sel) {
Chris Lattner8e67b632008-06-26 04:37:12 +0000214 // FIXME: uniquing on the string is wasteful, unique on Sel instead!
215 llvm::GlobalAlias *&US = UntypedSelectors[Sel.getName()];
216 if (US == 0)
217 US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy),
218 llvm::GlobalValue::InternalLinkage,
219 ".objc_untyped_selector_alias",
220 NULL, &TheModule);
221
222 return Builder.CreateLoad(US);
223
224}
225
Chris Lattner5e7dcc62008-06-26 04:44:19 +0000226llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str,
227 const std::string &Name) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000228 llvm::Constant * ConstStr = llvm::ConstantArray::get(Str);
229 ConstStr = new llvm::GlobalVariable(ConstStr->getType(), true,
230 llvm::GlobalValue::InternalLinkage,
231 ConstStr, Name, &TheModule);
232 return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
233}
234llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty,
235 std::vector<llvm::Constant*> &V, const std::string &Name) {
236 llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
237 return new llvm::GlobalVariable(Ty, false,
238 llvm::GlobalValue::InternalLinkage, C, Name, &TheModule);
239}
240llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
241 std::vector<llvm::Constant*> &V, const std::string &Name) {
242 llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
243 return new llvm::GlobalVariable(Ty, false,
244 llvm::GlobalValue::InternalLinkage, C, Name, &TheModule);
245}
246
247/// Generate an NSConstantString object.
248//TODO: In case there are any crazy people still using the GNU runtime without
249//an OpenStep implementation, this should let them select their own class for
250//constant strings.
251llvm::Constant *CGObjCGNU::GenerateConstantString(const char *String, const
252 size_t length) {
Chris Lattner13fd7e52008-06-21 21:44:18 +0000253 std::string Str(String, String +length);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000254 std::vector<llvm::Constant*> Ivars;
255 Ivars.push_back(NULLPtr);
Chris Lattner13fd7e52008-06-21 21:44:18 +0000256 Ivars.push_back(MakeConstantString(Str));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000257 Ivars.push_back(llvm::ConstantInt::get(IntTy, length));
258 llvm::Constant *ObjCStr = MakeGlobal(
259 llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL),
260 Ivars, ".objc_str");
261 ConstantStrings.push_back(
262 llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty));
263 return ObjCStr;
264}
265
266///Generates a message send where the super is the receiver. This is a message
267///send to self with special delivery semantics indicating which class's method
268///should be called.
Chris Lattner85e35682008-08-08 19:57:58 +0000269llvm::Value *CGObjCGNU::GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
Chris Lattner8e67b632008-06-26 04:37:12 +0000270 const llvm::Type *ReturnTy,
271 llvm::Value *Sender,
272 const char *SuperClassName,
273 llvm::Value *Receiver,
274 Selector Sel,
275 llvm::Value** ArgV,
276 unsigned ArgC) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000277 // TODO: This should be cached, not looked up every time.
278 llvm::Value *ReceiverClass = LookupClass(Builder,
279 MakeConstantString(SuperClassName));
Chris Lattner8e67b632008-06-26 04:37:12 +0000280 llvm::Value *cmd = GetSelector(Builder, Sel);
Chris Lattner0f984262008-03-01 08:50:34 +0000281 std::vector<const llvm::Type*> impArgTypes;
282 impArgTypes.push_back(Receiver->getType());
Chris Lattner391d77a2008-03-30 23:03:07 +0000283 impArgTypes.push_back(SelectorTy);
Chris Lattner0f984262008-03-01 08:50:34 +0000284
285 // Avoid an explicit cast on the IMP by getting a version that has the right
286 // return type.
287 llvm::FunctionType *impType = llvm::FunctionType::get(ReturnTy, impArgTypes,
288 true);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000289 // Construct the structure used to look up the IMP
290 llvm::StructType *ObjCSuperTy = llvm::StructType::get(Receiver->getType(),
291 IdTy, NULL);
292 llvm::Value *ObjCSuper = Builder.CreateAlloca(ObjCSuperTy);
Eli Friedman1e692ac2008-06-13 23:01:12 +0000293 // FIXME: volatility
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000294 Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
295 Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
296
297 // Get the IMP
298 llvm::Constant *lookupFunction =
299 TheModule.getOrInsertFunction("objc_msg_lookup_super",
300 llvm::PointerType::getUnqual(impType),
301 llvm::PointerType::getUnqual(ObjCSuperTy),
302 SelectorTy, NULL);
303 llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
304 llvm::Value *imp = Builder.CreateCall(lookupFunction, lookupArgs,
305 lookupArgs+2);
306
307 // Call the method
308 llvm::SmallVector<llvm::Value*, 8> callArgs;
309 callArgs.push_back(Receiver);
310 callArgs.push_back(cmd);
311 callArgs.insert(callArgs.end(), ArgV, ArgV+ArgC);
312 return Builder.CreateCall(imp, callArgs.begin(), callArgs.end());
313}
314
315/// Generate code for a message send expression.
Chris Lattner85e35682008-08-08 19:57:58 +0000316llvm::Value *CGObjCGNU::GenerateMessageSend(llvm::IRBuilder<> &Builder,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000317 const llvm::Type *ReturnTy,
318 llvm::Value *Sender,
319 llvm::Value *Receiver,
Chris Lattner9384c762008-06-26 04:42:20 +0000320 Selector Sel,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000321 llvm::Value** ArgV,
322 unsigned ArgC) {
Chris Lattner9384c762008-06-26 04:42:20 +0000323 llvm::Value *cmd = GetSelector(Builder, Sel);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000324
325 // Look up the method implementation.
326 std::vector<const llvm::Type*> impArgTypes;
327 const llvm::Type *RetTy;
328 //TODO: Revisit this when LLVM supports aggregate return types.
329 if (ReturnTy->isSingleValueType() && ReturnTy != llvm::Type::VoidTy) {
330 RetTy = ReturnTy;
331 } else {
332 // For struct returns allocate the space in the caller and pass it up to
333 // the sender.
334 RetTy = llvm::Type::VoidTy;
335 impArgTypes.push_back(llvm::PointerType::getUnqual(ReturnTy));
336 }
337 impArgTypes.push_back(Receiver->getType());
338 impArgTypes.push_back(SelectorTy);
339
340 // Avoid an explicit cast on the IMP by getting a version that has the right
341 // return type.
342 llvm::FunctionType *impType = llvm::FunctionType::get(RetTy, impArgTypes,
343 true);
Chris Lattner0f984262008-03-01 08:50:34 +0000344
345 llvm::Constant *lookupFunction =
346 TheModule.getOrInsertFunction("objc_msg_lookup",
Chris Lattner391d77a2008-03-30 23:03:07 +0000347 llvm::PointerType::getUnqual(impType),
348 Receiver->getType(), SelectorTy, NULL);
Chris Lattner3eae03e2008-05-06 00:56:42 +0000349 llvm::Value *imp = Builder.CreateCall2(lookupFunction, Receiver, cmd);
350
351 // Call the method.
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000352 llvm::SmallVector<llvm::Value*, 16> Args;
353 if (!ReturnTy->isSingleValueType()) {
354 llvm::Value *Return = Builder.CreateAlloca(ReturnTy);
355 Args.push_back(Return);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000356 }
357 Args.push_back(Receiver);
358 Args.push_back(cmd);
359 Args.insert(Args.end(), ArgV, ArgV+ArgC);
Chris Lattner8fdf3282008-06-24 17:04:18 +0000360 if (!ReturnTy->isSingleValueType()) {
361 Builder.CreateCall(imp, Args.begin(), Args.end());
362 return Args[0];
363 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000364 return Builder.CreateCall(imp, Args.begin(), Args.end());
Chris Lattner0f984262008-03-01 08:50:34 +0000365}
366
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000367/// Generates a MethodList. Used in construction of a objc_class and
368/// objc_category structures.
369llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName,
Chris Lattnera4210072008-06-26 05:08:00 +0000370 const std::string &CategoryName,
371 const llvm::SmallVectorImpl<Selector> &MethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000372 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
373 bool isClassMethodList) {
374 // Get the method structure type.
375 llvm::StructType *ObjCMethodTy = llvm::StructType::get(
376 PtrToInt8Ty, // Really a selector, but the runtime creates it us.
377 PtrToInt8Ty, // Method types
378 llvm::PointerType::getUnqual(IMPTy), //Method pointer
379 NULL);
380 std::vector<llvm::Constant*> Methods;
381 std::vector<llvm::Constant*> Elements;
382 for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
383 Elements.clear();
Chris Lattnera4210072008-06-26 05:08:00 +0000384 llvm::Constant *C = CGM.GetAddrOfConstantString(MethodSels[i].getName());
385 Elements.push_back(llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000386 Elements.push_back(
387 llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
388 llvm::Constant *Method =
389 TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
Chris Lattnera4210072008-06-26 05:08:00 +0000390 MethodSels[i].getName(),
Chris Lattner550b8db2008-06-26 04:05:20 +0000391 isClassMethodList));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000392 Method = llvm::ConstantExpr::getBitCast(Method,
393 llvm::PointerType::getUnqual(IMPTy));
394 Elements.push_back(Method);
395 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements));
396 }
397
398 // Array of method structures
399 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
Chris Lattnera4210072008-06-26 05:08:00 +0000400 MethodSels.size());
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000401 llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy,
Chris Lattnerfba67632008-06-26 04:52:29 +0000402 Methods);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000403
404 // Structure containing list pointer, array and array count
405 llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields;
406 llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get();
407 llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy);
408 llvm::StructType *ObjCMethodListTy = llvm::StructType::get(NextPtrTy,
409 IntTy,
410 ObjCMethodArrayTy,
411 NULL);
412 // Refine next pointer type to concrete type
413 llvm::cast<llvm::OpaqueType>(
414 OpaqueNextTy.get())->refineAbstractTypeTo(ObjCMethodListTy);
415 ObjCMethodListTy = llvm::cast<llvm::StructType>(OpaqueNextTy.get());
416
417 Methods.clear();
418 Methods.push_back(llvm::ConstantPointerNull::get(
419 llvm::PointerType::getUnqual(ObjCMethodListTy)));
420 Methods.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty,
421 MethodTypes.size()));
422 Methods.push_back(MethodArray);
423
424 // Create an instance of the structure
425 return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list");
426}
427
428/// Generates an IvarList. Used in construction of a objc_class.
429llvm::Constant *CGObjCGNU::GenerateIvarList(
430 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
431 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
432 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) {
433 // Get the method structure type.
434 llvm::StructType *ObjCIvarTy = llvm::StructType::get(
435 PtrToInt8Ty,
436 PtrToInt8Ty,
437 IntTy,
438 NULL);
439 std::vector<llvm::Constant*> Ivars;
440 std::vector<llvm::Constant*> Elements;
441 for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
442 Elements.clear();
443 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarNames[i],
444 Zeros, 2));
445 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarTypes[i],
446 Zeros, 2));
447 Elements.push_back(IvarOffsets[i]);
448 Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements));
449 }
450
451 // Array of method structures
452 llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
453 IvarNames.size());
454
455
456 Elements.clear();
457 Elements.push_back(llvm::ConstantInt::get(
458 llvm::cast<llvm::IntegerType>(IntTy), (int)IvarNames.size()));
459 Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars));
460 // Structure containing array and array count
461 llvm::StructType *ObjCIvarListTy = llvm::StructType::get(IntTy,
462 ObjCIvarArrayTy,
463 NULL);
464
465 // Create an instance of the structure
466 return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list");
467}
468
469/// Generate a class structure
470llvm::Constant *CGObjCGNU::GenerateClassStructure(
471 llvm::Constant *MetaClass,
472 llvm::Constant *SuperClass,
473 unsigned info,
Chris Lattnerd002cc62008-06-26 04:47:04 +0000474 const char *Name,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000475 llvm::Constant *Version,
476 llvm::Constant *InstanceSize,
477 llvm::Constant *IVars,
478 llvm::Constant *Methods,
479 llvm::Constant *Protocols) {
480 // Set up the class structure
481 // Note: Several of these are char*s when they should be ids. This is
482 // because the runtime performs this translation on load.
483 llvm::StructType *ClassTy = llvm::StructType::get(
484 PtrToInt8Ty, // class_pointer
485 PtrToInt8Ty, // super_class
486 PtrToInt8Ty, // name
487 LongTy, // version
488 LongTy, // info
489 LongTy, // instance_size
490 IVars->getType(), // ivars
491 Methods->getType(), // methods
492 // These are all filled in by the runtime, so we pretend
493 PtrTy, // dtable
494 PtrTy, // subclass_list
495 PtrTy, // sibling_class
496 PtrTy, // protocols
497 PtrTy, // gc_object_type
498 NULL);
499 llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
500 llvm::Constant *NullP =
501 llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(PtrTy));
502 // Fill in the structure
503 std::vector<llvm::Constant*> Elements;
504 Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
505 Elements.push_back(SuperClass);
Chris Lattnerd002cc62008-06-26 04:47:04 +0000506 Elements.push_back(MakeConstantString(Name, ".class_name"));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000507 Elements.push_back(Zero);
508 Elements.push_back(llvm::ConstantInt::get(LongTy, info));
509 Elements.push_back(InstanceSize);
510 Elements.push_back(IVars);
511 Elements.push_back(Methods);
512 Elements.push_back(NullP);
513 Elements.push_back(NullP);
514 Elements.push_back(NullP);
515 Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
516 Elements.push_back(NullP);
517 // Create an instance of the structure
Chris Lattner1565e032008-07-21 06:31:05 +0000518 return MakeGlobal(ClassTy, Elements, SymbolNameForClass(Name));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000519}
520
521llvm::Constant *CGObjCGNU::GenerateProtocolMethodList(
522 const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
523 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes) {
524 // Get the method structure type.
525 llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(
526 PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
527 PtrToInt8Ty,
528 NULL);
529 std::vector<llvm::Constant*> Methods;
530 std::vector<llvm::Constant*> Elements;
531 for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
532 Elements.clear();
533 Elements.push_back( llvm::ConstantExpr::getGetElementPtr(MethodNames[i],
534 Zeros, 2));
535 Elements.push_back(
536 llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
537 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements));
538 }
539 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
540 MethodNames.size());
541 llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy, Methods);
542 llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(
543 IntTy, ObjCMethodArrayTy, NULL);
544 Methods.clear();
545 Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
546 Methods.push_back(Array);
547 return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list");
548}
549// Create the protocol list structure used in classes, categories and so on
550llvm::Constant *CGObjCGNU::GenerateProtocolList(
551 const llvm::SmallVectorImpl<std::string> &Protocols) {
552 llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
553 Protocols.size());
554 llvm::StructType *ProtocolListTy = llvm::StructType::get(
555 PtrTy, //Should be a recurisve pointer, but it's always NULL here.
556 LongTy,//FIXME: Should be size_t
557 ProtocolArrayTy,
558 NULL);
559 std::vector<llvm::Constant*> Elements;
560 for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
561 iter != endIter ; iter++) {
562 llvm::Constant *Ptr =
563 llvm::ConstantExpr::getBitCast(ExistingProtocols[*iter], PtrToInt8Ty);
564 Elements.push_back(Ptr);
565 }
566 llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
567 Elements);
568 Elements.clear();
569 Elements.push_back(NULLPtr);
570 Elements.push_back(llvm::ConstantInt::get(
571 llvm::cast<llvm::IntegerType>(LongTy), Protocols.size()));
572 Elements.push_back(ProtocolArray);
573 return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list");
574}
575
Chris Lattner85e35682008-08-08 19:57:58 +0000576llvm::Value *CGObjCGNU::GenerateProtocolRef(llvm::IRBuilder<> &Builder, const
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000577 char *ProtocolName) {
578 return ExistingProtocols[ProtocolName];
579}
580
581void CGObjCGNU::GenerateProtocol(const char *ProtocolName,
582 const llvm::SmallVectorImpl<std::string> &Protocols,
583 const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodNames,
584 const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes,
585 const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodNames,
586 const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes) {
587
588 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
589 llvm::Constant *InstanceMethodList =
590 GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes);
591 llvm::Constant *ClassMethodList =
592 GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes);
593 // Protocols are objects containing lists of the methods implemented and
594 // protocols adopted.
595 llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy,
596 PtrToInt8Ty,
597 ProtocolList->getType(),
598 InstanceMethodList->getType(),
599 ClassMethodList->getType(),
600 NULL);
601 std::vector<llvm::Constant*> Elements;
602 // The isa pointer must be set to a magic number so the runtime knows it's
603 // the correct layout.
604 Elements.push_back(llvm::ConstantExpr::getIntToPtr(
605 llvm::ConstantInt::get(llvm::Type::Int32Ty, ProtocolVersion), IdTy));
606 Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
607 Elements.push_back(ProtocolList);
608 Elements.push_back(InstanceMethodList);
609 Elements.push_back(ClassMethodList);
610 ExistingProtocols[ProtocolName] =
611 llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
612 ".objc_protocol"), IdTy);
613}
614
615void CGObjCGNU::GenerateCategory(
616 const char *ClassName,
617 const char *CategoryName,
Chris Lattnera4210072008-06-26 05:08:00 +0000618 const llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000619 const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes,
Chris Lattnera4210072008-06-26 05:08:00 +0000620 const llvm::SmallVectorImpl<Selector> &ClassMethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000621 const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes,
622 const llvm::SmallVectorImpl<std::string> &Protocols) {
623 std::vector<llvm::Constant*> Elements;
624 Elements.push_back(MakeConstantString(CategoryName));
625 Elements.push_back(MakeConstantString(ClassName));
626 // Instance method list
627 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattnera4210072008-06-26 05:08:00 +0000628 ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000629 false), PtrTy));
630 // Class method list
631 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattnera4210072008-06-26 05:08:00 +0000632 ClassName, CategoryName, ClassMethodSels, ClassMethodTypes, true),
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000633 PtrTy));
634 // Protocol list
635 Elements.push_back(llvm::ConstantExpr::getBitCast(
636 GenerateProtocolList(Protocols), PtrTy));
637 Categories.push_back(llvm::ConstantExpr::getBitCast(
638 MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, PtrTy,
639 PtrTy, PtrTy, NULL), Elements), PtrTy));
640}
641void CGObjCGNU::GenerateClass(
642 const char *ClassName,
643 const char *SuperClassName,
644 const int instanceSize,
645 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
646 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
647 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets,
Chris Lattnera4210072008-06-26 05:08:00 +0000648 const llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000649 const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes,
Chris Lattnera4210072008-06-26 05:08:00 +0000650 const llvm::SmallVectorImpl<Selector> &ClassMethodSels,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000651 const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes,
652 const llvm::SmallVectorImpl<std::string> &Protocols) {
653 // Get the superclass pointer.
654 llvm::Constant *SuperClass;
655 if (SuperClassName) {
656 SuperClass = MakeConstantString(SuperClassName, ".super_class_name");
657 } else {
658 SuperClass = llvm::ConstantPointerNull::get(
659 llvm::cast<llvm::PointerType>(PtrToInt8Ty));
660 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000661 // Empty vector used to construct empty method lists
662 llvm::SmallVector<llvm::Constant*, 1> empty;
663 // Generate the method and instance variable lists
664 llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
Chris Lattnera4210072008-06-26 05:08:00 +0000665 InstanceMethodSels, InstanceMethodTypes, false);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000666 llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
Chris Lattnera4210072008-06-26 05:08:00 +0000667 ClassMethodSels, ClassMethodTypes, true);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000668 llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
669 IvarOffsets);
670 //Generate metaclass for class methods
671 llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
Chris Lattner1565e032008-07-21 06:31:05 +0000672 NULLPtr, 0x2L, /*name*/"", 0, Zeros[0], GenerateIvarList(
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000673 empty, empty, empty), ClassMethodList, NULLPtr);
674 // Generate the class structure
675 llvm::Constant *ClassStruct = GenerateClassStructure(MetaClassStruct,
Chris Lattnerd002cc62008-06-26 04:47:04 +0000676 SuperClass, 0x1L, ClassName, 0,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000677 llvm::ConstantInt::get(llvm::Type::Int32Ty, instanceSize), IvarList,
678 MethodList, GenerateProtocolList(Protocols));
679 // Add class structure to list to be added to the symtab later
680 ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty);
681 Classes.push_back(ClassStruct);
682}
683
684llvm::Function *CGObjCGNU::ModuleInitFunction() {
685 // Only emit an ObjC load function if no Objective-C stuff has been called
686 if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
687 ExistingProtocols.empty() && TypedSelectors.empty() &&
Anton Korobeynikov5f58b912008-06-01 15:14:46 +0000688 UntypedSelectors.empty())
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000689 return NULL;
Eli Friedman1b8956e2008-06-01 16:00:02 +0000690
691 // Name the ObjC types to make the IR a bit easier to read
692 TheModule.addTypeName(".objc_selector", SelectorTy);
693 TheModule.addTypeName(".objc_id", IdTy);
694 TheModule.addTypeName(".objc_imp", IMPTy);
695
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000696 std::vector<llvm::Constant*> Elements;
697 // Generate statics list:
698 llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
699 ConstantStrings.size() + 1);
700 ConstantStrings.push_back(NULLPtr);
701 Elements.push_back(MakeConstantString("NSConstantString",
702 ".objc_static_class_name"));
703 Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy, ConstantStrings));
704 llvm::StructType *StaticsListTy =
705 llvm::StructType::get(PtrToInt8Ty, StaticsArrayTy, NULL);
Chris Lattner630404b2008-06-26 04:10:42 +0000706 llvm::Type *StaticsListPtrTy = llvm::PointerType::getUnqual(StaticsListTy);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000707 llvm::Constant *Statics =
708 MakeGlobal(StaticsListTy, Elements, ".objc_statics");
Chris Lattner4e0b2642008-06-24 17:01:28 +0000709 llvm::ArrayType *StaticsListArrayTy =
Chris Lattner630404b2008-06-26 04:10:42 +0000710 llvm::ArrayType::get(StaticsListPtrTy, 2);
Chris Lattner4e0b2642008-06-24 17:01:28 +0000711 Elements.clear();
712 Elements.push_back(Statics);
Chris Lattner630404b2008-06-26 04:10:42 +0000713 Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
Chris Lattner4e0b2642008-06-24 17:01:28 +0000714 Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr");
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000715 Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
716 // Array of classes, categories, and constant objects
717 llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty,
718 Classes.size() + Categories.size() + 2);
Chris Lattner630404b2008-06-26 04:10:42 +0000719 llvm::StructType *SymTabTy = llvm::StructType::get(LongTy, SelectorTy,
720 llvm::Type::Int16Ty,
721 llvm::Type::Int16Ty,
722 ClassListTy, NULL);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000723
724 Elements.clear();
725 // Pointer to an array of selectors used in this module.
726 std::vector<llvm::Constant*> Selectors;
727 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
728 iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end();
729 iter != iterEnd ; ++iter) {
Chris Lattner630404b2008-06-26 04:10:42 +0000730 Elements.push_back(MakeConstantString(iter->first.first, ".objc_sel_name"));
731 Elements.push_back(MakeConstantString(iter->first.second,
732 ".objc_sel_types"));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000733 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
734 Elements.clear();
735 }
736 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
737 iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
Chris Lattner630404b2008-06-26 04:10:42 +0000738 iter != iterEnd; ++iter) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000739 Elements.push_back(
Chris Lattner630404b2008-06-26 04:10:42 +0000740 MakeConstantString(iter->getKeyData(), ".objc_sel_name"));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000741 Elements.push_back(NULLPtr);
742 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
743 Elements.clear();
744 }
745 Elements.push_back(NULLPtr);
746 Elements.push_back(NULLPtr);
747 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
748 Elements.clear();
749 // Number of static selectors
750 Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() ));
751 llvm::Constant *SelectorList = MakeGlobal(
752 llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors,
753 ".objc_selector_list");
754 Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList, SelectorTy));
755
756 // Now that all of the static selectors exist, create pointers to them.
757 int index = 0;
758 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
759 iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end();
760 iter != iterEnd; ++iter) {
761 llvm::Constant *Idxs[] = {Zeros[0],
762 llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]};
763 llvm::GlobalVariable *SelPtr = new llvm::GlobalVariable(SelectorTy, true,
764 llvm::GlobalValue::InternalLinkage,
765 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
766 ".objc_sel_ptr", &TheModule);
767 (*iter).second->setAliasee(SelPtr);
768 }
769 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
770 iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
771 iter != iterEnd; iter++) {
772 llvm::Constant *Idxs[] = {Zeros[0],
773 llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]};
774 llvm::GlobalVariable *SelPtr = new llvm::GlobalVariable(SelectorTy, true,
775 llvm::GlobalValue::InternalLinkage,
776 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
777 ".objc_sel_ptr", &TheModule);
778 (*iter).second->setAliasee(SelPtr);
779 }
780 // Number of classes defined.
781 Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty,
782 Classes.size()));
783 // Number of categories defined
784 Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty,
785 Categories.size()));
786 // Create an array of classes, then categories, then static object instances
787 Classes.insert(Classes.end(), Categories.begin(), Categories.end());
788 // NULL-terminated list of static object instances (mainly constant strings)
789 Classes.push_back(Statics);
790 Classes.push_back(NULLPtr);
791 llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes);
792 Elements.push_back(ClassList);
793 // Construct the symbol table
794 llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements);
795
796 // The symbol table is contained in a module which has some version-checking
797 // constants
798 llvm::StructType * ModuleTy = llvm::StructType::get(LongTy, LongTy,
799 PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL);
800 Elements.clear();
801 // Runtime version used for compatibility checking.
802 Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
803 //FIXME: Should be sizeof(ModuleTy)
804 Elements.push_back(llvm::ConstantInt::get(LongTy, 16));
805 //FIXME: Should be the path to the file where this module was declared
806 Elements.push_back(NULLPtr);
807 Elements.push_back(SymTab);
808 llvm::Value *Module = MakeGlobal(ModuleTy, Elements);
809
810 // Create the load function calling the runtime entry point with the module
811 // structure
812 std::vector<const llvm::Type*> VoidArgs;
813 llvm::Function * LoadFunction = llvm::Function::Create(
814 llvm::FunctionType::get(llvm::Type::VoidTy, VoidArgs, false),
815 llvm::GlobalValue::InternalLinkage, ".objc_load_function",
816 &TheModule);
817 llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", LoadFunction);
Chris Lattner85e35682008-08-08 19:57:58 +0000818 llvm::IRBuilder<> Builder;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000819 Builder.SetInsertPoint(EntryBB);
820 llvm::Value *Register = TheModule.getOrInsertFunction("__objc_exec_class",
821 llvm::Type::VoidTy, llvm::PointerType::getUnqual(ModuleTy), NULL);
822 Builder.CreateCall(Register, Module);
823 Builder.CreateRetVoid();
824 return LoadFunction;
825}
Chris Lattner391d77a2008-03-30 23:03:07 +0000826llvm::Function *CGObjCGNU::MethodPreamble(
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000827 const std::string &ClassName,
828 const std::string &CategoryName,
829 const std::string &MethodName,
Chris Lattner391d77a2008-03-30 23:03:07 +0000830 const llvm::Type *ReturnTy,
831 const llvm::Type *SelfTy,
832 const llvm::Type **ArgTy,
833 unsigned ArgC,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000834 bool isClassMethod,
Chris Lattner391d77a2008-03-30 23:03:07 +0000835 bool isVarArg) {
836 std::vector<const llvm::Type*> Args;
Chris Lattner8fdf3282008-06-24 17:04:18 +0000837 if (!ReturnTy->isSingleValueType() && ReturnTy != llvm::Type::VoidTy) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000838 Args.push_back(llvm::PointerType::getUnqual(ReturnTy));
839 ReturnTy = llvm::Type::VoidTy;
840 }
Chris Lattner391d77a2008-03-30 23:03:07 +0000841 Args.push_back(SelfTy);
842 Args.push_back(SelectorTy);
843 Args.insert(Args.end(), ArgTy, ArgTy+ArgC);
844
845 llvm::FunctionType *MethodTy = llvm::FunctionType::get(ReturnTy,
846 Args,
847 isVarArg);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000848 std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
849 MethodName, isClassMethod);
850
Gabor Greif984d0b42008-04-06 20:42:52 +0000851 llvm::Function *Method = llvm::Function::Create(MethodTy,
Chris Lattner391d77a2008-03-30 23:03:07 +0000852 llvm::GlobalValue::InternalLinkage,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000853 FunctionName,
Chris Lattner391d77a2008-03-30 23:03:07 +0000854 &TheModule);
Chris Lattner391d77a2008-03-30 23:03:07 +0000855 llvm::Function::arg_iterator AI = Method->arg_begin();
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000856 // Name the struct return argument.
857 // FIXME: This is probably the wrong test.
858 if (!ReturnTy->isFirstClassType() && ReturnTy != llvm::Type::VoidTy) {
859 AI->setName("agg.result");
860 ++AI;
861 }
Chris Lattner391d77a2008-03-30 23:03:07 +0000862 AI->setName("self");
863 ++AI;
864 AI->setName("_cmd");
865 return Method;
866}
867
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000868CodeGen::CGObjCRuntime *CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM){
Chris Lattnerdce14062008-06-26 04:19:03 +0000869 return new CGObjCGNU(CGM);
Chris Lattner0f984262008-03-01 08:50:34 +0000870}