CGObjC.cpp revision 202879
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#include "clang/AST/StmtObjC.h" 20#include "clang/Basic/Diagnostic.h" 21#include "llvm/ADT/STLExtras.h" 22#include "llvm/Target/TargetData.h" 23using namespace clang; 24using namespace CodeGen; 25 26/// Emits an instance of NSConstantString representing the object. 27llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) 28{ 29 llvm::Constant *C = 30 CGM.getObjCRuntime().GenerateConstantString(E->getString()); 31 // FIXME: This bitcast should just be made an invariant on the Runtime. 32 return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType())); 33} 34 35/// Emit a selector. 36llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) { 37 // Untyped selector. 38 // Note that this implementation allows for non-constant strings to be passed 39 // as arguments to @selector(). Currently, the only thing preventing this 40 // behaviour is the type checking in the front end. 41 return CGM.getObjCRuntime().GetSelector(Builder, E->getSelector()); 42} 43 44llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) { 45 // FIXME: This should pass the Decl not the name. 46 return CGM.getObjCRuntime().GenerateProtocolRef(Builder, E->getProtocol()); 47} 48 49 50RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { 51 // Only the lookup mechanism and first two arguments of the method 52 // implementation vary between runtimes. We can get the receiver and 53 // arguments in generic code. 54 55 CGObjCRuntime &Runtime = CGM.getObjCRuntime(); 56 const Expr *ReceiverExpr = E->getReceiver(); 57 bool isSuperMessage = false; 58 bool isClassMessage = false; 59 // Find the receiver 60 llvm::Value *Receiver; 61 if (!ReceiverExpr) { 62 const ObjCInterfaceDecl *OID = E->getClassInfo().first; 63 64 // Very special case, super send in class method. The receiver is 65 // self (the class object) and the send uses super semantics. 66 if (!OID) { 67 assert(E->getClassName()->isStr("super") && 68 "Unexpected missing class interface in message send."); 69 isSuperMessage = true; 70 Receiver = LoadObjCSelf(); 71 } else { 72 Receiver = Runtime.GetClass(Builder, OID); 73 } 74 75 isClassMessage = true; 76 } else if (isa<ObjCSuperExpr>(E->getReceiver())) { 77 isSuperMessage = true; 78 Receiver = LoadObjCSelf(); 79 } else { 80 Receiver = EmitScalarExpr(E->getReceiver()); 81 } 82 83 CallArgList Args; 84 EmitCallArgs(Args, E->getMethodDecl(), E->arg_begin(), E->arg_end()); 85 86 if (isSuperMessage) { 87 // super is only valid in an Objective-C method 88 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 89 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); 90 return Runtime.GenerateMessageSendSuper(*this, E->getType(), 91 E->getSelector(), 92 OMD->getClassInterface(), 93 isCategoryImpl, 94 Receiver, 95 isClassMessage, 96 Args, 97 E->getMethodDecl()); 98 } 99 100 return Runtime.GenerateMessageSend(*this, E->getType(), E->getSelector(), 101 Receiver, isClassMessage, Args, 102 E->getMethodDecl()); 103} 104 105/// StartObjCMethod - Begin emission of an ObjCMethod. This generates 106/// the LLVM function and sets the other context used by 107/// CodeGenFunction. 108void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, 109 const ObjCContainerDecl *CD) { 110 FunctionArgList Args; 111 llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD); 112 113 const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD); 114 CGM.SetInternalFunctionAttributes(OMD, Fn, FI); 115 116 Args.push_back(std::make_pair(OMD->getSelfDecl(), 117 OMD->getSelfDecl()->getType())); 118 Args.push_back(std::make_pair(OMD->getCmdDecl(), 119 OMD->getCmdDecl()->getType())); 120 121 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 122 E = OMD->param_end(); PI != E; ++PI) 123 Args.push_back(std::make_pair(*PI, (*PI)->getType())); 124 125 StartFunction(OMD, OMD->getResultType(), Fn, Args, OMD->getLocEnd()); 126} 127 128/// Generate an Objective-C method. An Objective-C method is a C function with 129/// its pointer, name, and types registered in the class struture. 130void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { 131 // Check if we should generate debug info for this method. 132 if (CGM.getDebugInfo() && !OMD->hasAttr<NoDebugAttr>()) 133 DebugInfo = CGM.getDebugInfo(); 134 StartObjCMethod(OMD, OMD->getClassInterface()); 135 EmitStmt(OMD->getBody()); 136 FinishFunction(OMD->getBodyRBrace()); 137} 138 139// FIXME: I wasn't sure about the synthesis approach. If we end up generating an 140// AST for the whole body we can just fall back to having a GenerateFunction 141// which takes the body Stmt. 142 143/// GenerateObjCGetter - Generate an Objective-C property getter 144/// function. The given Decl must be an ObjCImplementationDecl. @synthesize 145/// is illegal within a category. 146void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, 147 const ObjCPropertyImplDecl *PID) { 148 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); 149 const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 150 ObjCMethodDecl *OMD = PD->getGetterMethodDecl(); 151 assert(OMD && "Invalid call to generate getter (empty method)"); 152 // FIXME: This is rather murky, we create this here since they will not have 153 // been created by Sema for us. 154 OMD->createImplicitParams(getContext(), IMP->getClassInterface()); 155 StartObjCMethod(OMD, IMP->getClassInterface()); 156 157 // Determine if we should use an objc_getProperty call for 158 // this. Non-atomic properties are directly evaluated. 159 // atomic 'copy' and 'retain' properties are also directly 160 // evaluated in gc-only mode. 161 if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && 162 !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic) && 163 (PD->getSetterKind() == ObjCPropertyDecl::Copy || 164 PD->getSetterKind() == ObjCPropertyDecl::Retain)) { 165 llvm::Value *GetPropertyFn = 166 CGM.getObjCRuntime().GetPropertyGetFunction(); 167 168 if (!GetPropertyFn) { 169 CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); 170 FinishFunction(); 171 return; 172 } 173 174 // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true). 175 // FIXME: Can't this be simpler? This might even be worse than the 176 // corresponding gcc code. 177 CodeGenTypes &Types = CGM.getTypes(); 178 ValueDecl *Cmd = OMD->getCmdDecl(); 179 llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); 180 QualType IdTy = getContext().getObjCIdType(); 181 llvm::Value *SelfAsId = 182 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); 183 llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); 184 llvm::Value *True = 185 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); 186 CallArgList Args; 187 Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy)); 188 Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); 189 Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); 190 Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy)); 191 // FIXME: We shouldn't need to get the function info here, the 192 // runtime already should have computed it to build the function. 193 RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args), 194 GetPropertyFn, ReturnValueSlot(), Args); 195 // We need to fix the type here. Ivars with copy & retain are 196 // always objects so we don't need to worry about complex or 197 // aggregates. 198 RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), 199 Types.ConvertType(PD->getType()))); 200 EmitReturnOfRValue(RV, PD->getType()); 201 } else { 202 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); 203 if (hasAggregateLLVMType(Ivar->getType())) { 204 EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType()); 205 } else { 206 CodeGenTypes &Types = CGM.getTypes(); 207 RValue RV = EmitLoadOfLValue(LV, Ivar->getType()); 208 RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), 209 Types.ConvertType(PD->getType()))); 210 EmitReturnOfRValue(RV, PD->getType()); 211 } 212 } 213 214 FinishFunction(); 215} 216 217/// GenerateObjCSetter - Generate an Objective-C property setter 218/// function. The given Decl must be an ObjCImplementationDecl. @synthesize 219/// is illegal within a category. 220void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, 221 const ObjCPropertyImplDecl *PID) { 222 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); 223 const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 224 ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); 225 assert(OMD && "Invalid call to generate setter (empty method)"); 226 // FIXME: This is rather murky, we create this here since they will not have 227 // been created by Sema for us. 228 OMD->createImplicitParams(getContext(), IMP->getClassInterface()); 229 StartObjCMethod(OMD, IMP->getClassInterface()); 230 231 bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy; 232 bool IsAtomic = 233 !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); 234 235 // Determine if we should use an objc_setProperty call for 236 // this. Properties with 'copy' semantics always use it, as do 237 // non-atomic properties with 'release' semantics as long as we are 238 // not in gc-only mode. 239 if (IsCopy || 240 (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && 241 PD->getSetterKind() == ObjCPropertyDecl::Retain)) { 242 llvm::Value *SetPropertyFn = 243 CGM.getObjCRuntime().GetPropertySetFunction(); 244 245 if (!SetPropertyFn) { 246 CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); 247 FinishFunction(); 248 return; 249 } 250 251 // Emit objc_setProperty((id) self, _cmd, offset, arg, 252 // <is-atomic>, <is-copy>). 253 // FIXME: Can't this be simpler? This might even be worse than the 254 // corresponding gcc code. 255 CodeGenTypes &Types = CGM.getTypes(); 256 ValueDecl *Cmd = OMD->getCmdDecl(); 257 llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); 258 QualType IdTy = getContext().getObjCIdType(); 259 llvm::Value *SelfAsId = 260 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); 261 llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); 262 llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; 263 llvm::Value *ArgAsId = 264 Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"), 265 Types.ConvertType(IdTy)); 266 llvm::Value *True = 267 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); 268 llvm::Value *False = 269 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); 270 CallArgList Args; 271 Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy)); 272 Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); 273 Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); 274 Args.push_back(std::make_pair(RValue::get(ArgAsId), IdTy)); 275 Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False), 276 getContext().BoolTy)); 277 Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False), 278 getContext().BoolTy)); 279 // FIXME: We shouldn't need to get the function info here, the runtime 280 // already should have computed it to build the function. 281 EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args), SetPropertyFn, 282 ReturnValueSlot(), Args); 283 } else { 284 // FIXME: Find a clean way to avoid AST node creation. 285 SourceLocation Loc = PD->getLocation(); 286 ValueDecl *Self = OMD->getSelfDecl(); 287 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); 288 DeclRefExpr Base(Self, Self->getType(), Loc); 289 ParmVarDecl *ArgDecl = *OMD->param_begin(); 290 DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), Loc); 291 ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true); 292 293 // The property type can differ from the ivar type in some situations with 294 // Objective-C pointer types, we can always bit cast the RHS in these cases. 295 if (getContext().getCanonicalType(Ivar->getType()) != 296 getContext().getCanonicalType(ArgDecl->getType())) { 297 ImplicitCastExpr ArgCasted(Ivar->getType(), CastExpr::CK_BitCast, &Arg, 298 false); 299 BinaryOperator Assign(&IvarRef, &ArgCasted, BinaryOperator::Assign, 300 Ivar->getType(), Loc); 301 EmitStmt(&Assign); 302 } else { 303 BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign, 304 Ivar->getType(), Loc); 305 EmitStmt(&Assign); 306 } 307 } 308 309 FinishFunction(); 310} 311 312llvm::Value *CodeGenFunction::LoadObjCSelf() { 313 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 314 // See if we need to lazily forward self inside a block literal. 315 BlockForwardSelf(); 316 return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self"); 317} 318 319QualType CodeGenFunction::TypeOfSelfObject() { 320 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 321 ImplicitParamDecl *selfDecl = OMD->getSelfDecl(); 322 const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>( 323 getContext().getCanonicalType(selfDecl->getType())); 324 return PTy->getPointeeType(); 325} 326 327RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp, 328 const Selector &S) { 329 llvm::Value *Receiver = LoadObjCSelf(); 330 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 331 bool isClassMessage = OMD->isClassMethod(); 332 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); 333 return CGM.getObjCRuntime().GenerateMessageSendSuper(*this, 334 Exp->getType(), 335 S, 336 OMD->getClassInterface(), 337 isCategoryImpl, 338 Receiver, 339 isClassMessage, 340 CallArgList()); 341 342} 343 344RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp) { 345 Exp = Exp->IgnoreParens(); 346 // FIXME: Split it into two separate routines. 347 if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) { 348 Selector S = E->getProperty()->getGetterName(); 349 if (isa<ObjCSuperExpr>(E->getBase())) 350 return EmitObjCSuperPropertyGet(E, S); 351 return CGM.getObjCRuntime(). 352 GenerateMessageSend(*this, Exp->getType(), S, 353 EmitScalarExpr(E->getBase()), 354 false, CallArgList()); 355 } else { 356 const ObjCImplicitSetterGetterRefExpr *KE = 357 cast<ObjCImplicitSetterGetterRefExpr>(Exp); 358 Selector S = KE->getGetterMethod()->getSelector(); 359 llvm::Value *Receiver; 360 if (KE->getInterfaceDecl()) { 361 const ObjCInterfaceDecl *OID = KE->getInterfaceDecl(); 362 Receiver = CGM.getObjCRuntime().GetClass(Builder, OID); 363 } else if (isa<ObjCSuperExpr>(KE->getBase())) 364 return EmitObjCSuperPropertyGet(KE, S); 365 else 366 Receiver = EmitScalarExpr(KE->getBase()); 367 return CGM.getObjCRuntime(). 368 GenerateMessageSend(*this, Exp->getType(), S, 369 Receiver, 370 KE->getInterfaceDecl() != 0, CallArgList()); 371 } 372} 373 374void CodeGenFunction::EmitObjCSuperPropertySet(const Expr *Exp, 375 const Selector &S, 376 RValue Src) { 377 CallArgList Args; 378 llvm::Value *Receiver = LoadObjCSelf(); 379 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 380 bool isClassMessage = OMD->isClassMethod(); 381 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); 382 Args.push_back(std::make_pair(Src, Exp->getType())); 383 CGM.getObjCRuntime().GenerateMessageSendSuper(*this, 384 Exp->getType(), 385 S, 386 OMD->getClassInterface(), 387 isCategoryImpl, 388 Receiver, 389 isClassMessage, 390 Args); 391 return; 392} 393 394void CodeGenFunction::EmitObjCPropertySet(const Expr *Exp, 395 RValue Src) { 396 // FIXME: Split it into two separate routines. 397 if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) { 398 Selector S = E->getProperty()->getSetterName(); 399 if (isa<ObjCSuperExpr>(E->getBase())) { 400 EmitObjCSuperPropertySet(E, S, Src); 401 return; 402 } 403 CallArgList Args; 404 Args.push_back(std::make_pair(Src, E->getType())); 405 CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, 406 EmitScalarExpr(E->getBase()), 407 false, Args); 408 } else if (const ObjCImplicitSetterGetterRefExpr *E = 409 dyn_cast<ObjCImplicitSetterGetterRefExpr>(Exp)) { 410 Selector S = E->getSetterMethod()->getSelector(); 411 CallArgList Args; 412 llvm::Value *Receiver; 413 if (E->getInterfaceDecl()) { 414 const ObjCInterfaceDecl *OID = E->getInterfaceDecl(); 415 Receiver = CGM.getObjCRuntime().GetClass(Builder, OID); 416 } else if (isa<ObjCSuperExpr>(E->getBase())) { 417 EmitObjCSuperPropertySet(E, S, Src); 418 return; 419 } else 420 Receiver = EmitScalarExpr(E->getBase()); 421 Args.push_back(std::make_pair(Src, E->getType())); 422 CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, 423 Receiver, 424 E->getInterfaceDecl() != 0, Args); 425 } else 426 assert (0 && "bad expression node in EmitObjCPropertySet"); 427} 428 429void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ 430 llvm::Constant *EnumerationMutationFn = 431 CGM.getObjCRuntime().EnumerationMutationFunction(); 432 llvm::Value *DeclAddress; 433 QualType ElementTy; 434 435 if (!EnumerationMutationFn) { 436 CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime"); 437 return; 438 } 439 440 if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) { 441 EmitStmt(SD); 442 assert(HaveInsertPoint() && "DeclStmt destroyed insert point!"); 443 const Decl* D = SD->getSingleDecl(); 444 ElementTy = cast<ValueDecl>(D)->getType(); 445 DeclAddress = LocalDeclMap[D]; 446 } else { 447 ElementTy = cast<Expr>(S.getElement())->getType(); 448 DeclAddress = 0; 449 } 450 451 // Fast enumeration state. 452 QualType StateTy = getContext().getObjCFastEnumerationStateType(); 453 llvm::AllocaInst *StatePtr = CreateTempAlloca(ConvertType(StateTy), 454 "state.ptr"); 455 StatePtr->setAlignment(getContext().getTypeAlign(StateTy) >> 3); 456 EmitMemSetToZero(StatePtr, StateTy); 457 458 // Number of elements in the items array. 459 static const unsigned NumItems = 16; 460 461 // Get selector 462 llvm::SmallVector<IdentifierInfo*, 3> II; 463 II.push_back(&CGM.getContext().Idents.get("countByEnumeratingWithState")); 464 II.push_back(&CGM.getContext().Idents.get("objects")); 465 II.push_back(&CGM.getContext().Idents.get("count")); 466 Selector FastEnumSel = CGM.getContext().Selectors.getSelector(II.size(), 467 &II[0]); 468 469 QualType ItemsTy = 470 getContext().getConstantArrayType(getContext().getObjCIdType(), 471 llvm::APInt(32, NumItems), 472 ArrayType::Normal, 0); 473 llvm::Value *ItemsPtr = CreateTempAlloca(ConvertType(ItemsTy), "items.ptr"); 474 475 llvm::Value *Collection = EmitScalarExpr(S.getCollection()); 476 477 CallArgList Args; 478 Args.push_back(std::make_pair(RValue::get(StatePtr), 479 getContext().getPointerType(StateTy))); 480 481 Args.push_back(std::make_pair(RValue::get(ItemsPtr), 482 getContext().getPointerType(ItemsTy))); 483 484 const llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy); 485 llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems); 486 Args.push_back(std::make_pair(RValue::get(Count), 487 getContext().UnsignedLongTy)); 488 489 RValue CountRV = 490 CGM.getObjCRuntime().GenerateMessageSend(*this, 491 getContext().UnsignedLongTy, 492 FastEnumSel, 493 Collection, false, Args); 494 495 llvm::Value *LimitPtr = CreateTempAlloca(UnsignedLongLTy, "limit.ptr"); 496 Builder.CreateStore(CountRV.getScalarVal(), LimitPtr); 497 498 llvm::BasicBlock *NoElements = createBasicBlock("noelements"); 499 llvm::BasicBlock *SetStartMutations = createBasicBlock("setstartmutations"); 500 501 llvm::Value *Limit = Builder.CreateLoad(LimitPtr); 502 llvm::Value *Zero = llvm::Constant::getNullValue(UnsignedLongLTy); 503 504 llvm::Value *IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero"); 505 Builder.CreateCondBr(IsZero, NoElements, SetStartMutations); 506 507 EmitBlock(SetStartMutations); 508 509 llvm::Value *StartMutationsPtr = 510 CreateTempAlloca(UnsignedLongLTy); 511 512 llvm::Value *StateMutationsPtrPtr = 513 Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr"); 514 llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, 515 "mutationsptr"); 516 517 llvm::Value *StateMutations = Builder.CreateLoad(StateMutationsPtr, 518 "mutations"); 519 520 Builder.CreateStore(StateMutations, StartMutationsPtr); 521 522 llvm::BasicBlock *LoopStart = createBasicBlock("loopstart"); 523 EmitBlock(LoopStart); 524 525 llvm::Value *CounterPtr = CreateTempAlloca(UnsignedLongLTy, "counter.ptr"); 526 Builder.CreateStore(Zero, CounterPtr); 527 528 llvm::BasicBlock *LoopBody = createBasicBlock("loopbody"); 529 EmitBlock(LoopBody); 530 531 StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); 532 StateMutations = Builder.CreateLoad(StateMutationsPtr, "statemutations"); 533 534 llvm::Value *StartMutations = Builder.CreateLoad(StartMutationsPtr, 535 "mutations"); 536 llvm::Value *MutationsEqual = Builder.CreateICmpEQ(StateMutations, 537 StartMutations, 538 "tobool"); 539 540 541 llvm::BasicBlock *WasMutated = createBasicBlock("wasmutated"); 542 llvm::BasicBlock *WasNotMutated = createBasicBlock("wasnotmutated"); 543 544 Builder.CreateCondBr(MutationsEqual, WasNotMutated, WasMutated); 545 546 EmitBlock(WasMutated); 547 llvm::Value *V = 548 Builder.CreateBitCast(Collection, 549 ConvertType(getContext().getObjCIdType()), 550 "tmp"); 551 CallArgList Args2; 552 Args2.push_back(std::make_pair(RValue::get(V), 553 getContext().getObjCIdType())); 554 // FIXME: We shouldn't need to get the function info here, the runtime already 555 // should have computed it to build the function. 556 EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2), 557 EnumerationMutationFn, ReturnValueSlot(), Args2); 558 559 EmitBlock(WasNotMutated); 560 561 llvm::Value *StateItemsPtr = 562 Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr"); 563 564 llvm::Value *Counter = Builder.CreateLoad(CounterPtr, "counter"); 565 566 llvm::Value *EnumStateItems = Builder.CreateLoad(StateItemsPtr, 567 "stateitems"); 568 569 llvm::Value *CurrentItemPtr = 570 Builder.CreateGEP(EnumStateItems, Counter, "currentitem.ptr"); 571 572 llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr, "currentitem"); 573 574 // Cast the item to the right type. 575 CurrentItem = Builder.CreateBitCast(CurrentItem, 576 ConvertType(ElementTy), "tmp"); 577 578 if (!DeclAddress) { 579 LValue LV = EmitLValue(cast<Expr>(S.getElement())); 580 581 // Set the value to null. 582 Builder.CreateStore(CurrentItem, LV.getAddress()); 583 } else 584 Builder.CreateStore(CurrentItem, DeclAddress); 585 586 // Increment the counter. 587 Counter = Builder.CreateAdd(Counter, 588 llvm::ConstantInt::get(UnsignedLongLTy, 1)); 589 Builder.CreateStore(Counter, CounterPtr); 590 591 llvm::BasicBlock *LoopEnd = createBasicBlock("loopend"); 592 llvm::BasicBlock *AfterBody = createBasicBlock("afterbody"); 593 594 BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody)); 595 596 EmitStmt(S.getBody()); 597 598 BreakContinueStack.pop_back(); 599 600 EmitBlock(AfterBody); 601 602 llvm::BasicBlock *FetchMore = createBasicBlock("fetchmore"); 603 604 Counter = Builder.CreateLoad(CounterPtr); 605 Limit = Builder.CreateLoad(LimitPtr); 606 llvm::Value *IsLess = Builder.CreateICmpULT(Counter, Limit, "isless"); 607 Builder.CreateCondBr(IsLess, LoopBody, FetchMore); 608 609 // Fetch more elements. 610 EmitBlock(FetchMore); 611 612 CountRV = 613 CGM.getObjCRuntime().GenerateMessageSend(*this, 614 getContext().UnsignedLongTy, 615 FastEnumSel, 616 Collection, false, Args); 617 Builder.CreateStore(CountRV.getScalarVal(), LimitPtr); 618 Limit = Builder.CreateLoad(LimitPtr); 619 620 IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero"); 621 Builder.CreateCondBr(IsZero, NoElements, LoopStart); 622 623 // No more elements. 624 EmitBlock(NoElements); 625 626 if (!DeclAddress) { 627 // If the element was not a declaration, set it to be null. 628 629 LValue LV = EmitLValue(cast<Expr>(S.getElement())); 630 631 // Set the value to null. 632 Builder.CreateStore(llvm::Constant::getNullValue(ConvertType(ElementTy)), 633 LV.getAddress()); 634 } 635 636 EmitBlock(LoopEnd); 637} 638 639void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) { 640 CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S); 641} 642 643void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) { 644 CGM.getObjCRuntime().EmitThrowStmt(*this, S); 645} 646 647void CodeGenFunction::EmitObjCAtSynchronizedStmt( 648 const ObjCAtSynchronizedStmt &S) { 649 CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S); 650} 651 652CGObjCRuntime::~CGObjCRuntime() {} 653