CGObjCMac.cpp revision 259d93d1e1f820d5ee7251e875fdb7c883102f16
1//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
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//
10// This provides Objective-C code generation targetting the Apple runtime.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
15
16#include "CodeGenModule.h"
17#include "clang/AST/ASTContext.h"
18#include "clang/AST/Decl.h"
19#include "clang/Basic/LangOptions.h"
20
21#include "llvm/Module.h"
22#include "llvm/Support/IRBuilder.h"
23
24using namespace clang;
25
26namespace {
27
28/// ObjCTypesHelper - Helper class that encapsulates lazy
29/// construction of varies types used during ObjC generation.
30class ObjCTypesHelper {
31private:
32  CodeGen::CodeGenModule &CGM;
33
34  const llvm::StructType *CFStringType;
35  llvm::Constant *CFConstantStringClassReference;
36  llvm::Function *MessageSendFn;
37
38public:
39  const llvm::Type *LongTy;
40
41  /// ObjectTy - Opaque type for Objective-C objects
42  const llvm::Type *ObjectTy, *ObjectPtrTy;
43  /// SelectorTy - Opaque type for Objective-C selectors
44  const llvm::Type *SelectorTy, *SelectorPtrTy;
45
46public:
47  ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
48  ~ObjCTypesHelper();
49
50  llvm::Constant *getCFConstantStringClassReference();
51  const llvm::StructType *getCFStringType();
52  llvm::Function *getMessageSendFn();
53};
54
55class CGObjCMac : public CodeGen::CGObjCRuntime {
56private:
57  CodeGen::CodeGenModule &CGM;
58  ObjCTypesHelper ObjCTypes;
59  /// ObjCABI - FIXME: Not sure yet.
60  unsigned ObjCABI;
61
62  /// MethodVarNames - uniqued method variable names.
63  llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
64
65  /// SelectorReferences - uniqued selector references.
66  llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
67
68  /// UsedGlobals - list of globals to pack into the llvm.used metadata
69  /// to prevent them from being clobbered.
70  std::vector<llvm::GlobalValue*> UsedGlobals;
71
72  /// EmitImageInfo - Emit the image info marker used to encode some module
73  /// level information.
74  void EmitImageInfo();
75
76  /// FinishModule - Write out global data structures at the end of
77  /// processing a translation unit.
78  void FinishModule();
79
80  /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
81  /// for the given selector.
82  llvm::Value *EmitSelector(llvm::IRBuilder<> &Builder, Selector Sel);
83
84  /// GetMethodVarName - Return a unique constant for the given
85  /// selector's name.
86  llvm::Constant *GetMethodVarName(Selector Sel);
87
88public:
89  CGObjCMac(CodeGen::CodeGenModule &cgm);
90  virtual llvm::Constant *GenerateConstantString(const std::string &String);
91
92  virtual llvm::Value *GenerateMessageSend(llvm::IRBuilder<> &Builder,
93                                           const llvm::Type *ReturnTy,
94                                           llvm::Value *Sender,
95                                           llvm::Value *Receiver,
96                                           Selector Sel,
97                                           llvm::Value** ArgV,
98                                           unsigned ArgC);
99
100  virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
101                                                const llvm::Type *ReturnTy,
102                                                llvm::Value *Sender,
103                                                const char *SuperClassName,
104                                                llvm::Value *Receiver,
105                                                Selector Sel,
106                                                llvm::Value** ArgV,
107                                                unsigned ArgC);
108
109  virtual llvm::Value *LookupClass(llvm::IRBuilder<> &Builder,
110                                   llvm::Value *ClassName);
111
112  virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel);
113
114  virtual llvm::Function *MethodPreamble(const std::string &ClassName,
115                                         const std::string &CategoryName,
116                                         const std::string &MethodName,
117                                         const llvm::Type *ReturnTy,
118                                         const llvm::Type *SelfTy,
119                                         const llvm::Type **ArgTy,
120                                         unsigned ArgC,
121                                         bool isClassMethod,
122                                         bool isVarArg);
123
124  virtual void GenerateCategory(const char *ClassName, const char *CategoryName,
125           const llvm::SmallVectorImpl<Selector>  &InstanceMethodSels,
126           const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes,
127           const llvm::SmallVectorImpl<Selector>  &ClassMethodSels,
128           const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes,
129           const llvm::SmallVectorImpl<std::string> &Protocols);
130
131  virtual void GenerateClass(
132           const char *ClassName,
133           const char *SuperClassName,
134           const int instanceSize,
135           const llvm::SmallVectorImpl<llvm::Constant *>  &IvarNames,
136           const llvm::SmallVectorImpl<llvm::Constant *>  &IvarTypes,
137           const llvm::SmallVectorImpl<llvm::Constant *>  &IvarOffsets,
138           const llvm::SmallVectorImpl<Selector>  &InstanceMethodSels,
139           const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes,
140           const llvm::SmallVectorImpl<Selector>  &ClassMethodSels,
141           const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes,
142           const llvm::SmallVectorImpl<std::string> &Protocols);
143
144  virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder<> &Builder,
145                                           const char *ProtocolName);
146
147  virtual void GenerateProtocol(const char *ProtocolName,
148      const llvm::SmallVectorImpl<std::string> &Protocols,
149      const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodNames,
150      const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes,
151      const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodNames,
152      const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes);
153
154  virtual llvm::Function *ModuleInitFunction();
155};
156} // end anonymous namespace
157
158/* *** Helper Functions *** */
159
160/// getConstantGEP() - Help routine to construct simple GEPs.
161static llvm::Constant *getConstantGEP(llvm::Constant *C,
162                                      unsigned idx0,
163                                      unsigned idx1) {
164  llvm::Value *Idxs[] = {
165    llvm::ConstantInt::get(llvm::Type::Int32Ty, idx0),
166    llvm::ConstantInt::get(llvm::Type::Int32Ty, idx1)
167  };
168  return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
169}
170
171/* *** CGObjCMac Public Interface *** */
172
173CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm)
174  : CGM(cgm),
175    ObjCTypes(cgm),
176    ObjCABI(1)
177{
178  // FIXME: How does this get set in GCC? And what does it even mean?
179  if (ObjCTypes.LongTy != CGM.getTypes().ConvertType(CGM.getContext().IntTy))
180      ObjCABI = 2;
181
182  EmitImageInfo();
183}
184
185// This has to perform the lookup every time, since posing and related
186// techniques can modify the name -> class mapping.
187llvm::Value *CGObjCMac::LookupClass(llvm::IRBuilder<> &Builder,
188                                    llvm::Value *ClassName) {
189  assert(0 && "Cannot lookup classes on Mac runtime.");
190  return 0;
191}
192
193/// GetSelector - Return the pointer to the unique'd string for this selector.
194llvm::Value *CGObjCMac::GetSelector(llvm::IRBuilder<> &Builder, Selector Sel) {
195  return EmitSelector(Builder, Sel);
196}
197
198/// Generate a constant CFString object.
199/*
200   struct __builtin_CFString {
201     const int *isa; // point to __CFConstantStringClassReference
202     int flags;
203     const char *str;
204     long length;
205   };
206*/
207
208llvm::Constant *CGObjCMac::GenerateConstantString(const std::string &String) {
209  // FIXME: I have no idea what this constant is (it is a magic
210  // constant in GCC as well). Most likely the encoding of the string
211  // and at least one part of it relates to UTF-16. Is this just the
212  // code for UTF-8? Where is this handled for us?
213  //  See: <rdr://2996215>
214  unsigned flags = 0x07c8;
215
216  // FIXME: Use some machinery to unique this. We can't reuse the CGM
217  // one since we put them in a different section.
218  llvm::Constant *StringC = llvm::ConstantArray::get(String);
219  llvm::Constant *StringGV =
220    new llvm::GlobalVariable(StringC->getType(), true,
221                             llvm::GlobalValue::InternalLinkage,
222                             StringC, ".str", &CGM.getModule());
223  llvm::Constant *Values[4] = {
224    ObjCTypes.getCFConstantStringClassReference(),
225    llvm::ConstantInt::get(llvm::Type::Int32Ty, flags),
226    getConstantGEP(StringGV, 0, 0), // Decay array -> ptr
227    llvm::ConstantInt::get(ObjCTypes.LongTy, String.size())
228  };
229
230  llvm::Constant *CFStringC =
231    llvm::ConstantStruct::get(ObjCTypes.getCFStringType(),
232                              std::vector<llvm::Constant*>(Values, Values+4));
233
234  llvm::GlobalVariable *CFStringGV =
235    new llvm::GlobalVariable(CFStringC->getType(), true,
236                             llvm::GlobalValue::InternalLinkage,
237                             CFStringC, "",
238                             &CGM.getModule());
239
240  CFStringGV->setSection("__DATA, __cfstring");
241
242  return CFStringGV;
243}
244
245/// Generates a message send where the super is the receiver.  This is
246/// a message send to self with special delivery semantics indicating
247/// which class's method should be called.
248llvm::Value *CGObjCMac::GenerateMessageSendSuper(llvm::IRBuilder<> &Builder,
249                                                 const llvm::Type *ReturnTy,
250                                                 llvm::Value *Sender,
251                                                 const char *SuperClassName,
252                                                 llvm::Value *Receiver,
253                                                 Selector Sel,
254                                                 llvm::Value** ArgV,
255                                                 unsigned ArgC) {
256  assert(0 && "Cannot generate message send to super for Mac runtime.");
257  return 0;
258}
259
260/// Generate code for a message send expression.
261llvm::Value *CGObjCMac::GenerateMessageSend(llvm::IRBuilder<> &Builder,
262                                            const llvm::Type *ReturnTy,
263                                            llvm::Value *Sender,
264                                            llvm::Value *Receiver,
265                                            Selector Sel,
266                                            llvm::Value** ArgV,
267                                            unsigned ArgC) {
268  if (!Sender) {
269    llvm::Function *F = ObjCTypes.getMessageSendFn();
270    llvm::Value **Args = new llvm::Value*[ArgC+2];
271    Args[0] = Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
272    Args[1] = EmitSelector(Builder, Sel);
273    std::copy(ArgV, ArgV+ArgC, Args+2);
274    llvm::CallInst *CI = Builder.CreateCall(F, Args, Args+ArgC+2, "tmp");
275    delete[] Args;
276    return Builder.CreateBitCast(CI, ReturnTy, "tmp");
277  } else {
278    assert(0 && "cannot generate message sends with sender");
279    return 0;
280  }
281}
282
283llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder,
284                                            const char *ProtocolName) {
285  assert(0 && "Cannot get protocol reference on Mac runtime.");
286  return 0;
287}
288
289void CGObjCMac::GenerateProtocol(const char *ProtocolName,
290    const llvm::SmallVectorImpl<std::string> &Protocols,
291    const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodNames,
292    const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes,
293    const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodNames,
294    const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes) {
295  assert(0 && "Cannot generate protocol for Mac runtime.");
296}
297
298void CGObjCMac::GenerateCategory(
299           const char *ClassName,
300           const char *CategoryName,
301           const llvm::SmallVectorImpl<Selector>  &InstanceMethodSels,
302           const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes,
303           const llvm::SmallVectorImpl<Selector>  &ClassMethodSels,
304           const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes,
305           const llvm::SmallVectorImpl<std::string> &Protocols) {
306  assert(0 && "Cannot generate category for Mac runtime.");
307}
308
309void CGObjCMac::GenerateClass(
310           const char *ClassName,
311           const char *SuperClassName,
312           const int instanceSize,
313           const llvm::SmallVectorImpl<llvm::Constant *>  &IvarNames,
314           const llvm::SmallVectorImpl<llvm::Constant *>  &IvarTypes,
315           const llvm::SmallVectorImpl<llvm::Constant *>  &IvarOffsets,
316           const llvm::SmallVectorImpl<Selector>  &InstanceMethodSels,
317           const llvm::SmallVectorImpl<llvm::Constant *>  &InstanceMethodTypes,
318           const llvm::SmallVectorImpl<Selector>  &ClassMethodSels,
319           const llvm::SmallVectorImpl<llvm::Constant *>  &ClassMethodTypes,
320           const llvm::SmallVectorImpl<std::string> &Protocols) {
321  assert(0 && "Cannot generate class for Mac runtime.");
322}
323
324llvm::Function *CGObjCMac::ModuleInitFunction() {
325  // Abuse this interface function as a place to finalize.
326  FinishModule();
327
328  return NULL;
329}
330
331llvm::Function *CGObjCMac::MethodPreamble(const std::string &ClassName,
332                                          const std::string &CategoryName,
333                                          const std::string &MethodName,
334                                          const llvm::Type *ReturnTy,
335                                          const llvm::Type *SelfTy,
336                                          const llvm::Type **ArgTy,
337                                          unsigned ArgC,
338                                          bool isClassMethod,
339                                          bool isVarArg) {
340  assert(0 && "Cannot generate method preamble for Mac runtime.");
341  return 0;
342}
343
344/* *** Private Interface *** */
345
346/// EmitImageInfo - Emit the image info marker used to encode some module
347/// level information.
348///
349/// See: <rdr://4810609&4810587&4810587>
350/// struct IMAGE_INFO {
351///   unsigned version;
352///   unsigned flags;
353/// };
354enum ImageInfoFlags {
355  eImageInfo_FixAndContinue   = (1 << 0), // FIXME: Not sure what this implies
356  eImageInfo_GarbageCollected = (1 << 1),
357  eImageInfo_GCOnly           = (1 << 2)
358};
359
360void CGObjCMac::EmitImageInfo() {
361  unsigned version = 0; // Version is unused?
362  unsigned flags = 0;
363
364  // FIXME: Fix and continue?
365  if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
366    flags |= eImageInfo_GarbageCollected;
367  if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
368    flags |= eImageInfo_GCOnly;
369
370  // Emitted as int[2];
371  llvm::Constant *values[2] = {
372    llvm::ConstantInt::get(llvm::Type::Int32Ty, version),
373    llvm::ConstantInt::get(llvm::Type::Int32Ty, flags)
374  };
375  llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::Int32Ty, 2);
376  llvm::GlobalValue *GV =
377    new llvm::GlobalVariable(AT, true,
378                             llvm::GlobalValue::InternalLinkage,
379                             llvm::ConstantArray::get(AT, values, 2),
380                             "\01L_OBJC_IMAGE_INFO",
381                             &CGM.getModule());
382
383  if (ObjCABI == 1) {
384    GV->setSection("__OBJC, __image_info,regular");
385  } else {
386    GV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip");
387  }
388
389  UsedGlobals.push_back(GV);
390}
391
392llvm::Value *CGObjCMac::EmitSelector(llvm::IRBuilder<> &Builder, Selector Sel) {
393  llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
394
395  if (!Entry) {
396    llvm::Constant *Casted =
397      llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
398                                     ObjCTypes.SelectorPtrTy);
399    Entry =
400      new llvm::GlobalVariable(ObjCTypes.SelectorPtrTy, false,
401                               llvm::GlobalValue::InternalLinkage,
402                               Casted, "\01L_OBJC_SELECTOR_REFERENCES_",
403                               &CGM.getModule());
404    Entry->setSection("__OBJC,__message_refs,literal_pointers,no_dead_strip");
405    UsedGlobals.push_back(Entry);
406  }
407
408  return Builder.CreateLoad(Entry, false, "tmp");
409}
410
411llvm::Constant *CGObjCMac::GetMethodVarName(Selector Sel) {
412  llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
413
414  if (!Entry) {
415    llvm::Constant *C = llvm::ConstantArray::get(Sel.getName());
416    Entry =
417      new llvm::GlobalVariable(C->getType(), true,
418                               llvm::GlobalValue::InternalLinkage,
419                               C, "\01L_OBJC_METH_VAR_NAME_",
420                               &CGM.getModule());
421    Entry->setSection("__TEXT,__cstring,cstring_literals");
422    UsedGlobals.push_back(Entry);
423  }
424
425  return Entry;
426}
427
428void CGObjCMac::FinishModule() {
429  std::vector<llvm::Constant*> Used;
430
431  llvm::Type *I8Ptr = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
432  for (std::vector<llvm::GlobalValue*>::iterator i = UsedGlobals.begin(),
433         e = UsedGlobals.end(); i != e; ++i) {
434    Used.push_back(llvm::ConstantExpr::getBitCast(*i, I8Ptr));
435  }
436
437  llvm::ArrayType *AT = llvm::ArrayType::get(I8Ptr, Used.size());
438  llvm::GlobalValue *GV =
439    new llvm::GlobalVariable(AT, false,
440                             llvm::GlobalValue::AppendingLinkage,
441                             llvm::ConstantArray::get(AT, Used),
442                             "llvm.used",
443                             &CGM.getModule());
444
445  GV->setSection("llvm.metadata");
446}
447
448/* *** */
449
450ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
451  : CGM(cgm),
452    CFStringType(0),
453    CFConstantStringClassReference(0),
454    MessageSendFn(0),
455    LongTy(CGM.getTypes().ConvertType(CGM.getContext().LongTy)),
456    // FIXME: We want the types from the front-end.
457    ObjectTy(llvm::OpaqueType::get()),
458    ObjectPtrTy(llvm::PointerType::getUnqual(ObjectTy)),
459    SelectorTy(llvm::OpaqueType::get()),
460    SelectorPtrTy(llvm::PointerType::getUnqual(SelectorTy))
461{
462  CGM.getModule().addTypeName("struct.__objc_object", ObjectTy);
463  CGM.getModule().addTypeName("struct.__objc_selector", SelectorTy);
464}
465
466ObjCTypesHelper::~ObjCTypesHelper() {
467}
468
469const llvm::StructType *ObjCTypesHelper::getCFStringType() {
470  if (!CFStringType) {
471    CFStringType =
472      llvm::StructType::get(llvm::PointerType::getUnqual(llvm::Type::Int32Ty),
473                            llvm::Type::Int32Ty,
474                            llvm::PointerType::getUnqual(llvm::Type::Int8Ty),
475                            LongTy,
476                            NULL);
477
478    CGM.getModule().addTypeName("struct.__builtin_CFString", CFStringType);
479  }
480
481  return CFStringType;
482}
483
484llvm::Constant *ObjCTypesHelper::getCFConstantStringClassReference() {
485  if (!CFConstantStringClassReference) {
486    llvm::GlobalValue *GV =
487      new llvm::GlobalVariable(llvm::ArrayType::get(llvm::Type::Int32Ty, 0),
488                               false,
489                               llvm::GlobalValue::ExternalLinkage,
490                               0, "__CFConstantStringClassReference",
491                                                     &CGM.getModule());
492
493    // Decay to pointer.
494    CFConstantStringClassReference = getConstantGEP(GV, 0, 0);
495  }
496
497  return CFConstantStringClassReference;
498}
499
500llvm::Function *ObjCTypesHelper::getMessageSendFn() {
501  if (!MessageSendFn) {
502    std::vector<const llvm::Type*> Params;
503    Params.push_back(ObjectPtrTy);
504    Params.push_back(SelectorPtrTy);
505    MessageSendFn = llvm::Function::Create(llvm::FunctionType::get(ObjectPtrTy,
506                                                                   Params,
507                                                                   true),
508                                           llvm::Function::ExternalLinkage,
509                                           "objc_msgSend",
510                                           &CGM.getModule());
511  }
512
513  return MessageSendFn;
514}
515
516/* *** */
517
518CodeGen::CGObjCRuntime *CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM){
519  return new CGObjCMac(CGM);
520}
521