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(Ivar->getType(), CastExpr::CK_BitCast, &Arg,
407 CXXBaseSpecifierArray(), false);
408 BinaryOperator Assign(&IvarRef, &ArgCasted, BinaryOperator::Assign,
409 Ivar->getType(), Loc);
412 BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign,
413 Ivar->getType(), Loc);
421 void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
424 llvm::SmallVector<CXXBaseOrMemberInitializer *, 8> IvarInitializers;
425 MD->createImplicitParams(CGM.getContext(), IMP->getClassInterface());
426 StartObjCMethod(MD, IMP->getClassInterface());
427 for (ObjCImplementationDecl::init_const_iterator B = IMP->init_begin(),
428 E = IMP->init_end(); B != E; ++B) {
429 CXXBaseOrMemberInitializer *Member = (*B);
430 IvarInitializers.push_back(Member);
433 for (unsigned I = 0, E = IvarInitializers.size(); I != E; ++I) {
434 CXXBaseOrMemberInitializer *IvarInit = IvarInitializers[I];
435 FieldDecl *Field = IvarInit->getMember();
436 QualType FieldType = Field->getType();
437 ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field);
438 LValue LV = EmitLValueForIvar(TypeOfSelfObject(),
439 LoadObjCSelf(), Ivar, 0);
440 EmitAggExpr(IvarInit->getInit(), LV.getAddress(),
441 LV.isVolatileQualified(), false, true);
443 // constructor returns 'self'.
444 CodeGenTypes &Types = CGM.getTypes();
445 QualType IdTy(CGM.getContext().getObjCIdType());
446 llvm::Value *SelfAsId =
447 Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
448 EmitReturnOfRValue(RValue::get(SelfAsId), IdTy);
451 for (size_t i = IvarInitializers.size(); i > 0; --i) {
452 FieldDecl *Field = IvarInitializers[i - 1]->getMember();
453 QualType FieldType = Field->getType();
454 const ConstantArrayType *Array =
455 getContext().getAsConstantArrayType(FieldType);
457 FieldType = getContext().getBaseElementType(FieldType);
459 ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field);
460 LValue LV = EmitLValueForIvar(TypeOfSelfObject(),
461 LoadObjCSelf(), Ivar, 0);
462 const RecordType *RT = FieldType->getAs<RecordType>();
463 CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
464 CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor();
465 if (!Dtor->isTrivial()) {
467 const llvm::Type *BasePtr = ConvertType(FieldType);
468 BasePtr = llvm::PointerType::getUnqual(BasePtr);
469 llvm::Value *BaseAddrPtr =
470 Builder.CreateBitCast(LV.getAddress(), BasePtr);
471 EmitCXXAggrDestructorCall(Dtor,
474 EmitCXXDestructorCall(Dtor,
475 Dtor_Complete, /*ForVirtualBase=*/false,
484 bool CodeGenFunction::IndirectObjCSetterArg(const CGFunctionInfo &FI) {
485 CGFunctionInfo::const_arg_iterator it = FI.arg_begin();
487 const ABIArgInfo &AI = it->info;
488 // FIXME. Is this sufficient check?
489 return (AI.getKind() == ABIArgInfo::Indirect);
492 bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) {
493 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
495 if (const RecordType *FDTTy = Ty.getTypePtr()->getAs<RecordType>())
496 return FDTTy->getDecl()->hasObjectMember();
500 llvm::Value *CodeGenFunction::LoadObjCSelf() {
501 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
502 return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self");
505 QualType CodeGenFunction::TypeOfSelfObject() {
506 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
507 ImplicitParamDecl *selfDecl = OMD->getSelfDecl();
508 const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>(
509 getContext().getCanonicalType(selfDecl->getType()));
510 return PTy->getPointeeType();
513 RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp,
515 ReturnValueSlot Return) {
516 llvm::Value *Receiver = LoadObjCSelf();
517 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
518 bool isClassMessage = OMD->isClassMethod();
519 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext());
520 return CGM.getObjCRuntime().GenerateMessageSendSuper(*this,
524 OMD->getClassInterface(),
532 RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp,
533 ReturnValueSlot Return) {
534 Exp = Exp->IgnoreParens();
535 // FIXME: Split it into two separate routines.
536 if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) {
537 Selector S = E->getProperty()->getGetterName();
538 if (isa<ObjCSuperExpr>(E->getBase()))
539 return EmitObjCSuperPropertyGet(E, S, Return);
540 return CGM.getObjCRuntime().
541 GenerateMessageSend(*this, Return, Exp->getType(), S,
542 EmitScalarExpr(E->getBase()),
545 const ObjCImplicitSetterGetterRefExpr *KE =
546 cast<ObjCImplicitSetterGetterRefExpr>(Exp);
547 Selector S = KE->getGetterMethod()->getSelector();
548 llvm::Value *Receiver;
549 if (KE->getInterfaceDecl()) {
550 const ObjCInterfaceDecl *OID = KE->getInterfaceDecl();
551 Receiver = CGM.getObjCRuntime().GetClass(Builder, OID);
552 } else if (isa<ObjCSuperExpr>(KE->getBase()))
553 return EmitObjCSuperPropertyGet(KE, S, Return);
555 Receiver = EmitScalarExpr(KE->getBase());
556 return CGM.getObjCRuntime().
557 GenerateMessageSend(*this, Return, Exp->getType(), S,
559 CallArgList(), KE->getInterfaceDecl());
563 void CodeGenFunction::EmitObjCSuperPropertySet(const Expr *Exp,
567 llvm::Value *Receiver = LoadObjCSelf();
568 const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
569 bool isClassMessage = OMD->isClassMethod();
570 bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext());
571 Args.push_back(std::make_pair(Src, Exp->getType()));
572 CGM.getObjCRuntime().GenerateMessageSendSuper(*this,
576 OMD->getClassInterface(),
584 void CodeGenFunction::EmitObjCPropertySet(const Expr *Exp,
586 // FIXME: Split it into two separate routines.
587 if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) {
588 Selector S = E->getProperty()->getSetterName();
589 if (isa<ObjCSuperExpr>(E->getBase())) {
590 EmitObjCSuperPropertySet(E, S, Src);
594 Args.push_back(std::make_pair(Src, E->getType()));
595 CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
596 getContext().VoidTy, S,
597 EmitScalarExpr(E->getBase()),
599 } else if (const ObjCImplicitSetterGetterRefExpr *E =
600 dyn_cast<ObjCImplicitSetterGetterRefExpr>(Exp)) {
601 const ObjCMethodDecl *SetterMD = E->getSetterMethod();
602 Selector S = SetterMD->getSelector();
604 llvm::Value *Receiver;
605 if (E->getInterfaceDecl()) {
606 const ObjCInterfaceDecl *OID = E->getInterfaceDecl();
607 Receiver = CGM.getObjCRuntime().GetClass(Builder, OID);
608 } else if (isa<ObjCSuperExpr>(E->getBase())) {
609 EmitObjCSuperPropertySet(E, S, Src);
612 Receiver = EmitScalarExpr(E->getBase());
613 ObjCMethodDecl::param_iterator P = SetterMD->param_begin();
614 Args.push_back(std::make_pair(Src, (*P)->getType()));
615 CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
616 getContext().VoidTy, S,
618 Args, E->getInterfaceDecl());
620 assert (0 && "bad expression node in EmitObjCPropertySet");
623 void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
624 llvm::Constant *EnumerationMutationFn =
625 CGM.getObjCRuntime().EnumerationMutationFunction();
626 llvm::Value *DeclAddress;
629 if (!EnumerationMutationFn) {
630 CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime");
634 if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
636 assert(HaveInsertPoint() && "DeclStmt destroyed insert point!");
637 const Decl* D = SD->getSingleDecl();
638 ElementTy = cast<ValueDecl>(D)->getType();
639 DeclAddress = LocalDeclMap[D];
641 ElementTy = cast<Expr>(S.getElement())->getType();
645 // Fast enumeration state.
646 QualType StateTy = getContext().getObjCFastEnumerationStateType();
647 llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr");
648 EmitNullInitialization(StatePtr, StateTy);
650 // Number of elements in the items array.
651 static const unsigned NumItems = 16;
654 IdentifierInfo *II[] = {
655 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
656 &CGM.getContext().Idents.get("objects"),
657 &CGM.getContext().Idents.get("count")
659 Selector FastEnumSel =
660 CGM.getContext().Selectors.getSelector(llvm::array_lengthof(II), &II[0]);
663 getContext().getConstantArrayType(getContext().getObjCIdType(),
664 llvm::APInt(32, NumItems),
665 ArrayType::Normal, 0);
666 llvm::Value *ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr");
668 llvm::Value *Collection = EmitScalarExpr(S.getCollection());
671 Args.push_back(std::make_pair(RValue::get(StatePtr),
672 getContext().getPointerType(StateTy)));
674 Args.push_back(std::make_pair(RValue::get(ItemsPtr),
675 getContext().getPointerType(ItemsTy)));
677 const llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy);
678 llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems);
679 Args.push_back(std::make_pair(RValue::get(Count),
680 getContext().UnsignedLongTy));
683 CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
684 getContext().UnsignedLongTy,
688 llvm::Value *LimitPtr = CreateMemTemp(getContext().UnsignedLongTy,
690 Builder.CreateStore(CountRV.getScalarVal(), LimitPtr);
692 llvm::BasicBlock *NoElements = createBasicBlock("noelements");
693 llvm::BasicBlock *SetStartMutations = createBasicBlock("setstartmutations");
695 llvm::Value *Limit = Builder.CreateLoad(LimitPtr);
696 llvm::Value *Zero = llvm::Constant::getNullValue(UnsignedLongLTy);
698 llvm::Value *IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero");
699 Builder.CreateCondBr(IsZero, NoElements, SetStartMutations);
701 EmitBlock(SetStartMutations);
703 llvm::Value *StartMutationsPtr = CreateMemTemp(getContext().UnsignedLongTy);
705 llvm::Value *StateMutationsPtrPtr =
706 Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr");
707 llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr,
710 llvm::Value *StateMutations = Builder.CreateLoad(StateMutationsPtr,
713 Builder.CreateStore(StateMutations, StartMutationsPtr);
715 llvm::BasicBlock *LoopStart = createBasicBlock("loopstart");
716 EmitBlock(LoopStart);
718 llvm::Value *CounterPtr = CreateMemTemp(getContext().UnsignedLongTy,
720 Builder.CreateStore(Zero, CounterPtr);
722 llvm::BasicBlock *LoopBody = createBasicBlock("loopbody");
725 StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr");
726 StateMutations = Builder.CreateLoad(StateMutationsPtr, "statemutations");
728 llvm::Value *StartMutations = Builder.CreateLoad(StartMutationsPtr,
730 llvm::Value *MutationsEqual = Builder.CreateICmpEQ(StateMutations,
735 llvm::BasicBlock *WasMutated = createBasicBlock("wasmutated");
736 llvm::BasicBlock *WasNotMutated = createBasicBlock("wasnotmutated");
738 Builder.CreateCondBr(MutationsEqual, WasNotMutated, WasMutated);
740 EmitBlock(WasMutated);
742 Builder.CreateBitCast(Collection,
743 ConvertType(getContext().getObjCIdType()),
746 Args2.push_back(std::make_pair(RValue::get(V),
747 getContext().getObjCIdType()));
748 // FIXME: We shouldn't need to get the function info here, the runtime already
749 // should have computed it to build the function.
750 EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2,
751 FunctionType::ExtInfo()),
752 EnumerationMutationFn, ReturnValueSlot(), Args2);
754 EmitBlock(WasNotMutated);
756 llvm::Value *StateItemsPtr =
757 Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr");
759 llvm::Value *Counter = Builder.CreateLoad(CounterPtr, "counter");
761 llvm::Value *EnumStateItems = Builder.CreateLoad(StateItemsPtr,
764 llvm::Value *CurrentItemPtr =
765 Builder.CreateGEP(EnumStateItems, Counter, "currentitem.ptr");
767 llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr, "currentitem");
769 // Cast the item to the right type.
770 CurrentItem = Builder.CreateBitCast(CurrentItem,
771 ConvertType(ElementTy), "tmp");
774 LValue LV = EmitLValue(cast<Expr>(S.getElement()));
776 // Set the value to null.
777 Builder.CreateStore(CurrentItem, LV.getAddress());
779 Builder.CreateStore(CurrentItem, DeclAddress);
781 // Increment the counter.
782 Counter = Builder.CreateAdd(Counter,
783 llvm::ConstantInt::get(UnsignedLongLTy, 1));
784 Builder.CreateStore(Counter, CounterPtr);
786 JumpDest LoopEnd = getJumpDestInCurrentScope("loopend");
787 JumpDest AfterBody = getJumpDestInCurrentScope("afterbody");
789 BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
791 EmitStmt(S.getBody());
793 BreakContinueStack.pop_back();
795 EmitBlock(AfterBody.Block);
797 llvm::BasicBlock *FetchMore = createBasicBlock("fetchmore");
799 Counter = Builder.CreateLoad(CounterPtr);
800 Limit = Builder.CreateLoad(LimitPtr);
801 llvm::Value *IsLess = Builder.CreateICmpULT(Counter, Limit, "isless");
802 Builder.CreateCondBr(IsLess, LoopBody, FetchMore);
804 // Fetch more elements.
805 EmitBlock(FetchMore);
808 CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
809 getContext().UnsignedLongTy,
812 Builder.CreateStore(CountRV.getScalarVal(), LimitPtr);
813 Limit = Builder.CreateLoad(LimitPtr);
815 IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero");
816 Builder.CreateCondBr(IsZero, NoElements, LoopStart);
819 EmitBlock(NoElements);
822 // If the element was not a declaration, set it to be null.
824 LValue LV = EmitLValue(cast<Expr>(S.getElement()));
826 // Set the value to null.
827 Builder.CreateStore(llvm::Constant::getNullValue(ConvertType(ElementTy)),
831 EmitBlock(LoopEnd.Block);
834 void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) {
835 CGM.getObjCRuntime().EmitTryStmt(*this, S);
838 void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) {
839 CGM.getObjCRuntime().EmitThrowStmt(*this, S);
842 void CodeGenFunction::EmitObjCAtSynchronizedStmt(
843 const ObjCAtSynchronizedStmt &S) {
844 CGM.getObjCRuntime().EmitSynchronizedStmt(*this, S);
847 CGObjCRuntime::~CGObjCRuntime() {}