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