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 "CGDebugInfo.h" 15 #include "CGObjCRuntime.h" 16 #include "CodeGenFunction.h" 17 #include "CodeGenModule.h" 18 #include "clang/AST/ASTContext.h" 19 #include "clang/AST/DeclObjC.h" 20 #include "clang/AST/StmtObjC.h" 21 #include "clang/Basic/Diagnostic.h" 22 #include "llvm/ADT/STLExtras.h" 23 #include "llvm/Target/TargetData.h" 24 using namespace clang; 25 using namespace CodeGen; 26 27 /// Emits an instance of NSConstantString representing the object. 28 llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) 29 { 30 llvm::Constant *C = 31 CGM.getObjCRuntime().GenerateConstantString(E->getString()); 32 // FIXME: This bitcast should just be made an invariant on the Runtime. 33 return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType())); 34 } 35 36 /// Emit a selector. 37 llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) { 38 // Untyped selector. 39 // Note that this implementation allows for non-constant strings to be passed 40 // as arguments to @selector(). Currently, the only thing preventing this 41 // behaviour is the type checking in the front end. 42 return CGM.getObjCRuntime().GetSelector(Builder, E->getSelector()); 43 } 44 45 llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) { 46 // FIXME: This should pass the Decl not the name. 47 return CGM.getObjCRuntime().GenerateProtocolRef(Builder, E->getProtocol()); 48 } 49 50 51 RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, 52 ReturnValueSlot Return) { 53 // Only the lookup mechanism and first two arguments of the method 54 // implementation vary between runtimes. We can get the receiver and 55 // arguments in generic code. 56 57 CGObjCRuntime &Runtime = CGM.getObjCRuntime(); 58 bool isSuperMessage = false; 59 bool isClassMessage = false; 60 ObjCInterfaceDecl *OID = 0; 61 // Find the receiver 62 llvm::Value *Receiver = 0; 63 switch (E->getReceiverKind()) { 64 case ObjCMessageExpr::Instance: 65 Receiver = EmitScalarExpr(E->getInstanceReceiver()); 66 break; 67 68 case ObjCMessageExpr::Class: { 69 const ObjCObjectType *ObjTy 70 = E->getClassReceiver()->getAs<ObjCObjectType>(); 71 assert(ObjTy && "Invalid Objective-C class message send"); 72 OID = ObjTy->getInterface(); 73 assert(OID && "Invalid Objective-C class message send"); 74 Receiver = Runtime.GetClass(Builder, OID); 75 isClassMessage = true; 76 break; 77 } 78 79 case ObjCMessageExpr::SuperInstance: 80 Receiver = LoadObjCSelf(); 81 isSuperMessage = true; 82 break; 83 84 case ObjCMessageExpr::SuperClass: 85 Receiver = LoadObjCSelf(); 86 isSuperMessage = true; 87 isClassMessage = true; 88 break; 89 } 90 91 CallArgList Args; 92 EmitCallArgs(Args, E->getMethodDecl(), E->arg_begin(), E->arg_end()); 93 94 QualType ResultType = 95 E->getMethodDecl() ? E->getMethodDecl()->getResultType() : E->getType(); 96 97 if (isSuperMessage) { 98 // super is only valid in an Objective-C method 99 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 100 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); 101 return Runtime.GenerateMessageSendSuper(*this, Return, ResultType, 102 E->getSelector(), 103 OMD->getClassInterface(), 104 isCategoryImpl, 105 Receiver, 106 isClassMessage, 107 Args, 108 E->getMethodDecl()); 109 } 110 111 return Runtime.GenerateMessageSend(*this, Return, ResultType, 112 E->getSelector(), 113 Receiver, Args, OID, 114 E->getMethodDecl()); 115 } 116 117 /// StartObjCMethod - Begin emission of an ObjCMethod. This generates 118 /// the LLVM function and sets the other context used by 119 /// CodeGenFunction. 120 void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, 121 const ObjCContainerDecl *CD) { 122 FunctionArgList args; 123 // Check if we should generate debug info for this method. 124 if (CGM.getModuleDebugInfo() && !OMD->hasAttr<NoDebugAttr>()) 125 DebugInfo = CGM.getModuleDebugInfo(); 126 127 llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD); 128 129 const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD); 130 CGM.SetInternalFunctionAttributes(OMD, Fn, FI); 131 132 args.push_back(OMD->getSelfDecl()); 133 args.push_back(OMD->getCmdDecl()); 134 135 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 136 E = OMD->param_end(); PI != E; ++PI) 137 args.push_back(*PI); 138 139 CurGD = OMD; 140 141 StartFunction(OMD, OMD->getResultType(), Fn, FI, args, OMD->getLocStart()); 142 } 143 144 void CodeGenFunction::GenerateObjCGetterBody(ObjCIvarDecl *Ivar, 145 bool IsAtomic, bool IsStrong) { 146 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), 147 Ivar, 0); 148 llvm::Value *GetCopyStructFn = 149 CGM.getObjCRuntime().GetGetStructFunction(); 150 CodeGenTypes &Types = CGM.getTypes(); 151 // objc_copyStruct (ReturnValue, &structIvar, 152 // sizeof (Type of Ivar), isAtomic, false); 153 CallArgList Args; 154 RValue RV = RValue::get(Builder.CreateBitCast(ReturnValue, 155 Types.ConvertType(getContext().VoidPtrTy))); 156 Args.add(RV, getContext().VoidPtrTy); 157 RV = RValue::get(Builder.CreateBitCast(LV.getAddress(), 158 Types.ConvertType(getContext().VoidPtrTy))); 159 Args.add(RV, getContext().VoidPtrTy); 160 // sizeof (Type of Ivar) 161 CharUnits Size = getContext().getTypeSizeInChars(Ivar->getType()); 162 llvm::Value *SizeVal = 163 llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), 164 Size.getQuantity()); 165 Args.add(RValue::get(SizeVal), getContext().LongTy); 166 llvm::Value *isAtomic = 167 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 168 IsAtomic ? 1 : 0); 169 Args.add(RValue::get(isAtomic), getContext().BoolTy); 170 llvm::Value *hasStrong = 171 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 172 IsStrong ? 1 : 0); 173 Args.add(RValue::get(hasStrong), getContext().BoolTy); 174 EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, 175 FunctionType::ExtInfo()), 176 GetCopyStructFn, ReturnValueSlot(), Args); 177 } 178 179 /// Generate an Objective-C method. An Objective-C method is a C function with 180 /// its pointer, name, and types registered in the class struture. 181 void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { 182 StartObjCMethod(OMD, OMD->getClassInterface()); 183 EmitStmt(OMD->getBody()); 184 FinishFunction(OMD->getBodyRBrace()); 185 } 186 187 // FIXME: I wasn't sure about the synthesis approach. If we end up generating an 188 // AST for the whole body we can just fall back to having a GenerateFunction 189 // which takes the body Stmt. 190 191 /// GenerateObjCGetter - Generate an Objective-C property getter 192 /// function. The given Decl must be an ObjCImplementationDecl. @synthesize 193 /// is illegal within a category. 194 void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, 195 const ObjCPropertyImplDecl *PID) { 196 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); 197 const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 198 bool IsAtomic = 199 !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); 200 ObjCMethodDecl *OMD = PD->getGetterMethodDecl(); 201 assert(OMD && "Invalid call to generate getter (empty method)"); 202 StartObjCMethod(OMD, IMP->getClassInterface()); 203 204 // Determine if we should use an objc_getProperty call for 205 // this. Non-atomic properties are directly evaluated. 206 // atomic 'copy' and 'retain' properties are also directly 207 // evaluated in gc-only mode. 208 if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && 209 IsAtomic && 210 (PD->getSetterKind() == ObjCPropertyDecl::Copy || 211 PD->getSetterKind() == ObjCPropertyDecl::Retain)) { 212 llvm::Value *GetPropertyFn = 213 CGM.getObjCRuntime().GetPropertyGetFunction(); 214 215 if (!GetPropertyFn) { 216 CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); 217 FinishFunction(); 218 return; 219 } 220 221 // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true). 222 // FIXME: Can't this be simpler? This might even be worse than the 223 // corresponding gcc code. 224 CodeGenTypes &Types = CGM.getTypes(); 225 ValueDecl *Cmd = OMD->getCmdDecl(); 226 llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); 227 QualType IdTy = getContext().getObjCIdType(); 228 llvm::Value *SelfAsId = 229 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); 230 llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); 231 llvm::Value *True = 232 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); 233 CallArgList Args; 234 Args.add(RValue::get(SelfAsId), IdTy); 235 Args.add(RValue::get(CmdVal), Cmd->getType()); 236 Args.add(RValue::get(Offset), getContext().getPointerDiffType()); 237 Args.add(RValue::get(True), getContext().BoolTy); 238 // FIXME: We shouldn't need to get the function info here, the 239 // runtime already should have computed it to build the function. 240 RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args, 241 FunctionType::ExtInfo()), 242 GetPropertyFn, ReturnValueSlot(), Args); 243 // We need to fix the type here. Ivars with copy & retain are 244 // always objects so we don't need to worry about complex or 245 // aggregates. 246 RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), 247 Types.ConvertType(PD->getType()))); 248 EmitReturnOfRValue(RV, PD->getType()); 249 } else { 250 const llvm::Triple &Triple = getContext().Target.getTriple(); 251 QualType IVART = Ivar->getType(); 252 if (IsAtomic && 253 IVART->isScalarType() && 254 (Triple.getArch() == llvm::Triple::arm || 255 Triple.getArch() == llvm::Triple::thumb) && 256 (getContext().getTypeSizeInChars(IVART) 257 > CharUnits::fromQuantity(4)) && 258 CGM.getObjCRuntime().GetGetStructFunction()) { 259 GenerateObjCGetterBody(Ivar, true, false); 260 } 261 else if (IsAtomic && 262 (IVART->isScalarType() && !IVART->isRealFloatingType()) && 263 Triple.getArch() == llvm::Triple::x86 && 264 (getContext().getTypeSizeInChars(IVART) 265 > CharUnits::fromQuantity(4)) && 266 CGM.getObjCRuntime().GetGetStructFunction()) { 267 GenerateObjCGetterBody(Ivar, true, false); 268 } 269 else if (IsAtomic && 270 (IVART->isScalarType() && !IVART->isRealFloatingType()) && 271 Triple.getArch() == llvm::Triple::x86_64 && 272 (getContext().getTypeSizeInChars(IVART) 273 > CharUnits::fromQuantity(8)) && 274 CGM.getObjCRuntime().GetGetStructFunction()) { 275 GenerateObjCGetterBody(Ivar, true, false); 276 } 277 else if (IVART->isAnyComplexType()) { 278 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), 279 Ivar, 0); 280 ComplexPairTy Pair = LoadComplexFromAddr(LV.getAddress(), 281 LV.isVolatileQualified()); 282 StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified()); 283 } 284 else if (hasAggregateLLVMType(IVART)) { 285 bool IsStrong = false; 286 if ((IsStrong = IvarTypeWithAggrGCObjects(IVART)) 287 && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect 288 && CGM.getObjCRuntime().GetGetStructFunction()) { 289 GenerateObjCGetterBody(Ivar, IsAtomic, IsStrong); 290 } 291 else { 292 const CXXRecordDecl *classDecl = IVART->getAsCXXRecordDecl(); 293 294 if (PID->getGetterCXXConstructor() && 295 classDecl && !classDecl->hasTrivialConstructor()) { 296 ReturnStmt *Stmt = 297 new (getContext()) ReturnStmt(SourceLocation(), 298 PID->getGetterCXXConstructor(), 299 0); 300 EmitReturnStmt(*Stmt); 301 } else if (IsAtomic && 302 !IVART->isAnyComplexType() && 303 Triple.getArch() == llvm::Triple::x86 && 304 (getContext().getTypeSizeInChars(IVART) 305 > CharUnits::fromQuantity(4)) && 306 CGM.getObjCRuntime().GetGetStructFunction()) { 307 GenerateObjCGetterBody(Ivar, true, false); 308 } 309 else if (IsAtomic && 310 !IVART->isAnyComplexType() && 311 Triple.getArch() == llvm::Triple::x86_64 && 312 (getContext().getTypeSizeInChars(IVART) 313 > CharUnits::fromQuantity(8)) && 314 CGM.getObjCRuntime().GetGetStructFunction()) { 315 GenerateObjCGetterBody(Ivar, true, false); 316 } 317 else { 318 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), 319 Ivar, 0); 320 EmitAggregateCopy(ReturnValue, LV.getAddress(), IVART); 321 } 322 } 323 } 324 else { 325 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), 326 Ivar, 0); 327 if (PD->getType()->isReferenceType()) { 328 RValue RV = RValue::get(LV.getAddress()); 329 EmitReturnOfRValue(RV, PD->getType()); 330 } 331 else { 332 CodeGenTypes &Types = CGM.getTypes(); 333 RValue RV = EmitLoadOfLValue(LV, IVART); 334 RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), 335 Types.ConvertType(PD->getType()))); 336 EmitReturnOfRValue(RV, PD->getType()); 337 } 338 } 339 } 340 341 FinishFunction(); 342 } 343 344 void CodeGenFunction::GenerateObjCAtomicSetterBody(ObjCMethodDecl *OMD, 345 ObjCIvarDecl *Ivar) { 346 // objc_copyStruct (&structIvar, &Arg, 347 // sizeof (struct something), true, false); 348 llvm::Value *GetCopyStructFn = 349 CGM.getObjCRuntime().GetSetStructFunction(); 350 CodeGenTypes &Types = CGM.getTypes(); 351 CallArgList Args; 352 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); 353 RValue RV = 354 RValue::get(Builder.CreateBitCast(LV.getAddress(), 355 Types.ConvertType(getContext().VoidPtrTy))); 356 Args.add(RV, getContext().VoidPtrTy); 357 llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; 358 llvm::Value *ArgAsPtrTy = 359 Builder.CreateBitCast(Arg, 360 Types.ConvertType(getContext().VoidPtrTy)); 361 RV = RValue::get(ArgAsPtrTy); 362 Args.add(RV, getContext().VoidPtrTy); 363 // sizeof (Type of Ivar) 364 CharUnits Size = getContext().getTypeSizeInChars(Ivar->getType()); 365 llvm::Value *SizeVal = 366 llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), 367 Size.getQuantity()); 368 Args.add(RValue::get(SizeVal), getContext().LongTy); 369 llvm::Value *True = 370 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); 371 Args.add(RValue::get(True), getContext().BoolTy); 372 llvm::Value *False = 373 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); 374 Args.add(RValue::get(False), getContext().BoolTy); 375 EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, 376 FunctionType::ExtInfo()), 377 GetCopyStructFn, ReturnValueSlot(), Args); 378 } 379 380 static bool 381 IvarAssignHasTrvialAssignment(const ObjCPropertyImplDecl *PID, 382 QualType IvarT) { 383 bool HasTrvialAssignment = true; 384 if (PID->getSetterCXXAssignment()) { 385 const CXXRecordDecl *classDecl = IvarT->getAsCXXRecordDecl(); 386 HasTrvialAssignment = 387 (!classDecl || classDecl->hasTrivialCopyAssignment()); 388 } 389 return HasTrvialAssignment; 390 } 391 392 /// GenerateObjCSetter - Generate an Objective-C property setter 393 /// function. The given Decl must be an ObjCImplementationDecl. @synthesize 394 /// is illegal within a category. 395 void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, 396 const ObjCPropertyImplDecl *PID) { 397 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); 398 const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 399 ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); 400 assert(OMD && "Invalid call to generate setter (empty method)"); 401 StartObjCMethod(OMD, IMP->getClassInterface()); 402 const llvm::Triple &Triple = getContext().Target.getTriple(); 403 QualType IVART = Ivar->getType(); 404 bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy; 405 bool IsAtomic = 406 !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); 407 408 // Determine if we should use an objc_setProperty call for 409 // this. Properties with 'copy' semantics always use it, as do 410 // non-atomic properties with 'release' semantics as long as we are 411 // not in gc-only mode. 412 if (IsCopy || 413 (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && 414 PD->getSetterKind() == ObjCPropertyDecl::Retain)) { 415 llvm::Value *SetPropertyFn = 416 CGM.getObjCRuntime().GetPropertySetFunction(); 417 418 if (!SetPropertyFn) { 419 CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); 420 FinishFunction(); 421 return; 422 } 423 424 // Emit objc_setProperty((id) self, _cmd, offset, arg, 425 // <is-atomic>, <is-copy>). 426 // FIXME: Can't this be simpler? This might even be worse than the 427 // corresponding gcc code. 428 CodeGenTypes &Types = CGM.getTypes(); 429 ValueDecl *Cmd = OMD->getCmdDecl(); 430 llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); 431 QualType IdTy = getContext().getObjCIdType(); 432 llvm::Value *SelfAsId = 433 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); 434 llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); 435 llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; 436 llvm::Value *ArgAsId = 437 Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"), 438 Types.ConvertType(IdTy)); 439 llvm::Value *True = 440 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); 441 llvm::Value *False = 442 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); 443 CallArgList Args; 444 Args.add(RValue::get(SelfAsId), IdTy); 445 Args.add(RValue::get(CmdVal), Cmd->getType()); 446 Args.add(RValue::get(Offset), getContext().getPointerDiffType()); 447 Args.add(RValue::get(ArgAsId), IdTy); 448 Args.add(RValue::get(IsAtomic ? True : False), getContext().BoolTy); 449 Args.add(RValue::get(IsCopy ? True : False), getContext().BoolTy); 450 // FIXME: We shouldn't need to get the function info here, the runtime 451 // already should have computed it to build the function. 452 EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, 453 FunctionType::ExtInfo()), 454 SetPropertyFn, 455 ReturnValueSlot(), Args); 456 } else if (IsAtomic && hasAggregateLLVMType(IVART) && 457 !IVART->isAnyComplexType() && 458 IvarAssignHasTrvialAssignment(PID, IVART) && 459 ((Triple.getArch() == llvm::Triple::x86 && 460 (getContext().getTypeSizeInChars(IVART) 461 > CharUnits::fromQuantity(4))) || 462 (Triple.getArch() == llvm::Triple::x86_64 && 463 (getContext().getTypeSizeInChars(IVART) 464 > CharUnits::fromQuantity(8)))) 465 && CGM.getObjCRuntime().GetSetStructFunction()) { 466 // objc_copyStruct (&structIvar, &Arg, 467 // sizeof (struct something), true, false); 468 GenerateObjCAtomicSetterBody(OMD, Ivar); 469 } else if (PID->getSetterCXXAssignment()) { 470 EmitIgnoredExpr(PID->getSetterCXXAssignment()); 471 } else { 472 if (IsAtomic && 473 IVART->isScalarType() && 474 (Triple.getArch() == llvm::Triple::arm || 475 Triple.getArch() == llvm::Triple::thumb) && 476 (getContext().getTypeSizeInChars(IVART) 477 > CharUnits::fromQuantity(4)) && 478 CGM.getObjCRuntime().GetGetStructFunction()) { 479 GenerateObjCAtomicSetterBody(OMD, Ivar); 480 } 481 else if (IsAtomic && 482 (IVART->isScalarType() && !IVART->isRealFloatingType()) && 483 Triple.getArch() == llvm::Triple::x86 && 484 (getContext().getTypeSizeInChars(IVART) 485 > CharUnits::fromQuantity(4)) && 486 CGM.getObjCRuntime().GetGetStructFunction()) { 487 GenerateObjCAtomicSetterBody(OMD, Ivar); 488 } 489 else if (IsAtomic && 490 (IVART->isScalarType() && !IVART->isRealFloatingType()) && 491 Triple.getArch() == llvm::Triple::x86_64 && 492 (getContext().getTypeSizeInChars(IVART) 493 > CharUnits::fromQuantity(8)) && 494 CGM.getObjCRuntime().GetGetStructFunction()) { 495 GenerateObjCAtomicSetterBody(OMD, Ivar); 496 } 497 else { 498 // FIXME: Find a clean way to avoid AST node creation. 499 SourceLocation Loc = PD->getLocation(); 500 ValueDecl *Self = OMD->getSelfDecl(); 501 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); 502 DeclRefExpr Base(Self, Self->getType(), VK_RValue, Loc); 503 ParmVarDecl *ArgDecl = *OMD->param_begin(); 504 QualType T = ArgDecl->getType(); 505 if (T->isReferenceType()) 506 T = cast<ReferenceType>(T)->getPointeeType(); 507 DeclRefExpr Arg(ArgDecl, T, VK_LValue, Loc); 508 ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true); 509 510 // The property type can differ from the ivar type in some situations with 511 // Objective-C pointer types, we can always bit cast the RHS in these cases. 512 if (getContext().getCanonicalType(Ivar->getType()) != 513 getContext().getCanonicalType(ArgDecl->getType())) { 514 ImplicitCastExpr ArgCasted(ImplicitCastExpr::OnStack, 515 Ivar->getType(), CK_BitCast, &Arg, 516 VK_RValue); 517 BinaryOperator Assign(&IvarRef, &ArgCasted, BO_Assign, 518 Ivar->getType(), VK_RValue, OK_Ordinary, Loc); 519 EmitStmt(&Assign); 520 } else { 521 BinaryOperator Assign(&IvarRef, &Arg, BO_Assign, 522 Ivar->getType(), VK_RValue, OK_Ordinary, Loc); 523 EmitStmt(&Assign); 524 } 525 } 526 } 527 528 FinishFunction(); 529 } 530 531 // FIXME: these are stolen from CGClass.cpp, which is lame. 532 namespace { 533 struct CallArrayIvarDtor : EHScopeStack::Cleanup { 534 const ObjCIvarDecl *ivar; 535 llvm::Value *self; 536 CallArrayIvarDtor(const ObjCIvarDecl *ivar, llvm::Value *self) 537 : ivar(ivar), self(self) {} 538 539 void Emit(CodeGenFunction &CGF, bool IsForEH) { 540 LValue lvalue = 541 CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), self, ivar, 0); 542 543 QualType type = ivar->getType(); 544 const ConstantArrayType *arrayType 545 = CGF.getContext().getAsConstantArrayType(type); 546 QualType baseType = CGF.getContext().getBaseElementType(arrayType); 547 const CXXRecordDecl *classDecl = baseType->getAsCXXRecordDecl(); 548 549 llvm::Value *base 550 = CGF.Builder.CreateBitCast(lvalue.getAddress(), 551 CGF.ConvertType(baseType)->getPointerTo()); 552 CGF.EmitCXXAggrDestructorCall(classDecl->getDestructor(), 553 arrayType, base); 554 } 555 }; 556 557 struct CallIvarDtor : EHScopeStack::Cleanup { 558 const ObjCIvarDecl *ivar; 559 llvm::Value *self; 560 CallIvarDtor(const ObjCIvarDecl *ivar, llvm::Value *self) 561 : ivar(ivar), self(self) {} 562 563 void Emit(CodeGenFunction &CGF, bool IsForEH) { 564 LValue lvalue = 565 CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), self, ivar, 0); 566 567 QualType type = ivar->getType(); 568 const CXXRecordDecl *classDecl = type->getAsCXXRecordDecl(); 569 570 CGF.EmitCXXDestructorCall(classDecl->getDestructor(), 571 Dtor_Complete, /*ForVirtualBase=*/false, 572 lvalue.getAddress()); 573 } 574 }; 575 } 576 577 static void emitCXXDestructMethod(CodeGenFunction &CGF, 578 ObjCImplementationDecl *impl) { 579 CodeGenFunction::RunCleanupsScope scope(CGF); 580 581 llvm::Value *self = CGF.LoadObjCSelf(); 582 583 ObjCInterfaceDecl *iface 584 = const_cast<ObjCInterfaceDecl*>(impl->getClassInterface()); 585 for (ObjCIvarDecl *ivar = iface->all_declared_ivar_begin(); 586 ivar; ivar = ivar->getNextIvar()) { 587 QualType type = ivar->getType(); 588 589 // Drill down to the base element type. 590 QualType baseType = type; 591 const ConstantArrayType *arrayType = 592 CGF.getContext().getAsConstantArrayType(baseType); 593 if (arrayType) baseType = CGF.getContext().getBaseElementType(arrayType); 594 595 // Check whether the ivar is a destructible type. 596 QualType::DestructionKind destructKind = baseType.isDestructedType(); 597 assert(destructKind == type.isDestructedType()); 598 599 switch (destructKind) { 600 case QualType::DK_none: 601 continue; 602 603 case QualType::DK_cxx_destructor: 604 if (arrayType) 605 CGF.EHStack.pushCleanup<CallArrayIvarDtor>(NormalAndEHCleanup, 606 ivar, self); 607 else 608 CGF.EHStack.pushCleanup<CallIvarDtor>(NormalAndEHCleanup, 609 ivar, self); 610 break; 611 } 612 } 613 614 assert(scope.requiresCleanups() && "nothing to do in .cxx_destruct?"); 615 } 616 617 void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, 618 ObjCMethodDecl *MD, 619 bool ctor) { 620 MD->createImplicitParams(CGM.getContext(), IMP->getClassInterface()); 621 StartObjCMethod(MD, IMP->getClassInterface()); 622 623 // Emit .cxx_construct. 624 if (ctor) { 625 llvm::SmallVector<CXXCtorInitializer *, 8> IvarInitializers; 626 for (ObjCImplementationDecl::init_const_iterator B = IMP->init_begin(), 627 E = IMP->init_end(); B != E; ++B) { 628 CXXCtorInitializer *IvarInit = (*B); 629 FieldDecl *Field = IvarInit->getAnyMember(); 630 ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field); 631 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), 632 LoadObjCSelf(), Ivar, 0); 633 EmitAggExpr(IvarInit->getInit(), AggValueSlot::forLValue(LV, true)); 634 } 635 // constructor returns 'self'. 636 CodeGenTypes &Types = CGM.getTypes(); 637 QualType IdTy(CGM.getContext().getObjCIdType()); 638 llvm::Value *SelfAsId = 639 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); 640 EmitReturnOfRValue(RValue::get(SelfAsId), IdTy); 641 642 // Emit .cxx_destruct. 643 } else { 644 emitCXXDestructMethod(*this, IMP); 645 } 646 FinishFunction(); 647 } 648 649 bool CodeGenFunction::IndirectObjCSetterArg(const CGFunctionInfo &FI) { 650 CGFunctionInfo::const_arg_iterator it = FI.arg_begin(); 651 it++; it++; 652 const ABIArgInfo &AI = it->info; 653 // FIXME. Is this sufficient check? 654 return (AI.getKind() == ABIArgInfo::Indirect); 655 } 656 657 bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) { 658 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC) 659 return false; 660 if (const RecordType *FDTTy = Ty.getTypePtr()->getAs<RecordType>()) 661 return FDTTy->getDecl()->hasObjectMember(); 662 return false; 663 } 664 665 llvm::Value *CodeGenFunction::LoadObjCSelf() { 666 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 667 return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self"); 668 } 669 670 QualType CodeGenFunction::TypeOfSelfObject() { 671 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); 672 ImplicitParamDecl *selfDecl = OMD->getSelfDecl(); 673 const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>( 674 getContext().getCanonicalType(selfDecl->getType())); 675 return PTy->getPointeeType(); 676 } 677 678 LValue 679 CodeGenFunction::EmitObjCPropertyRefLValue(const ObjCPropertyRefExpr *E) { 680 // This is a special l-value that just issues sends when we load or 681 // store through it. 682 683 // For certain base kinds, we need to emit the base immediately. 684 llvm::Value *Base; 685 if (E->isSuperReceiver()) 686 Base = LoadObjCSelf(); 687 else if (E->isClassReceiver()) 688 Base = CGM.getObjCRuntime().GetClass(Builder, E->getClassReceiver()); 689 else 690 Base = EmitScalarExpr(E->getBase()); 691 return LValue::MakePropertyRef(E, Base); 692 } 693 694 static RValue GenerateMessageSendSuper(CodeGenFunction &CGF, 695 ReturnValueSlot Return, 696 QualType ResultType, 697 Selector S, 698 llvm::Value *Receiver, 699 const CallArgList &CallArgs) { 700 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CGF.CurFuncDecl); 701 bool isClassMessage = OMD->isClassMethod(); 702 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); 703 return CGF.CGM.getObjCRuntime() 704 .GenerateMessageSendSuper(CGF, Return, ResultType, 705 S, OMD->getClassInterface(), 706 isCategoryImpl, Receiver, 707 isClassMessage, CallArgs); 708 } 709 710 RValue CodeGenFunction::EmitLoadOfPropertyRefLValue(LValue LV, 711 ReturnValueSlot Return) { 712 const ObjCPropertyRefExpr *E = LV.getPropertyRefExpr(); 713 QualType ResultType = E->getGetterResultType(); 714 Selector S; 715 if (E->isExplicitProperty()) { 716 const ObjCPropertyDecl *Property = E->getExplicitProperty(); 717 S = Property->getGetterName(); 718 } else { 719 const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter(); 720 S = Getter->getSelector(); 721 } 722 723 llvm::Value *Receiver = LV.getPropertyRefBaseAddr(); 724 725 // Accesses to 'super' follow a different code path. 726 if (E->isSuperReceiver()) 727 return GenerateMessageSendSuper(*this, Return, ResultType, 728 S, Receiver, CallArgList()); 729 730 const ObjCInterfaceDecl *ReceiverClass 731 = (E->isClassReceiver() ? E->getClassReceiver() : 0); 732 return CGM.getObjCRuntime(). 733 GenerateMessageSend(*this, Return, ResultType, S, 734 Receiver, CallArgList(), ReceiverClass); 735 } 736 737 void CodeGenFunction::EmitStoreThroughPropertyRefLValue(RValue Src, 738 LValue Dst) { 739 const ObjCPropertyRefExpr *E = Dst.getPropertyRefExpr(); 740 Selector S = E->getSetterSelector(); 741 QualType ArgType = E->getSetterArgType(); 742 743 // FIXME. Other than scalars, AST is not adequate for setter and 744 // getter type mismatches which require conversion. 745 if (Src.isScalar()) { 746 llvm::Value *SrcVal = Src.getScalarVal(); 747 QualType DstType = getContext().getCanonicalType(ArgType); 748 const llvm::Type *DstTy = ConvertType(DstType); 749 if (SrcVal->getType() != DstTy) 750 Src = 751 RValue::get(EmitScalarConversion(SrcVal, E->getType(), DstType)); 752 } 753 754 CallArgList Args; 755 Args.add(Src, ArgType); 756 757 llvm::Value *Receiver = Dst.getPropertyRefBaseAddr(); 758 QualType ResultType = getContext().VoidTy; 759 760 if (E->isSuperReceiver()) { 761 GenerateMessageSendSuper(*this, ReturnValueSlot(), 762 ResultType, S, Receiver, Args); 763 return; 764 } 765 766 const ObjCInterfaceDecl *ReceiverClass 767 = (E->isClassReceiver() ? E->getClassReceiver() : 0); 768 769 CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), 770 ResultType, S, Receiver, Args, 771 ReceiverClass); 772 } 773 774 void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ 775 llvm::Constant *EnumerationMutationFn = 776 CGM.getObjCRuntime().EnumerationMutationFunction(); 777 778 if (!EnumerationMutationFn) { 779 CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime"); 780 return; 781 } 782 783 // The local variable comes into scope immediately. 784 AutoVarEmission variable = AutoVarEmission::invalid(); 785 if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) 786 variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl())); 787 788 CGDebugInfo *DI = getDebugInfo(); 789 if (DI) { 790 DI->setLocation(S.getSourceRange().getBegin()); 791 DI->EmitRegionStart(Builder); 792 } 793 794 JumpDest LoopEnd = getJumpDestInCurrentScope("forcoll.end"); 795 JumpDest AfterBody = getJumpDestInCurrentScope("forcoll.next"); 796 797 // Fast enumeration state. 798 QualType StateTy = getContext().getObjCFastEnumerationStateType(); 799 llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr"); 800 EmitNullInitialization(StatePtr, StateTy); 801 802 // Number of elements in the items array. 803 static const unsigned NumItems = 16; 804 805 // Fetch the countByEnumeratingWithState:objects:count: selector. 806 IdentifierInfo *II[] = { 807 &CGM.getContext().Idents.get("countByEnumeratingWithState"), 808 &CGM.getContext().Idents.get("objects"), 809 &CGM.getContext().Idents.get("count") 810 }; 811 Selector FastEnumSel = 812 CGM.getContext().Selectors.getSelector(llvm::array_lengthof(II), &II[0]); 813 814 QualType ItemsTy = 815 getContext().getConstantArrayType(getContext().getObjCIdType(), 816 llvm::APInt(32, NumItems), 817 ArrayType::Normal, 0); 818 llvm::Value *ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr"); 819 820 // Emit the collection pointer. 821 llvm::Value *Collection = EmitScalarExpr(S.getCollection()); 822 823 // Send it our message: 824 CallArgList Args; 825 826 // The first argument is a temporary of the enumeration-state type. 827 Args.add(RValue::get(StatePtr), getContext().getPointerType(StateTy)); 828 829 // The second argument is a temporary array with space for NumItems 830 // pointers. We'll actually be loading elements from the array 831 // pointer written into the control state; this buffer is so that 832 // collections that *aren't* backed by arrays can still queue up 833 // batches of elements. 834 Args.add(RValue::get(ItemsPtr), getContext().getPointerType(ItemsTy)); 835 836 // The third argument is the capacity of that temporary array. 837 const llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy); 838 llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems); 839 Args.add(RValue::get(Count), getContext().UnsignedLongTy); 840 841 // Start the enumeration. 842 RValue CountRV = 843 CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), 844 getContext().UnsignedLongTy, 845 FastEnumSel, 846 Collection, Args); 847 848 // The initial number of objects that were returned in the buffer. 849 llvm::Value *initialBufferLimit = CountRV.getScalarVal(); 850 851 llvm::BasicBlock *EmptyBB = createBasicBlock("forcoll.empty"); 852 llvm::BasicBlock *LoopInitBB = createBasicBlock("forcoll.loopinit"); 853 854 llvm::Value *zero = llvm::Constant::getNullValue(UnsignedLongLTy); 855 856 // If the limit pointer was zero to begin with, the collection is 857 // empty; skip all this. 858 Builder.CreateCondBr(Builder.CreateICmpEQ(initialBufferLimit, zero, "iszero"), 859 EmptyBB, LoopInitBB); 860 861 // Otherwise, initialize the loop. 862 EmitBlock(LoopInitBB); 863 864 // Save the initial mutations value. This is the value at an 865 // address that was written into the state object by 866 // countByEnumeratingWithState:objects:count:. 867 llvm::Value *StateMutationsPtrPtr = 868 Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr"); 869 llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, 870 "mutationsptr"); 871 872 llvm::Value *initialMutations = 873 Builder.CreateLoad(StateMutationsPtr, "forcoll.initial-mutations"); 874 875 // Start looping. This is the point we return to whenever we have a 876 // fresh, non-empty batch of objects. 877 llvm::BasicBlock *LoopBodyBB = createBasicBlock("forcoll.loopbody"); 878 EmitBlock(LoopBodyBB); 879 880 // The current index into the buffer. 881 llvm::PHINode *index = Builder.CreatePHI(UnsignedLongLTy, 3, "forcoll.index"); 882 index->addIncoming(zero, LoopInitBB); 883 884 // The current buffer size. 885 llvm::PHINode *count = Builder.CreatePHI(UnsignedLongLTy, 3, "forcoll.count"); 886 count->addIncoming(initialBufferLimit, LoopInitBB); 887 888 // Check whether the mutations value has changed from where it was 889 // at start. StateMutationsPtr should actually be invariant between 890 // refreshes. 891 StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); 892 llvm::Value *currentMutations 893 = Builder.CreateLoad(StateMutationsPtr, "statemutations"); 894 895 llvm::BasicBlock *WasMutatedBB = createBasicBlock("forcoll.mutated"); 896 llvm::BasicBlock *WasNotMutatedBB = createBasicBlock("forcoll.notmutated"); 897 898 Builder.CreateCondBr(Builder.CreateICmpEQ(currentMutations, initialMutations), 899 WasNotMutatedBB, WasMutatedBB); 900 901 // If so, call the enumeration-mutation function. 902 EmitBlock(WasMutatedBB); 903 llvm::Value *V = 904 Builder.CreateBitCast(Collection, 905 ConvertType(getContext().getObjCIdType()), 906 "tmp"); 907 CallArgList Args2; 908 Args2.add(RValue::get(V), getContext().getObjCIdType()); 909 // FIXME: We shouldn't need to get the function info here, the runtime already 910 // should have computed it to build the function. 911 EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2, 912 FunctionType::ExtInfo()), 913 EnumerationMutationFn, ReturnValueSlot(), Args2); 914 915 // Otherwise, or if the mutation function returns, just continue. 916 EmitBlock(WasNotMutatedBB); 917 918 // Initialize the element variable. 919 RunCleanupsScope elementVariableScope(*this); 920 bool elementIsVariable; 921 LValue elementLValue; 922 QualType elementType; 923 if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) { 924 // Initialize the variable, in case it's a __block variable or something. 925 EmitAutoVarInit(variable); 926 927 const VarDecl* D = cast<VarDecl>(SD->getSingleDecl()); 928 DeclRefExpr tempDRE(const_cast<VarDecl*>(D), D->getType(), 929 VK_LValue, SourceLocation()); 930 elementLValue = EmitLValue(&tempDRE); 931 elementType = D->getType(); 932 elementIsVariable = true; 933 } else { 934 elementLValue = LValue(); // suppress warning 935 elementType = cast<Expr>(S.getElement())->getType(); 936 elementIsVariable = false; 937 } 938 const llvm::Type *convertedElementType = ConvertType(elementType); 939 940 // Fetch the buffer out of the enumeration state. 941 // TODO: this pointer should actually be invariant between 942 // refreshes, which would help us do certain loop optimizations. 943 llvm::Value *StateItemsPtr = 944 Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr"); 945 llvm::Value *EnumStateItems = 946 Builder.CreateLoad(StateItemsPtr, "stateitems"); 947 948 // Fetch the value at the current index from the buffer. 949 llvm::Value *CurrentItemPtr = 950 Builder.CreateGEP(EnumStateItems, index, "currentitem.ptr"); 951 llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr); 952 953 // Cast that value to the right type. 954 CurrentItem = Builder.CreateBitCast(CurrentItem, convertedElementType, 955 "currentitem"); 956 957 // Make sure we have an l-value. Yes, this gets evaluated every 958 // time through the loop. 959 if (!elementIsVariable) 960 elementLValue = EmitLValue(cast<Expr>(S.getElement())); 961 962 EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, elementType); 963 964 // If we do have an element variable, this assignment is the end of 965 // its initialization. 966 if (elementIsVariable) 967 EmitAutoVarCleanups(variable); 968 969 // Perform the loop body, setting up break and continue labels. 970 BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody)); 971 { 972 RunCleanupsScope Scope(*this); 973 EmitStmt(S.getBody()); 974 } 975 BreakContinueStack.pop_back(); 976 977 // Destroy the element variable now. 978 elementVariableScope.ForceCleanup(); 979 980 // Check whether there are more elements. 981 EmitBlock(AfterBody.getBlock()); 982 983 llvm::BasicBlock *FetchMoreBB = createBasicBlock("forcoll.refetch"); 984 985 // First we check in the local buffer. 986 llvm::Value *indexPlusOne 987 = Builder.CreateAdd(index, llvm::ConstantInt::get(UnsignedLongLTy, 1)); 988 989 // If we haven't overrun the buffer yet, we can continue. 990 Builder.CreateCondBr(Builder.CreateICmpULT(indexPlusOne, count), 991 LoopBodyBB, FetchMoreBB); 992 993 index->addIncoming(indexPlusOne, AfterBody.getBlock()); 994 count->addIncoming(count, AfterBody.getBlock()); 995 996 // Otherwise, we have to fetch more elements. 997 EmitBlock(FetchMoreBB); 998 999 CountRV = 1000 CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), 1001 getContext().UnsignedLongTy, 1002 FastEnumSel, 1003 Collection, Args); 1004 1005 // If we got a zero count, we're done. 1006 llvm::Value *refetchCount = CountRV.getScalarVal(); 1007 1008 // (note that the message send might split FetchMoreBB) 1009 index->addIncoming(zero, Builder.GetInsertBlock()); 1010 count->addIncoming(refetchCount, Builder.GetInsertBlock()); 1011 1012 Builder.CreateCondBr(Builder.CreateICmpEQ(refetchCount, zero), 1013 EmptyBB, LoopBodyBB); 1014 1015 // No more elements. 1016 EmitBlock(EmptyBB); 1017 1018 if (!elementIsVariable) { 1019 // If the element was not a declaration, set it to be null. 1020 1021 llvm::Value *null = llvm::Constant::getNullValue(convertedElementType); 1022 elementLValue = EmitLValue(cast<Expr>(S.getElement())); 1023 EmitStoreThroughLValue(RValue::get(null), elementLValue, elementType); 1024 } 1025 1026 if (DI) { 1027 DI->setLocation(S.getSourceRange().getEnd()); 1028 DI->EmitRegionEnd(Builder); 1029 } 1030 1031 EmitBlock(LoopEnd.getBlock()); 1032 } 1033 1034 void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) { 1035 CGM.getObjCRuntime().EmitTryStmt(*this, S); 1036 } 1037 1038 void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) { 1039 CGM.getObjCRuntime().EmitThrowStmt(*this, S); 1040 } 1041 1042 void CodeGenFunction::EmitObjCAtSynchronizedStmt( 1043 const ObjCAtSynchronizedStmt &S) { 1044 CGM.getObjCRuntime().EmitSynchronizedStmt(*this, S); 1045 } 1046 1047 CGObjCRuntime::~CGObjCRuntime() {} 1048