1 //===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This contains code to emit Objective-C code as LLVM code.
12 //===----------------------------------------------------------------------===//
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"
23 using namespace clang;
24 using namespace CodeGen;
26 /// Emits an instance of NSConstantString representing the object.
27 llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
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()));
36 llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) {
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());
44 llvm::Value *CodeGenFunction::EmitObjCProtocolExpr(const ObjCProtocolExpr *E) {
45 // FIXME: This should pass the Decl not the name.
46 return CGM.getObjCRuntime().GenerateProtocolRef(Builder, E->getProtocol());
50 RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
51 ReturnValueSlot Return) {
52 // Only the lookup mechanism and first two arguments of the method
53 // implementation vary between runtimes. We can get the receiver and
54 // arguments in generic code.
56 CGObjCRuntime &Runtime = CGM.getObjCRuntime();
57 bool isSuperMessage = false;
58 bool isClassMessage = false;
59 ObjCInterfaceDecl *OID = 0;
61 llvm::Value *Receiver = 0;
62 switch (E->getReceiverKind()) {
63 case ObjCMessageExpr::Instance:
64 Receiver = EmitScalarExpr(E->getInstanceReceiver());
67 case ObjCMessageExpr::Class: {
68 const ObjCObjectType *ObjTy
69 = E->getClassReceiver()->getAs<ObjCObjectType>();
70 assert(ObjTy && "Invalid Objective-C class message send");
71 OID = ObjTy->getInterface();
72 assert(OID && "Invalid Objective-C class message send");
73 Receiver = Runtime.GetClass(Builder, OID);
74 isClassMessage = true;
78 case ObjCMessageExpr::SuperInstance:
79 Receiver = LoadObjCSelf();
80 isSuperMessage = true;
83 case ObjCMessageExpr::SuperClass:
84 Receiver = LoadObjCSelf();
85 isSuperMessage = true;
86 isClassMessage = true;
91 EmitCallArgs(Args, E->getMethodDecl(), E->arg_begin(), E->arg_end());
94 E->getMethodDecl() ? E->getMethodDecl()->getResultType() : E->getType();
97 // super is only valid in an Objective-C method
98 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
99 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext());
100 return Runtime.GenerateMessageSendSuper(*this, Return, ResultType,
102 OMD->getClassInterface(),
110 return Runtime.GenerateMessageSend(*this, Return, ResultType,
116 /// StartObjCMethod - Begin emission of an ObjCMethod. This generates
117 /// the LLVM function and sets the other context used by
119 void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
120 const ObjCContainerDecl *CD) {
121 FunctionArgList Args;
122 // Check if we should generate debug info for this method.
123 if (CGM.getDebugInfo() && !OMD->hasAttr<NoDebugAttr>())
124 DebugInfo = CGM.getDebugInfo();
126 llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD);
128 const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD);
129 CGM.SetInternalFunctionAttributes(OMD, Fn, FI);
131 Args.push_back(std::make_pair(OMD->getSelfDecl(),
132 OMD->getSelfDecl()->getType()));
133 Args.push_back(std::make_pair(OMD->getCmdDecl(),
134 OMD->getCmdDecl()->getType()));
136 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
137 E = OMD->param_end(); PI != E; ++PI)
138 Args.push_back(std::make_pair(*PI, (*PI)->getType()));
140 StartFunction(OMD, OMD->getResultType(), Fn, Args, OMD->getLocStart());
143 /// Generate an Objective-C method. An Objective-C method is a C function with
144 /// its pointer, name, and types registered in the class struture.
145 void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
146 StartObjCMethod(OMD, OMD->getClassInterface());
147 EmitStmt(OMD->getBody());
148 FinishFunction(OMD->getBodyRBrace());
151 // FIXME: I wasn't sure about the synthesis approach. If we end up generating an
152 // AST for the whole body we can just fall back to having a GenerateFunction
153 // which takes the body Stmt.
155 /// GenerateObjCGetter - Generate an Objective-C property getter
156 /// function. The given Decl must be an ObjCImplementationDecl. @synthesize
157 /// is illegal within a category.
158 void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
159 const ObjCPropertyImplDecl *PID) {
160 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
161 const ObjCPropertyDecl *PD = PID->getPropertyDecl();
163 !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic);
164 ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
165 assert(OMD && "Invalid call to generate getter (empty method)");
166 StartObjCMethod(OMD, IMP->getClassInterface());
168 // Determine if we should use an objc_getProperty call for
169 // this. Non-atomic properties are directly evaluated.
170 // atomic 'copy' and 'retain' properties are also directly
171 // evaluated in gc-only mode.
172 if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly &&
174 (PD->getSetterKind() == ObjCPropertyDecl::Copy ||
175 PD->getSetterKind() == ObjCPropertyDecl::Retain)) {
176 llvm::Value *GetPropertyFn =
177 CGM.getObjCRuntime().GetPropertyGetFunction();
179 if (!GetPropertyFn) {
180 CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy");
185 // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
186 // FIXME: Can't this be simpler? This might even be worse than the
187 // corresponding gcc code.
188 CodeGenTypes &Types = CGM.getTypes();
189 ValueDecl *Cmd = OMD->getCmdDecl();
190 llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd");
191 QualType IdTy = getContext().getObjCIdType();
192 llvm::Value *SelfAsId =
193 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
194 llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar);
196 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
198 Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy));
199 Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType()));
200 Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy));
201 Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy));
202 // FIXME: We shouldn't need to get the function info here, the
203 // runtime already should have computed it to build the function.
204 RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args,
205 FunctionType::ExtInfo()),
206 GetPropertyFn, ReturnValueSlot(), Args);
207 // We need to fix the type here. Ivars with copy & retain are
208 // always objects so we don't need to worry about complex or
210 RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
211 Types.ConvertType(PD->getType())));
212 EmitReturnOfRValue(RV, PD->getType());
214 if (Ivar->getType()->isAnyComplexType()) {
215 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
217 ComplexPairTy Pair = LoadComplexFromAddr(LV.getAddress(),
218 LV.isVolatileQualified());
219 StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified());
221 else if (hasAggregateLLVMType(Ivar->getType())) {
222 bool IsStrong = false;
223 if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(Ivar->getType())))
224 && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect
225 && CGM.getObjCRuntime().GetCopyStructFunction()) {
226 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
228 llvm::Value *GetCopyStructFn =
229 CGM.getObjCRuntime().GetCopyStructFunction();
230 CodeGenTypes &Types = CGM.getTypes();
231 // objc_copyStruct (ReturnValue, &structIvar,
232 // sizeof (Type of Ivar), isAtomic, false);
234 RValue RV = RValue::get(Builder.CreateBitCast(ReturnValue,
235 Types.ConvertType(getContext().VoidPtrTy)));
236 Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
237 RV = RValue::get(Builder.CreateBitCast(LV.getAddress(),
238 Types.ConvertType(getContext().VoidPtrTy)));
239 Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
240 // sizeof (Type of Ivar)
241 uint64_t Size = getContext().getTypeSize(Ivar->getType()) / 8;
242 llvm::Value *SizeVal =
243 llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size);
244 Args.push_back(std::make_pair(RValue::get(SizeVal),
245 getContext().LongTy));
246 llvm::Value *isAtomic =
247 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),
249 Args.push_back(std::make_pair(RValue::get(isAtomic),
250 getContext().BoolTy));
251 llvm::Value *hasStrong =
252 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),
254 Args.push_back(std::make_pair(RValue::get(hasStrong),
255 getContext().BoolTy));
256 EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
257 FunctionType::ExtInfo()),
258 GetCopyStructFn, ReturnValueSlot(), Args);
261 if (PID->getGetterCXXConstructor()) {
263 new (getContext()) ReturnStmt(SourceLocation(),
264 PID->getGetterCXXConstructor(),
266 EmitReturnStmt(*Stmt);
269 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
271 EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType());
275 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),
277 CodeGenTypes &Types = CGM.getTypes();
278 RValue RV = EmitLoadOfLValue(LV, Ivar->getType());
279 RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
280 Types.ConvertType(PD->getType())));
281 EmitReturnOfRValue(RV, PD->getType());
288 /// GenerateObjCSetter - Generate an Objective-C property setter
289 /// function. The given Decl must be an ObjCImplementationDecl. @synthesize
290 /// is illegal within a category.
291 void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
292 const ObjCPropertyImplDecl *PID) {
293 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
294 const ObjCPropertyDecl *PD = PID->getPropertyDecl();
295 ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
296 assert(OMD && "Invalid call to generate setter (empty method)");
297 StartObjCMethod(OMD, IMP->getClassInterface());
299 bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy;
301 !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic);
303 // Determine if we should use an objc_setProperty call for
304 // this. Properties with 'copy' semantics always use it, as do
305 // non-atomic properties with 'release' semantics as long as we are
306 // not in gc-only mode.
308 (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly &&
309 PD->getSetterKind() == ObjCPropertyDecl::Retain)) {
310 llvm::Value *SetPropertyFn =
311 CGM.getObjCRuntime().GetPropertySetFunction();
313 if (!SetPropertyFn) {
314 CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy");
319 // Emit objc_setProperty((id) self, _cmd, offset, arg,
320 // <is-atomic>, <is-copy>).
321 // FIXME: Can't this be simpler? This might even be worse than the
322 // corresponding gcc code.
323 CodeGenTypes &Types = CGM.getTypes();
324 ValueDecl *Cmd = OMD->getCmdDecl();
325 llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd");
326 QualType IdTy = getContext().getObjCIdType();
327 llvm::Value *SelfAsId =
328 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
329 llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar);
330 llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()];
331 llvm::Value *ArgAsId =
332 Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"),
333 Types.ConvertType(IdTy));
335 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
337 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0);
339 Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy));
340 Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType()));
341 Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy));
342 Args.push_back(std::make_pair(RValue::get(ArgAsId), IdTy));
343 Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False),
344 getContext().BoolTy));
345 Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False),
346 getContext().BoolTy));
347 // FIXME: We shouldn't need to get the function info here, the runtime
348 // already should have computed it to build the function.
349 EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
350 FunctionType::ExtInfo()),
352 ReturnValueSlot(), Args);
353 } else if (IsAtomic && hasAggregateLLVMType(Ivar->getType()) &&
354 !Ivar->getType()->isAnyComplexType() &&
355 IndirectObjCSetterArg(*CurFnInfo)
356 && CGM.getObjCRuntime().GetCopyStructFunction()) {
357 // objc_copyStruct (&structIvar, &Arg,
358 // sizeof (struct something), true, false);
359 llvm::Value *GetCopyStructFn =
360 CGM.getObjCRuntime().GetCopyStructFunction();
361 CodeGenTypes &Types = CGM.getTypes();
363 LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0);
364 RValue RV = RValue::get(Builder.CreateBitCast(LV.getAddress(),
365 Types.ConvertType(getContext().VoidPtrTy)));
366 Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
367 llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()];
368 llvm::Value *ArgAsPtrTy =
369 Builder.CreateBitCast(Arg,
370 Types.ConvertType(getContext().VoidPtrTy));
371 RV = RValue::get(ArgAsPtrTy);
372 Args.push_back(std::make_pair(RV, getContext().VoidPtrTy));
373 // sizeof (Type of Ivar)
374 uint64_t Size = getContext().getTypeSize(Ivar->getType()) / 8;
375 llvm::Value *SizeVal =
376 llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size);
377 Args.push_back(std::make_pair(RValue::get(SizeVal),
378 getContext().LongTy));
380 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
381 Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy));
383 llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0);
384 Args.push_back(std::make_pair(RValue::get(False), getContext().BoolTy));
385 EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
386 FunctionType::ExtInfo()),
387 GetCopyStructFn, ReturnValueSlot(), Args);
388 } else if (PID->getSetterCXXAssignment()) {
389 EmitAnyExpr(PID->getSetterCXXAssignment(), (llvm::Value *)0, false, true,
393 // FIXME: Find a clean way to avoid AST node creation.
394 SourceLocation Loc = PD->getLocation();
395 ValueDecl *Self = OMD->getSelfDecl();
396 ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
397 DeclRefExpr Base(Self, Self->getType(), Loc);
398 ParmVarDecl *ArgDecl = *OMD->param_begin();
399 DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), Loc);
400 ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true);
402 // The property type can differ from the ivar type in some situations with
403 // Objective-C pointer types, we can always bit cast the RHS in these cases.
404 if (getContext().getCanonicalType(Ivar->getType()) !=
405 getContext().getCanonicalType(ArgDecl->getType())) {
406 ImplicitCastExpr ArgCasted(ImplicitCastExpr::OnStack,
407 Ivar->getType(), CK_BitCast, &Arg,
409 BinaryOperator Assign(&IvarRef, &ArgCasted, BO_Assign,
410 Ivar->getType(), Loc);
413 BinaryOperator Assign(&IvarRef, &Arg, BO_Assign,
414 Ivar->getType(), Loc);
422 void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
425 llvm::SmallVector<CXXBaseOrMemberInitializer *, 8> IvarInitializers;
426 MD->createImplicitParams(CGM.getContext(), IMP->getClassInterface());
427 StartObjCMethod(MD, IMP->getClassInterface());
428 for (ObjCImplementationDecl::init_const_iterator B = IMP->init_begin(),
429 E = IMP->init_end(); B != E; ++B) {
430 CXXBaseOrMemberInitializer *Member = (*B);
431 IvarInitializers.push_back(Member);
434 for (unsigned I = 0, E = IvarInitializers.size(); I != E; ++I) {
435 CXXBaseOrMemberInitializer *IvarInit = IvarInitializers[I];
436 FieldDecl *Field = IvarInit->getMember();
437 QualType FieldType = Field->getType();
438 ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field);
439 LValue LV = EmitLValueForIvar(TypeOfSelfObject(),
440 LoadObjCSelf(), Ivar, 0);
441 EmitAggExpr(IvarInit->getInit(), LV.getAddress(),
442 LV.isVolatileQualified(), false, true);
444 // constructor returns 'self'.
445 CodeGenTypes &Types = CGM.getTypes();
446 QualType IdTy(CGM.getContext().getObjCIdType());
447 llvm::Value *SelfAsId =
448 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
449 EmitReturnOfRValue(RValue::get(SelfAsId), IdTy);
452 for (size_t i = IvarInitializers.size(); i > 0; --i) {
453 FieldDecl *Field = IvarInitializers[i - 1]->getMember();
454 QualType FieldType = Field->getType();
455 const ConstantArrayType *Array =
456 getContext().getAsConstantArrayType(FieldType);
458 FieldType = getContext().getBaseElementType(FieldType);
460 ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field);
461 LValue LV = EmitLValueForIvar(TypeOfSelfObject(),
462 LoadObjCSelf(), Ivar, 0);
463 const RecordType *RT = FieldType->getAs<RecordType>();
464 CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
465 CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor();
466 if (!Dtor->isTrivial()) {
468 const llvm::Type *BasePtr = ConvertType(FieldType);
469 BasePtr = llvm::PointerType::getUnqual(BasePtr);
470 llvm::Value *BaseAddrPtr =
471 Builder.CreateBitCast(LV.getAddress(), BasePtr);
472 EmitCXXAggrDestructorCall(Dtor,
475 EmitCXXDestructorCall(Dtor,
476 Dtor_Complete, /*ForVirtualBase=*/false,
485 bool CodeGenFunction::IndirectObjCSetterArg(const CGFunctionInfo &FI) {
486 CGFunctionInfo::const_arg_iterator it = FI.arg_begin();
488 const ABIArgInfo &AI = it->info;
489 // FIXME. Is this sufficient check?
490 return (AI.getKind() == ABIArgInfo::Indirect);
493 bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) {
494 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
496 if (const RecordType *FDTTy = Ty.getTypePtr()->getAs<RecordType>())
497 return FDTTy->getDecl()->hasObjectMember();
501 llvm::Value *CodeGenFunction::LoadObjCSelf() {
502 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
503 return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self");
506 QualType CodeGenFunction::TypeOfSelfObject() {
507 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
508 ImplicitParamDecl *selfDecl = OMD->getSelfDecl();
509 const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>(
510 getContext().getCanonicalType(selfDecl->getType()));
511 return PTy->getPointeeType();
514 RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp,
516 ReturnValueSlot Return) {
517 llvm::Value *Receiver = LoadObjCSelf();
518 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
519 bool isClassMessage = OMD->isClassMethod();
520 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext());
521 return CGM.getObjCRuntime().GenerateMessageSendSuper(*this,
525 OMD->getClassInterface(),
533 RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp,
534 ReturnValueSlot Return) {
535 Exp = Exp->IgnoreParens();
536 // FIXME: Split it into two separate routines.
537 if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) {
538 Selector S = E->getProperty()->getGetterName();
539 if (isa<ObjCSuperExpr>(E->getBase()))
540 return EmitObjCSuperPropertyGet(E, S, Return);
541 return CGM.getObjCRuntime().
542 GenerateMessageSend(*this, Return, Exp->getType(), S,
543 EmitScalarExpr(E->getBase()),
546 const ObjCImplicitSetterGetterRefExpr *KE =
547 cast<ObjCImplicitSetterGetterRefExpr>(Exp);
548 Selector S = KE->getGetterMethod()->getSelector();
549 llvm::Value *Receiver;
550 if (KE->getInterfaceDecl()) {
551 const ObjCInterfaceDecl *OID = KE->getInterfaceDecl();
552 Receiver = CGM.getObjCRuntime().GetClass(Builder, OID);
553 } else if (isa<ObjCSuperExpr>(KE->getBase()))
554 return EmitObjCSuperPropertyGet(KE, S, Return);
556 Receiver = EmitScalarExpr(KE->getBase());
557 return CGM.getObjCRuntime().
558 GenerateMessageSend(*this, Return, Exp->getType(), S,
560 CallArgList(), KE->getInterfaceDecl());
564 void CodeGenFunction::EmitObjCSuperPropertySet(const Expr *Exp,
568 llvm::Value *Receiver = LoadObjCSelf();
569 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
570 bool isClassMessage = OMD->isClassMethod();
571 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext());
572 Args.push_back(std::make_pair(Src, Exp->getType()));
573 CGM.getObjCRuntime().GenerateMessageSendSuper(*this,
577 OMD->getClassInterface(),
585 void CodeGenFunction::EmitObjCPropertySet(const Expr *Exp,
587 // FIXME: Split it into two separate routines.
588 if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) {
589 Selector S = E->getProperty()->getSetterName();
590 if (isa<ObjCSuperExpr>(E->getBase())) {
591 EmitObjCSuperPropertySet(E, S, Src);
595 Args.push_back(std::make_pair(Src, E->getType()));
596 CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
597 getContext().VoidTy, S,
598 EmitScalarExpr(E->getBase()),
600 } else if (const ObjCImplicitSetterGetterRefExpr *E =
601 dyn_cast<ObjCImplicitSetterGetterRefExpr>(Exp)) {
602 const ObjCMethodDecl *SetterMD = E->getSetterMethod();
603 Selector S = SetterMD->getSelector();
605 llvm::Value *Receiver;
606 if (E->getInterfaceDecl()) {
607 const ObjCInterfaceDecl *OID = E->getInterfaceDecl();
608 Receiver = CGM.getObjCRuntime().GetClass(Builder, OID);
609 } else if (isa<ObjCSuperExpr>(E->getBase())) {
610 EmitObjCSuperPropertySet(E, S, Src);
613 Receiver = EmitScalarExpr(E->getBase());
614 ObjCMethodDecl::param_iterator P = SetterMD->param_begin();
615 Args.push_back(std::make_pair(Src, (*P)->getType()));
616 CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
617 getContext().VoidTy, S,
619 Args, E->getInterfaceDecl());
621 assert (0 && "bad expression node in EmitObjCPropertySet");
624 void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
625 llvm::Constant *EnumerationMutationFn =
626 CGM.getObjCRuntime().EnumerationMutationFunction();
627 llvm::Value *DeclAddress;
630 if (!EnumerationMutationFn) {
631 CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime");
635 if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
637 assert(HaveInsertPoint() && "DeclStmt destroyed insert point!");
638 const Decl* D = SD->getSingleDecl();
639 ElementTy = cast<ValueDecl>(D)->getType();
640 DeclAddress = LocalDeclMap[D];
642 ElementTy = cast<Expr>(S.getElement())->getType();
646 // Fast enumeration state.
647 QualType StateTy = getContext().getObjCFastEnumerationStateType();
648 llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr");
649 EmitNullInitialization(StatePtr, StateTy);
651 // Number of elements in the items array.
652 static const unsigned NumItems = 16;
655 IdentifierInfo *II[] = {
656 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
657 &CGM.getContext().Idents.get("objects"),
658 &CGM.getContext().Idents.get("count")
660 Selector FastEnumSel =
661 CGM.getContext().Selectors.getSelector(llvm::array_lengthof(II), &II[0]);
664 getContext().getConstantArrayType(getContext().getObjCIdType(),
665 llvm::APInt(32, NumItems),
666 ArrayType::Normal, 0);
667 llvm::Value *ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr");
669 llvm::Value *Collection = EmitScalarExpr(S.getCollection());
672 Args.push_back(std::make_pair(RValue::get(StatePtr),
673 getContext().getPointerType(StateTy)));
675 Args.push_back(std::make_pair(RValue::get(ItemsPtr),
676 getContext().getPointerType(ItemsTy)));
678 const llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy);
679 llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems);
680 Args.push_back(std::make_pair(RValue::get(Count),
681 getContext().UnsignedLongTy));
684 CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
685 getContext().UnsignedLongTy,
689 llvm::Value *LimitPtr = CreateMemTemp(getContext().UnsignedLongTy,
691 Builder.CreateStore(CountRV.getScalarVal(), LimitPtr);
693 llvm::BasicBlock *NoElements = createBasicBlock("noelements");
694 llvm::BasicBlock *SetStartMutations = createBasicBlock("setstartmutations");
696 llvm::Value *Limit = Builder.CreateLoad(LimitPtr);
697 llvm::Value *Zero = llvm::Constant::getNullValue(UnsignedLongLTy);
699 llvm::Value *IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero");
700 Builder.CreateCondBr(IsZero, NoElements, SetStartMutations);
702 EmitBlock(SetStartMutations);
704 llvm::Value *StartMutationsPtr = CreateMemTemp(getContext().UnsignedLongTy);
706 llvm::Value *StateMutationsPtrPtr =
707 Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr");
708 llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr,
711 llvm::Value *StateMutations = Builder.CreateLoad(StateMutationsPtr,
714 Builder.CreateStore(StateMutations, StartMutationsPtr);
716 llvm::BasicBlock *LoopStart = createBasicBlock("loopstart");
717 EmitBlock(LoopStart);
719 llvm::Value *CounterPtr = CreateMemTemp(getContext().UnsignedLongTy,
721 Builder.CreateStore(Zero, CounterPtr);
723 llvm::BasicBlock *LoopBody = createBasicBlock("loopbody");
726 StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr");
727 StateMutations = Builder.CreateLoad(StateMutationsPtr, "statemutations");
729 llvm::Value *StartMutations = Builder.CreateLoad(StartMutationsPtr,
731 llvm::Value *MutationsEqual = Builder.CreateICmpEQ(StateMutations,
736 llvm::BasicBlock *WasMutated = createBasicBlock("wasmutated");
737 llvm::BasicBlock *WasNotMutated = createBasicBlock("wasnotmutated");
739 Builder.CreateCondBr(MutationsEqual, WasNotMutated, WasMutated);
741 EmitBlock(WasMutated);
743 Builder.CreateBitCast(Collection,
744 ConvertType(getContext().getObjCIdType()),
747 Args2.push_back(std::make_pair(RValue::get(V),
748 getContext().getObjCIdType()));
749 // FIXME: We shouldn't need to get the function info here, the runtime already
750 // should have computed it to build the function.
751 EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2,
752 FunctionType::ExtInfo()),
753 EnumerationMutationFn, ReturnValueSlot(), Args2);
755 EmitBlock(WasNotMutated);
757 llvm::Value *StateItemsPtr =
758 Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr");
760 llvm::Value *Counter = Builder.CreateLoad(CounterPtr, "counter");
762 llvm::Value *EnumStateItems = Builder.CreateLoad(StateItemsPtr,
765 llvm::Value *CurrentItemPtr =
766 Builder.CreateGEP(EnumStateItems, Counter, "currentitem.ptr");
768 llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr, "currentitem");
770 // Cast the item to the right type.
771 CurrentItem = Builder.CreateBitCast(CurrentItem,
772 ConvertType(ElementTy), "tmp");
775 LValue LV = EmitLValue(cast<Expr>(S.getElement()));
777 // Set the value to null.
778 Builder.CreateStore(CurrentItem, LV.getAddress());
780 Builder.CreateStore(CurrentItem, DeclAddress);
782 // Increment the counter.
783 Counter = Builder.CreateAdd(Counter,
784 llvm::ConstantInt::get(UnsignedLongLTy, 1));
785 Builder.CreateStore(Counter, CounterPtr);
787 JumpDest LoopEnd = getJumpDestInCurrentScope("loopend");
788 JumpDest AfterBody = getJumpDestInCurrentScope("afterbody");
790 BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
792 EmitStmt(S.getBody());
794 BreakContinueStack.pop_back();
796 EmitBlock(AfterBody.getBlock());
798 llvm::BasicBlock *FetchMore = createBasicBlock("fetchmore");
800 Counter = Builder.CreateLoad(CounterPtr);
801 Limit = Builder.CreateLoad(LimitPtr);
802 llvm::Value *IsLess = Builder.CreateICmpULT(Counter, Limit, "isless");
803 Builder.CreateCondBr(IsLess, LoopBody, FetchMore);
805 // Fetch more elements.
806 EmitBlock(FetchMore);
809 CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
810 getContext().UnsignedLongTy,
813 Builder.CreateStore(CountRV.getScalarVal(), LimitPtr);
814 Limit = Builder.CreateLoad(LimitPtr);
816 IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero");
817 Builder.CreateCondBr(IsZero, NoElements, LoopStart);
820 EmitBlock(NoElements);
823 // If the element was not a declaration, set it to be null.
825 LValue LV = EmitLValue(cast<Expr>(S.getElement()));
827 // Set the value to null.
828 Builder.CreateStore(llvm::Constant::getNullValue(ConvertType(ElementTy)),
832 EmitBlock(LoopEnd.getBlock());
835 void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) {
836 CGM.getObjCRuntime().EmitTryStmt(*this, S);
839 void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) {
840 CGM.getObjCRuntime().EmitThrowStmt(*this, S);
843 void CodeGenFunction::EmitObjCAtSynchronizedStmt(
844 const ObjCAtSynchronizedStmt &S) {
845 CGM.getObjCRuntime().EmitSynchronizedStmt(*this, S);
848 CGObjCRuntime::~CGObjCRuntime() {}