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