CGObjC.cpp revision 85c59edda02df48fae8dc85049743319bc6e7e89
1//===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===//
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 contains code to emit Objective-C code as LLVM code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
15#include "CodeGenFunction.h"
16#include "CodeGenModule.h"
17#include "clang/AST/ASTContext.h"
18#include "clang/AST/DeclObjC.h"
19
20using namespace clang;
21using namespace CodeGen;
22
23/// Emits an instance of NSConstantString representing the object.
24llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) {
25  std::string String(E->getString()->getStrData(), E->getString()->getByteLength());
26  llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(String);
27  // FIXME: This bitcast should just be made an invariant on the Runtime.
28  return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
29}
30
31/// Emit a selector.
32llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) {
33  // Untyped selector.
34  // Note that this implementation allows for non-constant strings to be passed
35  // as arguments to @selector().  Currently, the only thing preventing this
36  // behaviour is the type checking in the front end.
37  return CGM.getObjCRuntime().GetSelector(Builder, E->getSelector());
38}
39
40llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) {
41  // FIXME: This should pass the Decl not the name.
42  return CGM.getObjCRuntime().GenerateProtocolRef(Builder, E->getProtocol());
43}
44
45
46RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) {
47  // Only the lookup mechanism and first two arguments of the method
48  // implementation vary between runtimes.  We can get the receiver and
49  // arguments in generic code.
50
51  CGObjCRuntime &Runtime = CGM.getObjCRuntime();
52  const Expr *ReceiverExpr = E->getReceiver();
53  bool isSuperMessage = false;
54  bool isClassMessage = false;
55  // Find the receiver
56  llvm::Value *Receiver;
57  if (!ReceiverExpr) {
58    const ObjCInterfaceDecl *OID = E->getClassInfo().first;
59
60    // Very special case, super send in class method. The receiver is
61    // self (the class object) and the send uses super semantics.
62    if (!OID) {
63      assert(!strcmp(E->getClassName()->getName(), "super") &&
64             "Unexpected missing class interface in message send.");
65      isSuperMessage = true;
66      Receiver = LoadObjCSelf();
67    } else {
68      Receiver = Runtime.GetClass(Builder, OID);
69    }
70
71    isClassMessage = true;
72  } else if (const PredefinedExpr *PDE =
73               dyn_cast<PredefinedExpr>(E->getReceiver())) {
74    assert(PDE->getIdentType() == PredefinedExpr::ObjCSuper);
75    isSuperMessage = true;
76    Receiver = LoadObjCSelf();
77  } else {
78    Receiver = EmitScalarExpr(E->getReceiver());
79  }
80
81  if (isSuperMessage) {
82    // super is only valid in an Objective-C method
83    const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
84    return Runtime.GenerateMessageSendSuper(*this, E,
85                                            OMD->getClassInterface(),
86                                            Receiver,
87                                            isClassMessage);
88  }
89  return Runtime.GenerateMessageSend(*this, E, Receiver, isClassMessage);
90}
91
92/// StartObjCMethod - Begin emission of an ObjCMethod. This generates
93/// the LLVM function and sets the other context used by
94/// CodeGenFunction.
95
96// FIXME: This should really be merged with GenerateCode.
97void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD) {
98  CurFn = CGM.getObjCRuntime().GenerateMethod(OMD);
99  llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", CurFn);
100
101  // Create a marker to make it easy to insert allocas into the entryblock
102  // later.  Don't create this with the builder, because we don't want it
103  // folded.
104  llvm::Value *Undef = llvm::UndefValue::get(llvm::Type::Int32Ty);
105  AllocaInsertPt = new llvm::BitCastInst(Undef, llvm::Type::Int32Ty, "allocapt",
106                                         EntryBB);
107
108  FnRetTy = OMD->getResultType();
109  CurFuncDecl = OMD;
110
111  Builder.SetInsertPoint(EntryBB);
112
113  // Emit allocs for param decls.  Give the LLVM Argument nodes names.
114  llvm::Function::arg_iterator AI = CurFn->arg_begin();
115
116  // Name the struct return argument.
117  if (hasAggregateLLVMType(OMD->getResultType())) {
118    AI->setName("agg.result");
119    ++AI;
120  }
121
122  // Add implicit parameters to the decl map.
123  EmitParmDecl(*OMD->getSelfDecl(), AI);
124  ++AI;
125
126  EmitParmDecl(*OMD->getCmdDecl(), AI);
127  ++AI;
128
129  for (unsigned i = 0, e = OMD->getNumParams(); i != e; ++i, ++AI) {
130    assert(AI != CurFn->arg_end() && "Argument mismatch!");
131    EmitParmDecl(*OMD->getParamDecl(i), AI);
132  }
133  assert(AI == CurFn->arg_end() && "Argument mismatch");
134}
135
136/// Generate an Objective-C method.  An Objective-C method is a C function with
137/// its pointer, name, and types registered in the class struture.
138void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
139  StartObjCMethod(OMD);
140  EmitStmt(OMD->getBody());
141
142  const CompoundStmt *S = dyn_cast<CompoundStmt>(OMD->getBody());
143  if (S) {
144    FinishFunction(S->getRBracLoc());
145  } else {
146    FinishFunction();
147  }
148}
149
150// FIXME: I wasn't sure about the synthesis approach. If we end up
151// generating an AST for the whole body we can just fall back to
152// having a GenerateFunction which takes the body Stmt.
153
154/// GenerateObjCGetter - Generate an Objective-C property getter
155/// function. The given Decl must be either an ObjCCategoryImplDecl
156/// or an ObjCImplementationDecl.
157void CodeGenFunction::GenerateObjCGetter(const ObjCPropertyImplDecl *PID) {
158  const ObjCPropertyDecl *PD = PID->getPropertyDecl();
159  ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
160  assert(OMD && "Invalid call to generate getter (empty method)");
161  // FIXME: This is rather murky, we create this here since they will
162  // not have been created by Sema for us.
163  OMD->createImplicitParams(getContext());
164  StartObjCMethod(OMD);
165
166  // FIXME: What about nonatomic?
167  SourceLocation Loc = PD->getLocation();
168  ValueDecl *Self = OMD->getSelfDecl();
169  ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
170  DeclRefExpr Base(Self, Self->getType(), Loc);
171  ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base,
172                          true, true);
173  ReturnStmt Return(Loc, &IvarRef);
174  EmitStmt(&Return);
175
176  FinishFunction();
177}
178
179/// GenerateObjCSetter - Generate an Objective-C property setter
180/// function. The given Decl must be either an ObjCCategoryImplDecl
181/// or an ObjCImplementationDecl.
182void CodeGenFunction::GenerateObjCSetter(const ObjCPropertyImplDecl *PID) {
183  const ObjCPropertyDecl *PD = PID->getPropertyDecl();
184  ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
185  assert(OMD && "Invalid call to generate setter (empty method)");
186  // FIXME: This is rather murky, we create this here since they will
187  // not have been created by Sema for us.
188  OMD->createImplicitParams(getContext());
189  StartObjCMethod(OMD);
190
191  switch (PD->getSetterKind()) {
192  case ObjCPropertyDecl::Assign: break;
193  case ObjCPropertyDecl::Copy:
194      CGM.ErrorUnsupported(PID, "Obj-C setter with 'copy'");
195      break;
196  case ObjCPropertyDecl::Retain:
197      CGM.ErrorUnsupported(PID, "Obj-C setter with 'retain'");
198      break;
199  }
200
201  // FIXME: What about nonatomic?
202  SourceLocation Loc = PD->getLocation();
203  ValueDecl *Self = OMD->getSelfDecl();
204  ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
205  DeclRefExpr Base(Self, Self->getType(), Loc);
206  ParmVarDecl *ArgDecl = OMD->getParamDecl(0);
207  DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), Loc);
208  ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base,
209                          true, true);
210  BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign,
211                        Ivar->getType(), Loc);
212  EmitStmt(&Assign);
213
214  FinishFunction();
215}
216
217llvm::Value *CodeGenFunction::LoadObjCSelf(void) {
218  const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
219  return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self");
220}
221
222RValue CodeGenFunction::EmitObjCPropertyGet(const ObjCPropertyRefExpr *E) {
223  // Determine getter selector.
224  Selector S;
225  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(E->getDecl())) {
226    S = MD->getSelector();
227  } else {
228    S = cast<ObjCPropertyDecl>(E->getDecl())->getGetterName();
229  }
230
231  // FIXME: Improve location information.
232  SourceLocation Loc = E->getLocation();
233  // PropertyRefExprs are always instance messages.
234  // FIXME: Is there any reason to try and pass the method here?
235  ObjCMessageExpr GetExpr(const_cast<Expr*>(E->getBase()),
236                          S, E->getType(), 0, Loc, Loc,
237                          0, 0);
238
239  return EmitObjCMessageExpr(&GetExpr);
240}
241
242void CodeGenFunction::EmitObjCPropertySet(const ObjCPropertyRefExpr *E,
243                                          RValue Src) {
244  ErrorUnsupported(E, "Objective-C property setter call");
245}
246
247CGObjCRuntime::~CGObjCRuntime() {}
248