CGObjC.cpp revision 203955
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->getLocStart()); 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 CC_Default, false), 195 GetPropertyFn, ReturnValueSlot(), Args); 196 // We need to fix the type here. Ivars with copy & retain are 197 // always objects so we don't need to worry about complex or 198 // aggregates. 199 RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), 200 Types.ConvertType(PD->getType()))); 201 EmitReturnOfRValue(RV, PD->getType()); 202 } else { 203 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); 204 if (hasAggregateLLVMType(Ivar->getType())) { 205 EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType()); 206 } else { 207 CodeGenTypes &Types = CGM.getTypes(); 208 RValue RV = EmitLoadOfLValue(LV, Ivar->getType()); 209 RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), 210 Types.ConvertType(PD->getType()))); 211 EmitReturnOfRValue(RV, PD->getType()); 212 } 213 } 214 215 FinishFunction(); 216} 217 218/// GenerateObjCSetter - Generate an Objective-C property setter 219/// function. The given Decl must be an ObjCImplementationDecl. @synthesize 220/// is illegal within a category. 221void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, 222 const ObjCPropertyImplDecl *PID) { 223 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); 224 const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 225 ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); 226 assert(OMD && "Invalid call to generate setter (empty method)"); 227 // FIXME: This is rather murky, we create this here since they will not have 228 // been created by Sema for us. 229 OMD->createImplicitParams(getContext(), IMP->getClassInterface()); 230 StartObjCMethod(OMD, IMP->getClassInterface()); 231 232 bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy; 233 bool IsAtomic = 234 !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); 235 236 // Determine if we should use an objc_setProperty call for 237 // this. Properties with 'copy' semantics always use it, as do 238 // non-atomic properties with 'release' semantics as long as we are 239 // not in gc-only mode. 240 if (IsCopy || 241 (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && 242 PD->getSetterKind() == ObjCPropertyDecl::Retain)) { 243 llvm::Value *SetPropertyFn = 244 CGM.getObjCRuntime().GetPropertySetFunction(); 245 246 if (!SetPropertyFn) { 247 CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); 248 FinishFunction(); 249 return; 250 } 251 252 // Emit objc_setProperty((id) self, _cmd, offset, arg, 253 // <is-atomic>, <is-copy>). 254 // FIXME: Can't this be simpler? This might even be worse than the 255 // corresponding gcc code. 256 CodeGenTypes &Types = CGM.getTypes(); 257 ValueDecl *Cmd = OMD->getCmdDecl(); 258 llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); 259 QualType IdTy = getContext().getObjCIdType(); 260 llvm::Value *SelfAsId = 261 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); 262 llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); 263 llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; 264 llvm::Value *ArgAsId = 265 Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"), 266 Types.ConvertType(IdTy)); 267 llvm::Value *True = 268 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); 269 llvm::Value *False = 270 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); 271 CallArgList Args; 272 Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy)); 273 Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); 274 Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); 275 Args.push_back(std::make_pair(RValue::get(ArgAsId), IdTy)); 276 Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False), 277 getContext().BoolTy)); 278 Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False), 279 getContext().BoolTy)); 280 // FIXME: We shouldn't need to get the function info here, the runtime 281 // already should have computed it to build the function. 282 EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, 283 CC_Default, false), SetPropertyFn, 284 ReturnValueSlot(), Args); 285 } else { 286 // FIXME: Find a clean way to avoid AST node creation. 287 SourceLocation Loc = PD->getLocation(); 288 ValueDecl *Self = OMD->getSelfDecl(); 289 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); 290 DeclRefExpr Base(Self, Self->getType(), Loc); 291 ParmVarDecl *ArgDecl = *OMD->param_begin(); 292 DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), Loc); 293 ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true); 294 295 // The property type can differ from the ivar type in some situations with 296 // Objective-C pointer types, we can always bit cast the RHS in these cases. 297 if (getContext().getCanonicalType(Ivar->getType()) != 298 getContext().getCanonicalType(ArgDecl->getType())) { 299 ImplicitCastExpr ArgCasted(Ivar->getType(), CastExpr::CK_BitCast, &Arg, 300 false); 301 BinaryOperator Assign(&IvarRef, &ArgCasted, BinaryOperator::Assign, 302 Ivar->getType(), Loc); 303 EmitStmt(&Assign); 304 } else { 305 BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign, 306 Ivar->getType(), Loc); 307 EmitStmt(&Assign); 308 } 309 } 310 311 FinishFunction(); 312} 313 314llvm::Value *CodeGenFunction::LoadObjCSelf() { 315 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 316 // See if we need to lazily forward self inside a block literal. 317 BlockForwardSelf(); 318 return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self"); 319} 320 321QualType CodeGenFunction::TypeOfSelfObject() { 322 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 323 ImplicitParamDecl *selfDecl = OMD->getSelfDecl(); 324 const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>( 325 getContext().getCanonicalType(selfDecl->getType())); 326 return PTy->getPointeeType(); 327} 328 329RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp, 330 const Selector &S) { 331 llvm::Value *Receiver = LoadObjCSelf(); 332 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 333 bool isClassMessage = OMD->isClassMethod(); 334 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); 335 return CGM.getObjCRuntime().GenerateMessageSendSuper(*this, 336 Exp->getType(), 337 S, 338 OMD->getClassInterface(), 339 isCategoryImpl, 340 Receiver, 341 isClassMessage, 342 CallArgList()); 343 344} 345 346RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp) { 347 Exp = Exp->IgnoreParens(); 348 // FIXME: Split it into two separate routines. 349 if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) { 350 Selector S = E->getProperty()->getGetterName(); 351 if (isa<ObjCSuperExpr>(E->getBase())) 352 return EmitObjCSuperPropertyGet(E, S); 353 return CGM.getObjCRuntime(). 354 GenerateMessageSend(*this, Exp->getType(), S, 355 EmitScalarExpr(E->getBase()), 356 false, CallArgList()); 357 } else { 358 const ObjCImplicitSetterGetterRefExpr *KE = 359 cast<ObjCImplicitSetterGetterRefExpr>(Exp); 360 Selector S = KE->getGetterMethod()->getSelector(); 361 llvm::Value *Receiver; 362 if (KE->getInterfaceDecl()) { 363 const ObjCInterfaceDecl *OID = KE->getInterfaceDecl(); 364 Receiver = CGM.getObjCRuntime().GetClass(Builder, OID); 365 } else if (isa<ObjCSuperExpr>(KE->getBase())) 366 return EmitObjCSuperPropertyGet(KE, S); 367 else 368 Receiver = EmitScalarExpr(KE->getBase()); 369 return CGM.getObjCRuntime(). 370 GenerateMessageSend(*this, Exp->getType(), S, 371 Receiver, 372 KE->getInterfaceDecl() != 0, CallArgList()); 373 } 374} 375 376void CodeGenFunction::EmitObjCSuperPropertySet(const Expr *Exp, 377 const Selector &S, 378 RValue Src) { 379 CallArgList Args; 380 llvm::Value *Receiver = LoadObjCSelf(); 381 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 382 bool isClassMessage = OMD->isClassMethod(); 383 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); 384 Args.push_back(std::make_pair(Src, Exp->getType())); 385 CGM.getObjCRuntime().GenerateMessageSendSuper(*this, 386 Exp->getType(), 387 S, 388 OMD->getClassInterface(), 389 isCategoryImpl, 390 Receiver, 391 isClassMessage, 392 Args); 393 return; 394} 395 396void CodeGenFunction::EmitObjCPropertySet(const Expr *Exp, 397 RValue Src) { 398 // FIXME: Split it into two separate routines. 399 if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) { 400 Selector S = E->getProperty()->getSetterName(); 401 if (isa<ObjCSuperExpr>(E->getBase())) { 402 EmitObjCSuperPropertySet(E, S, Src); 403 return; 404 } 405 CallArgList Args; 406 Args.push_back(std::make_pair(Src, E->getType())); 407 CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, 408 EmitScalarExpr(E->getBase()), 409 false, Args); 410 } else if (const ObjCImplicitSetterGetterRefExpr *E = 411 dyn_cast<ObjCImplicitSetterGetterRefExpr>(Exp)) { 412 Selector S = E->getSetterMethod()->getSelector(); 413 CallArgList Args; 414 llvm::Value *Receiver; 415 if (E->getInterfaceDecl()) { 416 const ObjCInterfaceDecl *OID = E->getInterfaceDecl(); 417 Receiver = CGM.getObjCRuntime().GetClass(Builder, OID); 418 } else if (isa<ObjCSuperExpr>(E->getBase())) { 419 EmitObjCSuperPropertySet(E, S, Src); 420 return; 421 } else 422 Receiver = EmitScalarExpr(E->getBase()); 423 Args.push_back(std::make_pair(Src, E->getType())); 424 CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, 425 Receiver, 426 E->getInterfaceDecl() != 0, Args); 427 } else 428 assert (0 && "bad expression node in EmitObjCPropertySet"); 429} 430 431void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ 432 llvm::Constant *EnumerationMutationFn = 433 CGM.getObjCRuntime().EnumerationMutationFunction(); 434 llvm::Value *DeclAddress; 435 QualType ElementTy; 436 437 if (!EnumerationMutationFn) { 438 CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime"); 439 return; 440 } 441 442 if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) { 443 EmitStmt(SD); 444 assert(HaveInsertPoint() && "DeclStmt destroyed insert point!"); 445 const Decl* D = SD->getSingleDecl(); 446 ElementTy = cast<ValueDecl>(D)->getType(); 447 DeclAddress = LocalDeclMap[D]; 448 } else { 449 ElementTy = cast<Expr>(S.getElement())->getType(); 450 DeclAddress = 0; 451 } 452 453 // Fast enumeration state. 454 QualType StateTy = getContext().getObjCFastEnumerationStateType(); 455 llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr"); 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 = CreateMemTemp(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 = CreateMemTemp(getContext().UnsignedLongTy, 496 "limit.ptr"); 497 Builder.CreateStore(CountRV.getScalarVal(), LimitPtr); 498 499 llvm::BasicBlock *NoElements = createBasicBlock("noelements"); 500 llvm::BasicBlock *SetStartMutations = createBasicBlock("setstartmutations"); 501 502 llvm::Value *Limit = Builder.CreateLoad(LimitPtr); 503 llvm::Value *Zero = llvm::Constant::getNullValue(UnsignedLongLTy); 504 505 llvm::Value *IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero"); 506 Builder.CreateCondBr(IsZero, NoElements, SetStartMutations); 507 508 EmitBlock(SetStartMutations); 509 510 llvm::Value *StartMutationsPtr = CreateMemTemp(getContext().UnsignedLongTy); 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 = CreateMemTemp(getContext().UnsignedLongTy, 526 "counter.ptr"); 527 Builder.CreateStore(Zero, CounterPtr); 528 529 llvm::BasicBlock *LoopBody = createBasicBlock("loopbody"); 530 EmitBlock(LoopBody); 531 532 StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); 533 StateMutations = Builder.CreateLoad(StateMutationsPtr, "statemutations"); 534 535 llvm::Value *StartMutations = Builder.CreateLoad(StartMutationsPtr, 536 "mutations"); 537 llvm::Value *MutationsEqual = Builder.CreateICmpEQ(StateMutations, 538 StartMutations, 539 "tobool"); 540 541 542 llvm::BasicBlock *WasMutated = createBasicBlock("wasmutated"); 543 llvm::BasicBlock *WasNotMutated = createBasicBlock("wasnotmutated"); 544 545 Builder.CreateCondBr(MutationsEqual, WasNotMutated, WasMutated); 546 547 EmitBlock(WasMutated); 548 llvm::Value *V = 549 Builder.CreateBitCast(Collection, 550 ConvertType(getContext().getObjCIdType()), 551 "tmp"); 552 CallArgList Args2; 553 Args2.push_back(std::make_pair(RValue::get(V), 554 getContext().getObjCIdType())); 555 // FIXME: We shouldn't need to get the function info here, the runtime already 556 // should have computed it to build the function. 557 EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2, 558 CC_Default, false), 559 EnumerationMutationFn, ReturnValueSlot(), Args2); 560 561 EmitBlock(WasNotMutated); 562 563 llvm::Value *StateItemsPtr = 564 Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr"); 565 566 llvm::Value *Counter = Builder.CreateLoad(CounterPtr, "counter"); 567 568 llvm::Value *EnumStateItems = Builder.CreateLoad(StateItemsPtr, 569 "stateitems"); 570 571 llvm::Value *CurrentItemPtr = 572 Builder.CreateGEP(EnumStateItems, Counter, "currentitem.ptr"); 573 574 llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr, "currentitem"); 575 576 // Cast the item to the right type. 577 CurrentItem = Builder.CreateBitCast(CurrentItem, 578 ConvertType(ElementTy), "tmp"); 579 580 if (!DeclAddress) { 581 LValue LV = EmitLValue(cast<Expr>(S.getElement())); 582 583 // Set the value to null. 584 Builder.CreateStore(CurrentItem, LV.getAddress()); 585 } else 586 Builder.CreateStore(CurrentItem, DeclAddress); 587 588 // Increment the counter. 589 Counter = Builder.CreateAdd(Counter, 590 llvm::ConstantInt::get(UnsignedLongLTy, 1)); 591 Builder.CreateStore(Counter, CounterPtr); 592 593 llvm::BasicBlock *LoopEnd = createBasicBlock("loopend"); 594 llvm::BasicBlock *AfterBody = createBasicBlock("afterbody"); 595 596 BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody)); 597 598 EmitStmt(S.getBody()); 599 600 BreakContinueStack.pop_back(); 601 602 EmitBlock(AfterBody); 603 604 llvm::BasicBlock *FetchMore = createBasicBlock("fetchmore"); 605 606 Counter = Builder.CreateLoad(CounterPtr); 607 Limit = Builder.CreateLoad(LimitPtr); 608 llvm::Value *IsLess = Builder.CreateICmpULT(Counter, Limit, "isless"); 609 Builder.CreateCondBr(IsLess, LoopBody, FetchMore); 610 611 // Fetch more elements. 612 EmitBlock(FetchMore); 613 614 CountRV = 615 CGM.getObjCRuntime().GenerateMessageSend(*this, 616 getContext().UnsignedLongTy, 617 FastEnumSel, 618 Collection, false, Args); 619 Builder.CreateStore(CountRV.getScalarVal(), LimitPtr); 620 Limit = Builder.CreateLoad(LimitPtr); 621 622 IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero"); 623 Builder.CreateCondBr(IsZero, NoElements, LoopStart); 624 625 // No more elements. 626 EmitBlock(NoElements); 627 628 if (!DeclAddress) { 629 // If the element was not a declaration, set it to be null. 630 631 LValue LV = EmitLValue(cast<Expr>(S.getElement())); 632 633 // Set the value to null. 634 Builder.CreateStore(llvm::Constant::getNullValue(ConvertType(ElementTy)), 635 LV.getAddress()); 636 } 637 638 EmitBlock(LoopEnd); 639} 640 641void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) { 642 CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S); 643} 644 645void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) { 646 CGM.getObjCRuntime().EmitThrowStmt(*this, S); 647} 648 649void CodeGenFunction::EmitObjCAtSynchronizedStmt( 650 const ObjCAtSynchronizedStmt &S) { 651 CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S); 652} 653 654CGObjCRuntime::~CGObjCRuntime() {} 655