CGObjC.cpp revision 207619
133965Sjdp//===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===// 278828Sobrien// 360484Sobrien// The LLVM Compiler Infrastructure 433965Sjdp// 533965Sjdp// This file is distributed under the University of Illinois Open Source 633965Sjdp// License. See LICENSE.TXT for details. 733965Sjdp// 833965Sjdp//===----------------------------------------------------------------------===// 933965Sjdp// 1033965Sjdp// This contains code to emit Objective-C code as LLVM code. 1133965Sjdp// 1233965Sjdp//===----------------------------------------------------------------------===// 1333965Sjdp 1433965Sjdp#include "CGObjCRuntime.h" 1533965Sjdp#include "CodeGenFunction.h" 1633965Sjdp#include "CodeGenModule.h" 1733965Sjdp#include "clang/AST/ASTContext.h" 1877298Sobrien#include "clang/AST/DeclObjC.h" 1977298Sobrien#include "clang/AST/StmtObjC.h" 2077298Sobrien#include "clang/Basic/Diagnostic.h" 2133965Sjdp#include "llvm/ADT/STLExtras.h" 2233965Sjdp#include "llvm/Target/TargetData.h" 2333965Sjdpusing namespace clang; 2433965Sjdpusing namespace CodeGen; 2533965Sjdp 2633965Sjdp/// Emits an instance of NSConstantString representing the object. 2733965Sjdpllvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) 2833965Sjdp{ 2933965Sjdp llvm::Constant *C = 3077298Sobrien CGM.getObjCRuntime().GenerateConstantString(E->getString()); 3133965Sjdp // FIXME: This bitcast should just be made an invariant on the Runtime. 3233965Sjdp return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType())); 3333965Sjdp} 3433965Sjdp 3533965Sjdp/// Emit a selector. 3633965Sjdpllvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) { 3777298Sobrien // Untyped selector. 3833965Sjdp // Note that this implementation allows for non-constant strings to be passed 3933965Sjdp // as arguments to @selector(). Currently, the only thing preventing this 4077298Sobrien // behaviour is the type checking in the front end. 4133965Sjdp return CGM.getObjCRuntime().GetSelector(Builder, E->getSelector()); 4233965Sjdp} 4377298Sobrien 4477298Sobrienllvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) { 4533965Sjdp // FIXME: This should pass the Decl not the name. 4633965Sjdp return CGM.getObjCRuntime().GenerateProtocolRef(Builder, E->getProtocol()); 4777298Sobrien} 4833965Sjdp 4933965Sjdp 5033965SjdpRValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { 5177298Sobrien // Only the lookup mechanism and first two arguments of the method 5233965Sjdp // implementation vary between runtimes. We can get the receiver and 5377298Sobrien // arguments in generic code. 5433965Sjdp 5533965Sjdp CGObjCRuntime &Runtime = CGM.getObjCRuntime(); 5633965Sjdp bool isSuperMessage = false; 5777298Sobrien bool isClassMessage = false; 5833965Sjdp ObjCInterfaceDecl *OID = 0; 5977298Sobrien // Find the receiver 6033965Sjdp llvm::Value *Receiver = 0; 6133965Sjdp switch (E->getReceiverKind()) { 6233965Sjdp case ObjCMessageExpr::Instance: 6333965Sjdp Receiver = EmitScalarExpr(E->getInstanceReceiver()); 6433965Sjdp break; 6533965Sjdp 6633965Sjdp case ObjCMessageExpr::Class: { 6733965Sjdp const ObjCInterfaceType *IFace 6877298Sobrien = E->getClassReceiver()->getAs<ObjCInterfaceType>(); 6977298Sobrien OID = IFace->getDecl(); 7033965Sjdp assert(IFace && "Invalid Objective-C class message send"); 7177298Sobrien Receiver = Runtime.GetClass(Builder, OID); 7233965Sjdp isClassMessage = true; 7333965Sjdp break; 7477298Sobrien } 7577298Sobrien 7633965Sjdp case ObjCMessageExpr::SuperInstance: 7733965Sjdp Receiver = LoadObjCSelf(); 7877298Sobrien isSuperMessage = true; 7933965Sjdp break; 8033965Sjdp 8133965Sjdp case ObjCMessageExpr::SuperClass: 8277298Sobrien Receiver = LoadObjCSelf(); 8333965Sjdp isSuperMessage = true; 8477298Sobrien isClassMessage = true; 8533965Sjdp break; 8633965Sjdp } 8733965Sjdp 8877298Sobrien CallArgList Args; 8933965Sjdp EmitCallArgs(Args, E->getMethodDecl(), E->arg_begin(), E->arg_end()); 9033965Sjdp 9177298Sobrien if (isSuperMessage) { 9233965Sjdp // super is only valid in an Objective-C method 9333965Sjdp const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 9433965Sjdp bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); 9577298Sobrien return Runtime.GenerateMessageSendSuper(*this, E->getType(), 9633965Sjdp E->getSelector(), 9733965Sjdp OMD->getClassInterface(), 9877298Sobrien isCategoryImpl, 9933965Sjdp Receiver, 10033965Sjdp isClassMessage, 10133965Sjdp Args, 10277298Sobrien E->getMethodDecl()); 10333965Sjdp } 10433965Sjdp 10577298Sobrien return Runtime.GenerateMessageSend(*this, E->getType(), E->getSelector(), 10633965Sjdp Receiver, Args, OID, 10733965Sjdp E->getMethodDecl()); 10833965Sjdp} 10977298Sobrien 11033965Sjdp/// StartObjCMethod - Begin emission of an ObjCMethod. This generates 11133965Sjdp/// the LLVM function and sets the other context used by 11277298Sobrien/// CodeGenFunction. 11333965Sjdpvoid CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, 11433965Sjdp const ObjCContainerDecl *CD) { 11533965Sjdp FunctionArgList Args; 11633965Sjdp // Check if we should generate debug info for this method. 11733965Sjdp if (CGM.getDebugInfo() && !OMD->hasAttr<NoDebugAttr>()) 11833965Sjdp DebugInfo = CGM.getDebugInfo(); 11933965Sjdp 12033965Sjdp llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD); 12133965Sjdp 12233965Sjdp const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD); 12333965Sjdp CGM.SetInternalFunctionAttributes(OMD, Fn, FI); 12433965Sjdp 12533965Sjdp Args.push_back(std::make_pair(OMD->getSelfDecl(), 12633965Sjdp OMD->getSelfDecl()->getType())); 12733965Sjdp Args.push_back(std::make_pair(OMD->getCmdDecl(), 12833965Sjdp OMD->getCmdDecl()->getType())); 12933965Sjdp 13033965Sjdp for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 13133965Sjdp E = OMD->param_end(); PI != E; ++PI) 13233965Sjdp Args.push_back(std::make_pair(*PI, (*PI)->getType())); 13333965Sjdp 13433965Sjdp StartFunction(OMD, OMD->getResultType(), Fn, Args, OMD->getLocStart()); 13533965Sjdp} 13633965Sjdp 13733965Sjdp/// Generate an Objective-C method. An Objective-C method is a C function with 13833965Sjdp/// its pointer, name, and types registered in the class struture. 13933965Sjdpvoid CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { 14033965Sjdp StartObjCMethod(OMD, OMD->getClassInterface()); 14177298Sobrien EmitStmt(OMD->getBody()); 14233965Sjdp FinishFunction(OMD->getBodyRBrace()); 14333965Sjdp} 14433965Sjdp 14533965Sjdp// FIXME: I wasn't sure about the synthesis approach. If we end up generating an 14633965Sjdp// AST for the whole body we can just fall back to having a GenerateFunction 14733965Sjdp// which takes the body Stmt. 14833965Sjdp 14933965Sjdp/// GenerateObjCGetter - Generate an Objective-C property getter 15033965Sjdp/// function. The given Decl must be an ObjCImplementationDecl. @synthesize 15133965Sjdp/// is illegal within a category. 15233965Sjdpvoid CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, 15333965Sjdp const ObjCPropertyImplDecl *PID) { 15433965Sjdp ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); 15533965Sjdp const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 15633965Sjdp bool IsAtomic = 15733965Sjdp !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); 15833965Sjdp ObjCMethodDecl *OMD = PD->getGetterMethodDecl(); 15933965Sjdp assert(OMD && "Invalid call to generate getter (empty method)"); 16060484Sobrien // FIXME: This is rather murky, we create this here since they will not have 16160484Sobrien // been created by Sema for us. 16260484Sobrien OMD->createImplicitParams(getContext(), IMP->getClassInterface()); 16360484Sobrien StartObjCMethod(OMD, IMP->getClassInterface()); 16460484Sobrien 16560484Sobrien // Determine if we should use an objc_getProperty call for 16660484Sobrien // this. Non-atomic properties are directly evaluated. 16760484Sobrien // atomic 'copy' and 'retain' properties are also directly 16860484Sobrien // evaluated in gc-only mode. 16960484Sobrien if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && 17060484Sobrien IsAtomic && 17133965Sjdp (PD->getSetterKind() == ObjCPropertyDecl::Copy || 17289857Sobrien PD->getSetterKind() == ObjCPropertyDecl::Retain)) { 17389857Sobrien llvm::Value *GetPropertyFn = 17489857Sobrien CGM.getObjCRuntime().GetPropertyGetFunction(); 17533965Sjdp 17689857Sobrien if (!GetPropertyFn) { 17733965Sjdp CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); 17833965Sjdp FinishFunction(); 17989857Sobrien return; 18033965Sjdp } 18133965Sjdp 18233965Sjdp // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true). 18389857Sobrien // FIXME: Can't this be simpler? This might even be worse than the 18489857Sobrien // corresponding gcc code. 18589857Sobrien CodeGenTypes &Types = CGM.getTypes(); 18633965Sjdp ValueDecl *Cmd = OMD->getCmdDecl(); 18733965Sjdp llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); 18877298Sobrien QualType IdTy = getContext().getObjCIdType(); 18933965Sjdp llvm::Value *SelfAsId = 19033965Sjdp Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); 19133965Sjdp llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); 19233965Sjdp llvm::Value *True = 19377298Sobrien llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); 19477298Sobrien CallArgList Args; 19533965Sjdp Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy)); 19633965Sjdp Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); 19733965Sjdp Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); 19833965Sjdp Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy)); 19933965Sjdp // FIXME: We shouldn't need to get the function info here, the 20033965Sjdp // runtime already should have computed it to build the function. 20133965Sjdp RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args, 20233965Sjdp FunctionType::ExtInfo()), 20333965Sjdp GetPropertyFn, ReturnValueSlot(), Args); 20477298Sobrien // We need to fix the type here. Ivars with copy & retain are 20533965Sjdp // always objects so we don't need to worry about complex or 20633965Sjdp // aggregates. 20733965Sjdp RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), 20833965Sjdp Types.ConvertType(PD->getType()))); 20977298Sobrien EmitReturnOfRValue(RV, PD->getType()); 21033965Sjdp } else { 21133965Sjdp LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); 21233965Sjdp if (Ivar->getType()->isAnyComplexType()) { 21333965Sjdp ComplexPairTy Pair = LoadComplexFromAddr(LV.getAddress(), 21477298Sobrien LV.isVolatileQualified()); 21533965Sjdp StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified()); 21677298Sobrien } 21777298Sobrien else if (hasAggregateLLVMType(Ivar->getType())) { 21877298Sobrien bool IsStrong = false; 21933965Sjdp if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(Ivar->getType()))) 22033965Sjdp && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect 22133965Sjdp && CGM.getObjCRuntime().GetCopyStructFunction()) { 22277298Sobrien llvm::Value *GetCopyStructFn = 22377298Sobrien CGM.getObjCRuntime().GetCopyStructFunction(); 22433965Sjdp CodeGenTypes &Types = CGM.getTypes(); 22560484Sobrien // objc_copyStruct (ReturnValue, &structIvar, 22633965Sjdp // sizeof (Type of Ivar), isAtomic, false); 22733965Sjdp CallArgList Args; 22833965Sjdp RValue RV = RValue::get(Builder.CreateBitCast(ReturnValue, 22977298Sobrien Types.ConvertType(getContext().VoidPtrTy))); 23077298Sobrien Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); 23133965Sjdp RV = RValue::get(Builder.CreateBitCast(LV.getAddress(), 23260484Sobrien Types.ConvertType(getContext().VoidPtrTy))); 23333965Sjdp Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); 23433965Sjdp // sizeof (Type of Ivar) 23533965Sjdp uint64_t Size = getContext().getTypeSize(Ivar->getType()) / 8; 23633965Sjdp llvm::Value *SizeVal = 23733965Sjdp llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size); 23877298Sobrien Args.push_back(std::make_pair(RValue::get(SizeVal), 23933965Sjdp getContext().LongTy)); 24033965Sjdp llvm::Value *isAtomic = 24177298Sobrien llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 24277298Sobrien IsAtomic ? 1 : 0); 24377298Sobrien Args.push_back(std::make_pair(RValue::get(isAtomic), 24477298Sobrien getContext().BoolTy)); 24577298Sobrien llvm::Value *hasStrong = 24677298Sobrien llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 24777298Sobrien IsStrong ? 1 : 0); 24877298Sobrien Args.push_back(std::make_pair(RValue::get(hasStrong), 24977298Sobrien getContext().BoolTy)); 25077298Sobrien EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, 25177298Sobrien FunctionType::ExtInfo()), 25277298Sobrien GetCopyStructFn, ReturnValueSlot(), Args); 25377298Sobrien } 25477298Sobrien else 25577298Sobrien EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType()); 25677298Sobrien } else { 25733965Sjdp CodeGenTypes &Types = CGM.getTypes(); 25833965Sjdp RValue RV = EmitLoadOfLValue(LV, Ivar->getType()); 25933965Sjdp RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), 26033965Sjdp Types.ConvertType(PD->getType()))); 26133965Sjdp EmitReturnOfRValue(RV, PD->getType()); 26233965Sjdp } 26333965Sjdp } 26433965Sjdp 26533965Sjdp FinishFunction(); 26633965Sjdp} 26733965Sjdp 26833965Sjdp/// GenerateObjCSetter - Generate an Objective-C property setter 26933965Sjdp/// function. The given Decl must be an ObjCImplementationDecl. @synthesize 27033965Sjdp/// is illegal within a category. 27133965Sjdpvoid CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, 27233965Sjdp const ObjCPropertyImplDecl *PID) { 27333965Sjdp ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); 27433965Sjdp const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 27560484Sobrien ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); 27660484Sobrien assert(OMD && "Invalid call to generate setter (empty method)"); 27760484Sobrien // FIXME: This is rather murky, we create this here since they will not have 27877298Sobrien // been created by Sema for us. 27960484Sobrien OMD->createImplicitParams(getContext(), IMP->getClassInterface()); 28077298Sobrien StartObjCMethod(OMD, IMP->getClassInterface()); 28160484Sobrien 28277298Sobrien bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy; 28377298Sobrien bool IsAtomic = 28460484Sobrien !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); 28577298Sobrien 28677298Sobrien // Determine if we should use an objc_setProperty call for 28760484Sobrien // this. Properties with 'copy' semantics always use it, as do 28860484Sobrien // non-atomic properties with 'release' semantics as long as we are 28960484Sobrien // not in gc-only mode. 29077298Sobrien if (IsCopy || 29160484Sobrien (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && 29260484Sobrien PD->getSetterKind() == ObjCPropertyDecl::Retain)) { 29360484Sobrien llvm::Value *SetPropertyFn = 29460484Sobrien CGM.getObjCRuntime().GetPropertySetFunction(); 29560484Sobrien 29677298Sobrien if (!SetPropertyFn) { 29760484Sobrien CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); 29860484Sobrien FinishFunction(); 29960484Sobrien return; 30060484Sobrien } 30160484Sobrien 30260484Sobrien // Emit objc_setProperty((id) self, _cmd, offset, arg, 30377298Sobrien // <is-atomic>, <is-copy>). 30477298Sobrien // FIXME: Can't this be simpler? This might even be worse than the 30560484Sobrien // corresponding gcc code. 30660484Sobrien CodeGenTypes &Types = CGM.getTypes(); 30760484Sobrien ValueDecl *Cmd = OMD->getCmdDecl(); 30860484Sobrien llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); 30960484Sobrien QualType IdTy = getContext().getObjCIdType(); 31060484Sobrien llvm::Value *SelfAsId = 311 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); 312 llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); 313 llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; 314 llvm::Value *ArgAsId = 315 Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"), 316 Types.ConvertType(IdTy)); 317 llvm::Value *True = 318 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); 319 llvm::Value *False = 320 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); 321 CallArgList Args; 322 Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy)); 323 Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); 324 Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); 325 Args.push_back(std::make_pair(RValue::get(ArgAsId), IdTy)); 326 Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False), 327 getContext().BoolTy)); 328 Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False), 329 getContext().BoolTy)); 330 // FIXME: We shouldn't need to get the function info here, the runtime 331 // already should have computed it to build the function. 332 EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, 333 FunctionType::ExtInfo()), 334 SetPropertyFn, 335 ReturnValueSlot(), Args); 336 } else if (IsAtomic && hasAggregateLLVMType(Ivar->getType()) && 337 !Ivar->getType()->isAnyComplexType() && 338 IndirectObjCSetterArg(*CurFnInfo) 339 && CGM.getObjCRuntime().GetCopyStructFunction()) { 340 // objc_copyStruct (&structIvar, &Arg, 341 // sizeof (struct something), true, false); 342 llvm::Value *GetCopyStructFn = 343 CGM.getObjCRuntime().GetCopyStructFunction(); 344 CodeGenTypes &Types = CGM.getTypes(); 345 CallArgList Args; 346 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); 347 RValue RV = RValue::get(Builder.CreateBitCast(LV.getAddress(), 348 Types.ConvertType(getContext().VoidPtrTy))); 349 Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); 350 llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; 351 llvm::Value *ArgAsPtrTy = 352 Builder.CreateBitCast(Arg, 353 Types.ConvertType(getContext().VoidPtrTy)); 354 RV = RValue::get(ArgAsPtrTy); 355 Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); 356 // sizeof (Type of Ivar) 357 uint64_t Size = getContext().getTypeSize(Ivar->getType()) / 8; 358 llvm::Value *SizeVal = 359 llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size); 360 Args.push_back(std::make_pair(RValue::get(SizeVal), 361 getContext().LongTy)); 362 llvm::Value *True = 363 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); 364 Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy)); 365 llvm::Value *False = 366 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); 367 Args.push_back(std::make_pair(RValue::get(False), getContext().BoolTy)); 368 EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, 369 FunctionType::ExtInfo()), 370 GetCopyStructFn, ReturnValueSlot(), Args); 371 } else { 372 // FIXME: Find a clean way to avoid AST node creation. 373 SourceLocation Loc = PD->getLocation(); 374 ValueDecl *Self = OMD->getSelfDecl(); 375 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); 376 DeclRefExpr Base(Self, Self->getType(), Loc); 377 ParmVarDecl *ArgDecl = *OMD->param_begin(); 378 DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), Loc); 379 ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true); 380 381 // The property type can differ from the ivar type in some situations with 382 // Objective-C pointer types, we can always bit cast the RHS in these cases. 383 if (getContext().getCanonicalType(Ivar->getType()) != 384 getContext().getCanonicalType(ArgDecl->getType())) { 385 ImplicitCastExpr ArgCasted(Ivar->getType(), CastExpr::CK_BitCast, &Arg, 386 CXXBaseSpecifierArray(), false); 387 BinaryOperator Assign(&IvarRef, &ArgCasted, BinaryOperator::Assign, 388 Ivar->getType(), Loc); 389 EmitStmt(&Assign); 390 } else { 391 BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign, 392 Ivar->getType(), Loc); 393 EmitStmt(&Assign); 394 } 395 } 396 397 FinishFunction(); 398} 399 400void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, 401 ObjCMethodDecl *MD, 402 bool ctor) { 403 llvm::SmallVector<CXXBaseOrMemberInitializer *, 8> IvarInitializers; 404 MD->createImplicitParams(CGM.getContext(), IMP->getClassInterface()); 405 StartObjCMethod(MD, IMP->getClassInterface()); 406 for (ObjCImplementationDecl::init_const_iterator B = IMP->init_begin(), 407 E = IMP->init_end(); B != E; ++B) { 408 CXXBaseOrMemberInitializer *Member = (*B); 409 IvarInitializers.push_back(Member); 410 } 411 if (ctor) { 412 for (unsigned I = 0, E = IvarInitializers.size(); I != E; ++I) { 413 CXXBaseOrMemberInitializer *IvarInit = IvarInitializers[I]; 414 FieldDecl *Field = IvarInit->getMember(); 415 QualType FieldType = Field->getType(); 416 ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field); 417 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), 418 LoadObjCSelf(), Ivar, 0); 419 EmitAggExpr(IvarInit->getInit(), LV.getAddress(), 420 LV.isVolatileQualified(), false, true); 421 } 422 // constructor returns 'self'. 423 CodeGenTypes &Types = CGM.getTypes(); 424 QualType IdTy(CGM.getContext().getObjCIdType()); 425 llvm::Value *SelfAsId = 426 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); 427 EmitReturnOfRValue(RValue::get(SelfAsId), IdTy); 428 } 429 else { 430 // dtor 431 for (size_t i = IvarInitializers.size(); i > 0; --i) { 432 FieldDecl *Field = IvarInitializers[i - 1]->getMember(); 433 QualType FieldType = Field->getType(); 434 const ConstantArrayType *Array = 435 getContext().getAsConstantArrayType(FieldType); 436 if (Array) 437 FieldType = getContext().getBaseElementType(FieldType); 438 439 ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field); 440 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), 441 LoadObjCSelf(), Ivar, 0); 442 const RecordType *RT = FieldType->getAs<RecordType>(); 443 CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); 444 if (Array) { 445 const llvm::Type *BasePtr = ConvertType(FieldType); 446 BasePtr = llvm::PointerType::getUnqual(BasePtr); 447 llvm::Value *BaseAddrPtr = 448 Builder.CreateBitCast(LV.getAddress(), BasePtr); 449 EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()), 450 Array, BaseAddrPtr); 451 } 452 else 453 EmitCXXDestructorCall(FieldClassDecl->getDestructor(CGM.getContext()), 454 Dtor_Complete, /*ForVirtualBase=*/false, 455 LV.getAddress()); 456 } 457 } 458 FinishFunction(); 459} 460 461bool CodeGenFunction::IndirectObjCSetterArg(const CGFunctionInfo &FI) { 462 CGFunctionInfo::const_arg_iterator it = FI.arg_begin(); 463 it++; it++; 464 const ABIArgInfo &AI = it->info; 465 // FIXME. Is this sufficient check? 466 return (AI.getKind() == ABIArgInfo::Indirect); 467} 468 469bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) { 470 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC) 471 return false; 472 if (const RecordType *FDTTy = Ty.getTypePtr()->getAs<RecordType>()) 473 return FDTTy->getDecl()->hasObjectMember(); 474 return false; 475} 476 477llvm::Value *CodeGenFunction::LoadObjCSelf() { 478 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 479 // See if we need to lazily forward self inside a block literal. 480 BlockForwardSelf(); 481 return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self"); 482} 483 484QualType CodeGenFunction::TypeOfSelfObject() { 485 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 486 ImplicitParamDecl *selfDecl = OMD->getSelfDecl(); 487 const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>( 488 getContext().getCanonicalType(selfDecl->getType())); 489 return PTy->getPointeeType(); 490} 491 492RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp, 493 const Selector &S) { 494 llvm::Value *Receiver = LoadObjCSelf(); 495 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 496 bool isClassMessage = OMD->isClassMethod(); 497 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); 498 return CGM.getObjCRuntime().GenerateMessageSendSuper(*this, 499 Exp->getType(), 500 S, 501 OMD->getClassInterface(), 502 isCategoryImpl, 503 Receiver, 504 isClassMessage, 505 CallArgList()); 506 507} 508 509RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp) { 510 Exp = Exp->IgnoreParens(); 511 // FIXME: Split it into two separate routines. 512 if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) { 513 Selector S = E->getProperty()->getGetterName(); 514 if (isa<ObjCSuperExpr>(E->getBase())) 515 return EmitObjCSuperPropertyGet(E, S); 516 return CGM.getObjCRuntime(). 517 GenerateMessageSend(*this, Exp->getType(), S, 518 EmitScalarExpr(E->getBase()), 519 CallArgList()); 520 } else { 521 const ObjCImplicitSetterGetterRefExpr *KE = 522 cast<ObjCImplicitSetterGetterRefExpr>(Exp); 523 Selector S = KE->getGetterMethod()->getSelector(); 524 llvm::Value *Receiver; 525 if (KE->getInterfaceDecl()) { 526 const ObjCInterfaceDecl *OID = KE->getInterfaceDecl(); 527 Receiver = CGM.getObjCRuntime().GetClass(Builder, OID); 528 } else if (isa<ObjCSuperExpr>(KE->getBase())) 529 return EmitObjCSuperPropertyGet(KE, S); 530 else 531 Receiver = EmitScalarExpr(KE->getBase()); 532 return CGM.getObjCRuntime(). 533 GenerateMessageSend(*this, Exp->getType(), S, 534 Receiver, 535 CallArgList(), KE->getInterfaceDecl()); 536 } 537} 538 539void CodeGenFunction::EmitObjCSuperPropertySet(const Expr *Exp, 540 const Selector &S, 541 RValue Src) { 542 CallArgList Args; 543 llvm::Value *Receiver = LoadObjCSelf(); 544 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 545 bool isClassMessage = OMD->isClassMethod(); 546 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); 547 Args.push_back(std::make_pair(Src, Exp->getType())); 548 CGM.getObjCRuntime().GenerateMessageSendSuper(*this, 549 Exp->getType(), 550 S, 551 OMD->getClassInterface(), 552 isCategoryImpl, 553 Receiver, 554 isClassMessage, 555 Args); 556 return; 557} 558 559void CodeGenFunction::EmitObjCPropertySet(const Expr *Exp, 560 RValue Src) { 561 // FIXME: Split it into two separate routines. 562 if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) { 563 Selector S = E->getProperty()->getSetterName(); 564 if (isa<ObjCSuperExpr>(E->getBase())) { 565 EmitObjCSuperPropertySet(E, S, Src); 566 return; 567 } 568 CallArgList Args; 569 Args.push_back(std::make_pair(Src, E->getType())); 570 CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, 571 EmitScalarExpr(E->getBase()), 572 Args); 573 } else if (const ObjCImplicitSetterGetterRefExpr *E = 574 dyn_cast<ObjCImplicitSetterGetterRefExpr>(Exp)) { 575 Selector S = E->getSetterMethod()->getSelector(); 576 CallArgList Args; 577 llvm::Value *Receiver; 578 if (E->getInterfaceDecl()) { 579 const ObjCInterfaceDecl *OID = E->getInterfaceDecl(); 580 Receiver = CGM.getObjCRuntime().GetClass(Builder, OID); 581 } else if (isa<ObjCSuperExpr>(E->getBase())) { 582 EmitObjCSuperPropertySet(E, S, Src); 583 return; 584 } else 585 Receiver = EmitScalarExpr(E->getBase()); 586 Args.push_back(std::make_pair(Src, E->getType())); 587 CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, 588 Receiver, 589 Args, E->getInterfaceDecl()); 590 } else 591 assert (0 && "bad expression node in EmitObjCPropertySet"); 592} 593 594void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ 595 llvm::Constant *EnumerationMutationFn = 596 CGM.getObjCRuntime().EnumerationMutationFunction(); 597 llvm::Value *DeclAddress; 598 QualType ElementTy; 599 600 if (!EnumerationMutationFn) { 601 CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime"); 602 return; 603 } 604 605 if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) { 606 EmitStmt(SD); 607 assert(HaveInsertPoint() && "DeclStmt destroyed insert point!"); 608 const Decl* D = SD->getSingleDecl(); 609 ElementTy = cast<ValueDecl>(D)->getType(); 610 DeclAddress = LocalDeclMap[D]; 611 } else { 612 ElementTy = cast<Expr>(S.getElement())->getType(); 613 DeclAddress = 0; 614 } 615 616 // Fast enumeration state. 617 QualType StateTy = getContext().getObjCFastEnumerationStateType(); 618 llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr"); 619 EmitMemSetToZero(StatePtr, StateTy); 620 621 // Number of elements in the items array. 622 static const unsigned NumItems = 16; 623 624 // Get selector 625 IdentifierInfo *II[] = { 626 &CGM.getContext().Idents.get("countByEnumeratingWithState"), 627 &CGM.getContext().Idents.get("objects"), 628 &CGM.getContext().Idents.get("count") 629 }; 630 Selector FastEnumSel = 631 CGM.getContext().Selectors.getSelector(llvm::array_lengthof(II), &II[0]); 632 633 QualType ItemsTy = 634 getContext().getConstantArrayType(getContext().getObjCIdType(), 635 llvm::APInt(32, NumItems), 636 ArrayType::Normal, 0); 637 llvm::Value *ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr"); 638 639 llvm::Value *Collection = EmitScalarExpr(S.getCollection()); 640 641 CallArgList Args; 642 Args.push_back(std::make_pair(RValue::get(StatePtr), 643 getContext().getPointerType(StateTy))); 644 645 Args.push_back(std::make_pair(RValue::get(ItemsPtr), 646 getContext().getPointerType(ItemsTy))); 647 648 const llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy); 649 llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems); 650 Args.push_back(std::make_pair(RValue::get(Count), 651 getContext().UnsignedLongTy)); 652 653 RValue CountRV = 654 CGM.getObjCRuntime().GenerateMessageSend(*this, 655 getContext().UnsignedLongTy, 656 FastEnumSel, 657 Collection, Args); 658 659 llvm::Value *LimitPtr = CreateMemTemp(getContext().UnsignedLongTy, 660 "limit.ptr"); 661 Builder.CreateStore(CountRV.getScalarVal(), LimitPtr); 662 663 llvm::BasicBlock *NoElements = createBasicBlock("noelements"); 664 llvm::BasicBlock *SetStartMutations = createBasicBlock("setstartmutations"); 665 666 llvm::Value *Limit = Builder.CreateLoad(LimitPtr); 667 llvm::Value *Zero = llvm::Constant::getNullValue(UnsignedLongLTy); 668 669 llvm::Value *IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero"); 670 Builder.CreateCondBr(IsZero, NoElements, SetStartMutations); 671 672 EmitBlock(SetStartMutations); 673 674 llvm::Value *StartMutationsPtr = CreateMemTemp(getContext().UnsignedLongTy); 675 676 llvm::Value *StateMutationsPtrPtr = 677 Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr"); 678 llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, 679 "mutationsptr"); 680 681 llvm::Value *StateMutations = Builder.CreateLoad(StateMutationsPtr, 682 "mutations"); 683 684 Builder.CreateStore(StateMutations, StartMutationsPtr); 685 686 llvm::BasicBlock *LoopStart = createBasicBlock("loopstart"); 687 EmitBlock(LoopStart); 688 689 llvm::Value *CounterPtr = CreateMemTemp(getContext().UnsignedLongTy, 690 "counter.ptr"); 691 Builder.CreateStore(Zero, CounterPtr); 692 693 llvm::BasicBlock *LoopBody = createBasicBlock("loopbody"); 694 EmitBlock(LoopBody); 695 696 StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); 697 StateMutations = Builder.CreateLoad(StateMutationsPtr, "statemutations"); 698 699 llvm::Value *StartMutations = Builder.CreateLoad(StartMutationsPtr, 700 "mutations"); 701 llvm::Value *MutationsEqual = Builder.CreateICmpEQ(StateMutations, 702 StartMutations, 703 "tobool"); 704 705 706 llvm::BasicBlock *WasMutated = createBasicBlock("wasmutated"); 707 llvm::BasicBlock *WasNotMutated = createBasicBlock("wasnotmutated"); 708 709 Builder.CreateCondBr(MutationsEqual, WasNotMutated, WasMutated); 710 711 EmitBlock(WasMutated); 712 llvm::Value *V = 713 Builder.CreateBitCast(Collection, 714 ConvertType(getContext().getObjCIdType()), 715 "tmp"); 716 CallArgList Args2; 717 Args2.push_back(std::make_pair(RValue::get(V), 718 getContext().getObjCIdType())); 719 // FIXME: We shouldn't need to get the function info here, the runtime already 720 // should have computed it to build the function. 721 EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2, 722 FunctionType::ExtInfo()), 723 EnumerationMutationFn, ReturnValueSlot(), Args2); 724 725 EmitBlock(WasNotMutated); 726 727 llvm::Value *StateItemsPtr = 728 Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr"); 729 730 llvm::Value *Counter = Builder.CreateLoad(CounterPtr, "counter"); 731 732 llvm::Value *EnumStateItems = Builder.CreateLoad(StateItemsPtr, 733 "stateitems"); 734 735 llvm::Value *CurrentItemPtr = 736 Builder.CreateGEP(EnumStateItems, Counter, "currentitem.ptr"); 737 738 llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr, "currentitem"); 739 740 // Cast the item to the right type. 741 CurrentItem = Builder.CreateBitCast(CurrentItem, 742 ConvertType(ElementTy), "tmp"); 743 744 if (!DeclAddress) { 745 LValue LV = EmitLValue(cast<Expr>(S.getElement())); 746 747 // Set the value to null. 748 Builder.CreateStore(CurrentItem, LV.getAddress()); 749 } else 750 Builder.CreateStore(CurrentItem, DeclAddress); 751 752 // Increment the counter. 753 Counter = Builder.CreateAdd(Counter, 754 llvm::ConstantInt::get(UnsignedLongLTy, 1)); 755 Builder.CreateStore(Counter, CounterPtr); 756 757 llvm::BasicBlock *LoopEnd = createBasicBlock("loopend"); 758 llvm::BasicBlock *AfterBody = createBasicBlock("afterbody"); 759 760 BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody)); 761 762 EmitStmt(S.getBody()); 763 764 BreakContinueStack.pop_back(); 765 766 EmitBlock(AfterBody); 767 768 llvm::BasicBlock *FetchMore = createBasicBlock("fetchmore"); 769 770 Counter = Builder.CreateLoad(CounterPtr); 771 Limit = Builder.CreateLoad(LimitPtr); 772 llvm::Value *IsLess = Builder.CreateICmpULT(Counter, Limit, "isless"); 773 Builder.CreateCondBr(IsLess, LoopBody, FetchMore); 774 775 // Fetch more elements. 776 EmitBlock(FetchMore); 777 778 CountRV = 779 CGM.getObjCRuntime().GenerateMessageSend(*this, 780 getContext().UnsignedLongTy, 781 FastEnumSel, 782 Collection, Args); 783 Builder.CreateStore(CountRV.getScalarVal(), LimitPtr); 784 Limit = Builder.CreateLoad(LimitPtr); 785 786 IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero"); 787 Builder.CreateCondBr(IsZero, NoElements, LoopStart); 788 789 // No more elements. 790 EmitBlock(NoElements); 791 792 if (!DeclAddress) { 793 // If the element was not a declaration, set it to be null. 794 795 LValue LV = EmitLValue(cast<Expr>(S.getElement())); 796 797 // Set the value to null. 798 Builder.CreateStore(llvm::Constant::getNullValue(ConvertType(ElementTy)), 799 LV.getAddress()); 800 } 801 802 EmitBlock(LoopEnd); 803} 804 805void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) { 806 CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S); 807} 808 809void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) { 810 CGM.getObjCRuntime().EmitThrowStmt(*this, S); 811} 812 813void CodeGenFunction::EmitObjCAtSynchronizedStmt( 814 const ObjCAtSynchronizedStmt &S) { 815 CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S); 816} 817 818CGObjCRuntime::~CGObjCRuntime() {} 819