| Anders Carlsson | 5508518 | 2007-08-21 17:43:55 +0000 | [diff] [blame] | 1 | //===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
| Chris Lattner | 0bc735f | 2007-12-29 19:59:25 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
| Anders Carlsson | 5508518 | 2007-08-21 17:43:55 +0000 | [diff] [blame] | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | // This contains code to emit Objective-C code as LLVM code. | 
 | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
| Ted Kremenek | 2979ec7 | 2008-04-09 15:51:31 +0000 | [diff] [blame] | 14 | #include "CGObjCRuntime.h" | 
| Anders Carlsson | 5508518 | 2007-08-21 17:43:55 +0000 | [diff] [blame] | 15 | #include "CodeGenFunction.h" | 
 | 16 | #include "CodeGenModule.h" | 
| Daniel Dunbar | 85c59ed | 2008-08-29 08:11:39 +0000 | [diff] [blame] | 17 | #include "clang/AST/ASTContext.h" | 
| Daniel Dunbar | c4a1dea | 2008-08-11 05:35:13 +0000 | [diff] [blame] | 18 | #include "clang/AST/DeclObjC.h" | 
| Chris Lattner | 16f0049 | 2009-04-26 01:32:48 +0000 | [diff] [blame] | 19 | #include "clang/AST/StmtObjC.h" | 
| Daniel Dunbar | e66f4e3 | 2008-09-03 00:27:26 +0000 | [diff] [blame] | 20 | #include "clang/Basic/Diagnostic.h" | 
| Anders Carlsson | 3d8400d | 2008-08-30 19:51:14 +0000 | [diff] [blame] | 21 | #include "llvm/ADT/STLExtras.h" | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 22 | #include "llvm/Target/TargetData.h" | 
| Anders Carlsson | 5508518 | 2007-08-21 17:43:55 +0000 | [diff] [blame] | 23 | using namespace clang; | 
 | 24 | using namespace CodeGen; | 
 | 25 |  | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 26 | /// Emits an instance of NSConstantString representing the object. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 27 | llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) | 
| Daniel Dunbar | 71fcec9 | 2008-11-25 21:53:21 +0000 | [diff] [blame] | 28 | { | 
| David Chisnall | 0d13f6f | 2010-01-23 02:40:42 +0000 | [diff] [blame] | 29 |   llvm::Constant *C =  | 
 | 30 |       CGM.getObjCRuntime().GenerateConstantString(E->getString()); | 
| Daniel Dunbar | ed7c618 | 2008-08-20 00:28:19 +0000 | [diff] [blame] | 31 |   // FIXME: This bitcast should just be made an invariant on the Runtime. | 
| Owen Anderson | 3c4972d | 2009-07-29 18:54:39 +0000 | [diff] [blame] | 32 |   return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType())); | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 33 | } | 
 | 34 |  | 
 | 35 | /// Emit a selector. | 
 | 36 | llvm::Value *CodeGenFunction::EmitObjCSelectorExpr(const ObjCSelectorExpr *E) { | 
 | 37 |   // Untyped selector. | 
 | 38 |   // Note that this implementation allows for non-constant strings to be passed | 
 | 39 |   // as arguments to @selector().  Currently, the only thing preventing this | 
 | 40 |   // behaviour is the type checking in the front end. | 
| Daniel Dunbar | 6d5a1c2 | 2010-02-03 20:11:42 +0000 | [diff] [blame] | 41 |   return CGM.getObjCRuntime().GetSelector(Builder, E->getSelector()); | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 42 | } | 
 | 43 |  | 
| Daniel Dunbar | ed7c618 | 2008-08-20 00:28:19 +0000 | [diff] [blame] | 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()); | 
 | 47 | } | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 48 |  | 
 | 49 |  | 
| John McCall | ef072fd | 2010-05-22 01:48:05 +0000 | [diff] [blame] | 50 | RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, | 
 | 51 |                                             ReturnValueSlot Return) { | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 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. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 55 |  | 
| Daniel Dunbar | 208ff5e | 2008-08-11 18:12:00 +0000 | [diff] [blame] | 56 |   CGObjCRuntime &Runtime = CGM.getObjCRuntime(); | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 57 |   bool isSuperMessage = false; | 
| Daniel Dunbar | f56f191 | 2008-08-25 08:19:24 +0000 | [diff] [blame] | 58 |   bool isClassMessage = false; | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame] | 59 |   ObjCInterfaceDecl *OID = 0; | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 60 |   // Find the receiver | 
| Daniel Dunbar | 0b647a6 | 2010-04-22 03:17:06 +0000 | [diff] [blame] | 61 |   llvm::Value *Receiver = 0; | 
| Douglas Gregor | 04badcf | 2010-04-21 00:45:42 +0000 | [diff] [blame] | 62 |   switch (E->getReceiverKind()) { | 
 | 63 |   case ObjCMessageExpr::Instance: | 
 | 64 |     Receiver = EmitScalarExpr(E->getInstanceReceiver()); | 
 | 65 |     break; | 
| Daniel Dunbar | ddb2a3d | 2008-08-16 00:25:02 +0000 | [diff] [blame] | 66 |  | 
| Douglas Gregor | 04badcf | 2010-04-21 00:45:42 +0000 | [diff] [blame] | 67 |   case ObjCMessageExpr::Class: { | 
| John McCall | 3031c63 | 2010-05-17 20:12:43 +0000 | [diff] [blame] | 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"); | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame] | 73 |     Receiver = Runtime.GetClass(Builder, OID); | 
| Daniel Dunbar | f56f191 | 2008-08-25 08:19:24 +0000 | [diff] [blame] | 74 |     isClassMessage = true; | 
| Douglas Gregor | 04badcf | 2010-04-21 00:45:42 +0000 | [diff] [blame] | 75 |     break; | 
 | 76 |   } | 
 | 77 |  | 
 | 78 |   case ObjCMessageExpr::SuperInstance: | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 79 |     Receiver = LoadObjCSelf(); | 
| Douglas Gregor | 04badcf | 2010-04-21 00:45:42 +0000 | [diff] [blame] | 80 |     isSuperMessage = true; | 
 | 81 |     break; | 
 | 82 |  | 
 | 83 |   case ObjCMessageExpr::SuperClass: | 
 | 84 |     Receiver = LoadObjCSelf(); | 
 | 85 |     isSuperMessage = true; | 
 | 86 |     isClassMessage = true; | 
 | 87 |     break; | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 88 |   } | 
 | 89 |  | 
| Daniel Dunbar | 19cd87e | 2008-08-30 03:02:31 +0000 | [diff] [blame] | 90 |   CallArgList Args; | 
| Anders Carlsson | 131038e | 2009-04-18 20:29:27 +0000 | [diff] [blame] | 91 |   EmitCallArgs(Args, E->getMethodDecl(), E->arg_begin(), E->arg_end()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 92 |  | 
| Anders Carlsson | 7e70fb2 | 2010-06-21 20:59:55 +0000 | [diff] [blame] | 93 |   QualType ResultType = | 
 | 94 |     E->getMethodDecl() ? E->getMethodDecl()->getResultType() : E->getType(); | 
 | 95 |  | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 96 |   if (isSuperMessage) { | 
| Chris Lattner | 9384c76 | 2008-06-26 04:42:20 +0000 | [diff] [blame] | 97 |     // super is only valid in an Objective-C method | 
 | 98 |     const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); | 
| Fariborz Jahanian | 7ce7792 | 2009-02-28 20:07:56 +0000 | [diff] [blame] | 99 |     bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); | 
| Anders Carlsson | 7e70fb2 | 2010-06-21 20:59:55 +0000 | [diff] [blame] | 100 |     return Runtime.GenerateMessageSendSuper(*this, Return, ResultType, | 
| Daniel Dunbar | 7f8ea5c | 2008-08-30 05:35:15 +0000 | [diff] [blame] | 101 |                                             E->getSelector(), | 
| Daniel Dunbar | f56f191 | 2008-08-25 08:19:24 +0000 | [diff] [blame] | 102 |                                             OMD->getClassInterface(), | 
| Fariborz Jahanian | 7ce7792 | 2009-02-28 20:07:56 +0000 | [diff] [blame] | 103 |                                             isCategoryImpl, | 
| Daniel Dunbar | f56f191 | 2008-08-25 08:19:24 +0000 | [diff] [blame] | 104 |                                             Receiver, | 
| Daniel Dunbar | 19cd87e | 2008-08-30 03:02:31 +0000 | [diff] [blame] | 105 |                                             isClassMessage, | 
| Daniel Dunbar | d6c93d7 | 2009-09-17 04:01:22 +0000 | [diff] [blame] | 106 |                                             Args, | 
 | 107 |                                             E->getMethodDecl()); | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 108 |   } | 
| Daniel Dunbar | d6c93d7 | 2009-09-17 04:01:22 +0000 | [diff] [blame] | 109 |  | 
| Anders Carlsson | 7e70fb2 | 2010-06-21 20:59:55 +0000 | [diff] [blame] | 110 |   return Runtime.GenerateMessageSend(*this, Return, ResultType, | 
| John McCall | ef072fd | 2010-05-22 01:48:05 +0000 | [diff] [blame] | 111 |                                      E->getSelector(), | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame] | 112 |                                      Receiver, Args, OID, | 
| Fariborz Jahanian | df9ccc6 | 2009-05-05 21:36:57 +0000 | [diff] [blame] | 113 |                                      E->getMethodDecl()); | 
| Anders Carlsson | 5508518 | 2007-08-21 17:43:55 +0000 | [diff] [blame] | 114 | } | 
 | 115 |  | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 116 | /// StartObjCMethod - Begin emission of an ObjCMethod. This generates | 
 | 117 | /// the LLVM function and sets the other context used by | 
 | 118 | /// CodeGenFunction. | 
| Fariborz Jahanian | 679a502 | 2009-01-10 21:06:09 +0000 | [diff] [blame] | 119 | void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, | 
 | 120 |                                       const ObjCContainerDecl *CD) { | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 121 |   FunctionArgList Args; | 
| Devang Patel | 4800ea6 | 2010-04-05 21:09:15 +0000 | [diff] [blame] | 122 |   // Check if we should generate debug info for this method. | 
 | 123 |   if (CGM.getDebugInfo() && !OMD->hasAttr<NoDebugAttr>()) | 
 | 124 |     DebugInfo = CGM.getDebugInfo(); | 
 | 125 |  | 
| Fariborz Jahanian | 679a502 | 2009-01-10 21:06:09 +0000 | [diff] [blame] | 126 |   llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD); | 
| Daniel Dunbar | f80519b | 2008-09-04 23:41:35 +0000 | [diff] [blame] | 127 |  | 
| Daniel Dunbar | 0e4f40e | 2009-04-17 00:48:04 +0000 | [diff] [blame] | 128 |   const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD); | 
 | 129 |   CGM.SetInternalFunctionAttributes(OMD, Fn, FI); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 130 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 131 |   Args.push_back(std::make_pair(OMD->getSelfDecl(), | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 132 |                                 OMD->getSelfDecl()->getType())); | 
 | 133 |   Args.push_back(std::make_pair(OMD->getCmdDecl(), | 
 | 134 |                                 OMD->getCmdDecl()->getType())); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 135 |  | 
| Chris Lattner | 89951a8 | 2009-02-20 18:43:26 +0000 | [diff] [blame] | 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())); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 139 |  | 
| Peter Collingbourne | 1411047 | 2011-01-13 18:57:25 +0000 | [diff] [blame^] | 140 |   CurGD = OMD; | 
 | 141 |  | 
| Devang Patel | a92d613 | 2010-02-15 18:08:38 +0000 | [diff] [blame] | 142 |   StartFunction(OMD, OMD->getResultType(), Fn, Args, OMD->getLocStart()); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 143 | } | 
| Daniel Dunbar | b7ec246 | 2008-08-16 03:19:19 +0000 | [diff] [blame] | 144 |  | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 145 | /// Generate an Objective-C method.  An Objective-C method is a C function with | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 146 | /// its pointer, name, and types registered in the class struture. | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 147 | void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { | 
| Fariborz Jahanian | 679a502 | 2009-01-10 21:06:09 +0000 | [diff] [blame] | 148 |   StartObjCMethod(OMD, OMD->getClassInterface()); | 
| Argyrios Kyrtzidis | 6fb0aee | 2009-06-30 02:35:26 +0000 | [diff] [blame] | 149 |   EmitStmt(OMD->getBody()); | 
 | 150 |   FinishFunction(OMD->getBodyRBrace()); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 151 | } | 
 | 152 |  | 
| Mike Stump | f5408fe | 2009-05-16 07:57:57 +0000 | [diff] [blame] | 153 | // FIXME: I wasn't sure about the synthesis approach. If we end up generating an | 
 | 154 | // AST for the whole body we can just fall back to having a GenerateFunction | 
 | 155 | // which takes the body Stmt. | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 156 |  | 
 | 157 | /// GenerateObjCGetter - Generate an Objective-C property getter | 
| Steve Naroff | 489034c | 2009-01-10 22:55:25 +0000 | [diff] [blame] | 158 | /// function. The given Decl must be an ObjCImplementationDecl. @synthesize | 
 | 159 | /// is illegal within a category. | 
| Fariborz Jahanian | fef30b5 | 2008-12-09 20:23:04 +0000 | [diff] [blame] | 160 | void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, | 
 | 161 |                                          const ObjCPropertyImplDecl *PID) { | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 162 |   ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 163 |   const ObjCPropertyDecl *PD = PID->getPropertyDecl(); | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 164 |   bool IsAtomic = | 
 | 165 |     !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 166 |   ObjCMethodDecl *OMD = PD->getGetterMethodDecl(); | 
 | 167 |   assert(OMD && "Invalid call to generate getter (empty method)"); | 
| Fariborz Jahanian | 679a502 | 2009-01-10 21:06:09 +0000 | [diff] [blame] | 168 |   StartObjCMethod(OMD, IMP->getClassInterface()); | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 169 |    | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 170 |   // Determine if we should use an objc_getProperty call for | 
| Fariborz Jahanian | 447d7ae | 2008-12-08 23:56:17 +0000 | [diff] [blame] | 171 |   // this. Non-atomic properties are directly evaluated. | 
 | 172 |   // atomic 'copy' and 'retain' properties are also directly | 
 | 173 |   // evaluated in gc-only mode. | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 174 |   if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 175 |       IsAtomic && | 
| Fariborz Jahanian | 447d7ae | 2008-12-08 23:56:17 +0000 | [diff] [blame] | 176 |       (PD->getSetterKind() == ObjCPropertyDecl::Copy || | 
 | 177 |        PD->getSetterKind() == ObjCPropertyDecl::Retain)) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 178 |     llvm::Value *GetPropertyFn = | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 179 |       CGM.getObjCRuntime().GetPropertyGetFunction(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 180 |  | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 181 |     if (!GetPropertyFn) { | 
 | 182 |       CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); | 
 | 183 |       FinishFunction(); | 
 | 184 |       return; | 
 | 185 |     } | 
 | 186 |  | 
 | 187 |     // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true). | 
 | 188 |     // FIXME: Can't this be simpler? This might even be worse than the | 
 | 189 |     // corresponding gcc code. | 
 | 190 |     CodeGenTypes &Types = CGM.getTypes(); | 
 | 191 |     ValueDecl *Cmd = OMD->getCmdDecl(); | 
 | 192 |     llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); | 
 | 193 |     QualType IdTy = getContext().getObjCIdType(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 194 |     llvm::Value *SelfAsId = | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 195 |       Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); | 
| Fariborz Jahanian | fef30b5 | 2008-12-09 20:23:04 +0000 | [diff] [blame] | 196 |     llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 197 |     llvm::Value *True = | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 198 |       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 199 |     CallArgList Args; | 
 | 200 |     Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy)); | 
 | 201 |     Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); | 
 | 202 |     Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); | 
 | 203 |     Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy)); | 
| Daniel Dunbar | e4be5a6 | 2009-02-03 23:43:59 +0000 | [diff] [blame] | 204 |     // FIXME: We shouldn't need to get the function info here, the | 
 | 205 |     // runtime already should have computed it to build the function. | 
| John McCall | 04a67a6 | 2010-02-05 21:31:56 +0000 | [diff] [blame] | 206 |     RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args, | 
| Rafael Espindola | 264ba48 | 2010-03-30 20:24:48 +0000 | [diff] [blame] | 207 |                                                FunctionType::ExtInfo()), | 
| Anders Carlsson | f3c47c9 | 2009-12-24 19:25:24 +0000 | [diff] [blame] | 208 |                          GetPropertyFn, ReturnValueSlot(), Args); | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 209 |     // We need to fix the type here. Ivars with copy & retain are | 
 | 210 |     // always objects so we don't need to worry about complex or | 
 | 211 |     // aggregates. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 212 |     RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 213 |                                            Types.ConvertType(PD->getType()))); | 
 | 214 |     EmitReturnOfRValue(RV, PD->getType()); | 
 | 215 |   } else { | 
| Fariborz Jahanian | 1b23fe6 | 2010-03-25 21:56:43 +0000 | [diff] [blame] | 216 |     if (Ivar->getType()->isAnyComplexType()) { | 
| Fariborz Jahanian | 97a73cd | 2010-05-06 15:45:36 +0000 | [diff] [blame] | 217 |       LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),  | 
 | 218 |                                     Ivar, 0); | 
| Fariborz Jahanian | 1b23fe6 | 2010-03-25 21:56:43 +0000 | [diff] [blame] | 219 |       ComplexPairTy Pair = LoadComplexFromAddr(LV.getAddress(), | 
 | 220 |                                                LV.isVolatileQualified()); | 
 | 221 |       StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified()); | 
 | 222 |     } | 
 | 223 |     else if (hasAggregateLLVMType(Ivar->getType())) { | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 224 |       bool IsStrong = false; | 
 | 225 |       if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(Ivar->getType()))) | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 226 |           && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect | 
| David Chisnall | 8fac25d | 2010-12-26 22:13:16 +0000 | [diff] [blame] | 227 |           && CGM.getObjCRuntime().GetGetStructFunction()) { | 
| Fariborz Jahanian | 97a73cd | 2010-05-06 15:45:36 +0000 | [diff] [blame] | 228 |         LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),  | 
 | 229 |                                       Ivar, 0); | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 230 |         llvm::Value *GetCopyStructFn = | 
| David Chisnall | 8fac25d | 2010-12-26 22:13:16 +0000 | [diff] [blame] | 231 |           CGM.getObjCRuntime().GetGetStructFunction(); | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 232 |         CodeGenTypes &Types = CGM.getTypes(); | 
 | 233 |         // objc_copyStruct (ReturnValue, &structIvar,  | 
 | 234 |         //                  sizeof (Type of Ivar), isAtomic, false); | 
 | 235 |         CallArgList Args; | 
 | 236 |         RValue RV = RValue::get(Builder.CreateBitCast(ReturnValue, | 
 | 237 |                                     Types.ConvertType(getContext().VoidPtrTy))); | 
 | 238 |         Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); | 
 | 239 |         RV = RValue::get(Builder.CreateBitCast(LV.getAddress(), | 
 | 240 |                                     Types.ConvertType(getContext().VoidPtrTy))); | 
 | 241 |         Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); | 
 | 242 |         // sizeof (Type of Ivar) | 
 | 243 |         uint64_t Size =  getContext().getTypeSize(Ivar->getType()) / 8; | 
 | 244 |         llvm::Value *SizeVal = | 
 | 245 |           llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size); | 
 | 246 |         Args.push_back(std::make_pair(RValue::get(SizeVal), | 
 | 247 |                                       getContext().LongTy)); | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 248 |         llvm::Value *isAtomic = | 
| Fariborz Jahanian | 08adf32 | 2010-04-13 18:43:37 +0000 | [diff] [blame] | 249 |           llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),  | 
 | 250 |                                  IsAtomic ? 1 : 0); | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 251 |         Args.push_back(std::make_pair(RValue::get(isAtomic),  | 
 | 252 |                                       getContext().BoolTy)); | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 253 |         llvm::Value *hasStrong = | 
 | 254 |           llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),  | 
 | 255 |                                  IsStrong ? 1 : 0); | 
 | 256 |         Args.push_back(std::make_pair(RValue::get(hasStrong),  | 
 | 257 |                                       getContext().BoolTy)); | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 258 |         EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, | 
 | 259 |                                        FunctionType::ExtInfo()), | 
 | 260 |                  GetCopyStructFn, ReturnValueSlot(), Args); | 
 | 261 |       } | 
| Fariborz Jahanian | 97a73cd | 2010-05-06 15:45:36 +0000 | [diff] [blame] | 262 |       else { | 
 | 263 |         if (PID->getGetterCXXConstructor()) { | 
 | 264 |           ReturnStmt *Stmt =  | 
 | 265 |             new (getContext()) ReturnStmt(SourceLocation(),  | 
| Douglas Gregor | 5077c38 | 2010-05-15 06:01:05 +0000 | [diff] [blame] | 266 |                                           PID->getGetterCXXConstructor(), | 
 | 267 |                                           0); | 
| Fariborz Jahanian | 97a73cd | 2010-05-06 15:45:36 +0000 | [diff] [blame] | 268 |           EmitReturnStmt(*Stmt); | 
 | 269 |         } | 
 | 270 |         else { | 
 | 271 |           LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),  | 
 | 272 |                                         Ivar, 0); | 
 | 273 |           EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType()); | 
 | 274 |         } | 
 | 275 |       } | 
| Mike Stump | b3589f4 | 2009-07-30 22:28:39 +0000 | [diff] [blame] | 276 |     } else { | 
| Fariborz Jahanian | 97a73cd | 2010-05-06 15:45:36 +0000 | [diff] [blame] | 277 |       LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(),  | 
 | 278 |                                     Ivar, 0); | 
| Fariborz Jahanian | ed1d29d | 2009-03-03 18:49:40 +0000 | [diff] [blame] | 279 |       CodeGenTypes &Types = CGM.getTypes(); | 
 | 280 |       RValue RV = EmitLoadOfLValue(LV, Ivar->getType()); | 
 | 281 |       RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 282 |                        Types.ConvertType(PD->getType()))); | 
| Fariborz Jahanian | ed1d29d | 2009-03-03 18:49:40 +0000 | [diff] [blame] | 283 |       EmitReturnOfRValue(RV, PD->getType()); | 
 | 284 |     } | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 285 |   } | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 286 |  | 
 | 287 |   FinishFunction(); | 
 | 288 | } | 
 | 289 |  | 
 | 290 | /// GenerateObjCSetter - Generate an Objective-C property setter | 
| Steve Naroff | 489034c | 2009-01-10 22:55:25 +0000 | [diff] [blame] | 291 | /// function. The given Decl must be an ObjCImplementationDecl. @synthesize | 
 | 292 | /// is illegal within a category. | 
| Fariborz Jahanian | fef30b5 | 2008-12-09 20:23:04 +0000 | [diff] [blame] | 293 | void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, | 
 | 294 |                                          const ObjCPropertyImplDecl *PID) { | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 295 |   ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 296 |   const ObjCPropertyDecl *PD = PID->getPropertyDecl(); | 
 | 297 |   ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); | 
 | 298 |   assert(OMD && "Invalid call to generate setter (empty method)"); | 
| Fariborz Jahanian | 679a502 | 2009-01-10 21:06:09 +0000 | [diff] [blame] | 299 |   StartObjCMethod(OMD, IMP->getClassInterface()); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 300 |  | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 301 |   bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 302 |   bool IsAtomic = | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 303 |     !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); | 
 | 304 |  | 
 | 305 |   // Determine if we should use an objc_setProperty call for | 
 | 306 |   // this. Properties with 'copy' semantics always use it, as do | 
 | 307 |   // non-atomic properties with 'release' semantics as long as we are | 
 | 308 |   // not in gc-only mode. | 
 | 309 |   if (IsCopy || | 
 | 310 |       (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && | 
 | 311 |        PD->getSetterKind() == ObjCPropertyDecl::Retain)) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 312 |     llvm::Value *SetPropertyFn = | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 313 |       CGM.getObjCRuntime().GetPropertySetFunction(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 314 |  | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 315 |     if (!SetPropertyFn) { | 
 | 316 |       CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); | 
 | 317 |       FinishFunction(); | 
 | 318 |       return; | 
 | 319 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 320 |  | 
 | 321 |     // Emit objc_setProperty((id) self, _cmd, offset, arg, | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 322 |     //                       <is-atomic>, <is-copy>). | 
 | 323 |     // FIXME: Can't this be simpler? This might even be worse than the | 
 | 324 |     // corresponding gcc code. | 
 | 325 |     CodeGenTypes &Types = CGM.getTypes(); | 
 | 326 |     ValueDecl *Cmd = OMD->getCmdDecl(); | 
 | 327 |     llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); | 
 | 328 |     QualType IdTy = getContext().getObjCIdType(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 329 |     llvm::Value *SelfAsId = | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 330 |       Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); | 
| Fariborz Jahanian | fef30b5 | 2008-12-09 20:23:04 +0000 | [diff] [blame] | 331 |     llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); | 
| Chris Lattner | 89951a8 | 2009-02-20 18:43:26 +0000 | [diff] [blame] | 332 |     llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 333 |     llvm::Value *ArgAsId = | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 334 |       Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"), | 
 | 335 |                             Types.ConvertType(IdTy)); | 
 | 336 |     llvm::Value *True = | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 337 |       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 338 |     llvm::Value *False = | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 339 |       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 340 |     CallArgList Args; | 
 | 341 |     Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy)); | 
 | 342 |     Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); | 
 | 343 |     Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); | 
 | 344 |     Args.push_back(std::make_pair(RValue::get(ArgAsId), IdTy)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 345 |     Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False), | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 346 |                                   getContext().BoolTy)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 347 |     Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False), | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 348 |                                   getContext().BoolTy)); | 
| Mike Stump | f5408fe | 2009-05-16 07:57:57 +0000 | [diff] [blame] | 349 |     // FIXME: We shouldn't need to get the function info here, the runtime | 
 | 350 |     // already should have computed it to build the function. | 
| John McCall | 04a67a6 | 2010-02-05 21:31:56 +0000 | [diff] [blame] | 351 |     EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, | 
| Rafael Espindola | 264ba48 | 2010-03-30 20:24:48 +0000 | [diff] [blame] | 352 |                                    FunctionType::ExtInfo()), | 
 | 353 |              SetPropertyFn, | 
| Anders Carlsson | f3c47c9 | 2009-12-24 19:25:24 +0000 | [diff] [blame] | 354 |              ReturnValueSlot(), Args); | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 355 |   } else if (IsAtomic && hasAggregateLLVMType(Ivar->getType()) && | 
 | 356 |              !Ivar->getType()->isAnyComplexType() && | 
 | 357 |              IndirectObjCSetterArg(*CurFnInfo) | 
| David Chisnall | 8fac25d | 2010-12-26 22:13:16 +0000 | [diff] [blame] | 358 |              && CGM.getObjCRuntime().GetSetStructFunction()) { | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 359 |     // objc_copyStruct (&structIvar, &Arg,  | 
 | 360 |     //                  sizeof (struct something), true, false); | 
 | 361 |     llvm::Value *GetCopyStructFn = | 
| David Chisnall | 8fac25d | 2010-12-26 22:13:16 +0000 | [diff] [blame] | 362 |       CGM.getObjCRuntime().GetSetStructFunction(); | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 363 |     CodeGenTypes &Types = CGM.getTypes(); | 
 | 364 |     CallArgList Args; | 
 | 365 |     LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); | 
 | 366 |     RValue RV = RValue::get(Builder.CreateBitCast(LV.getAddress(), | 
 | 367 |                                     Types.ConvertType(getContext().VoidPtrTy))); | 
 | 368 |     Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); | 
 | 369 |     llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; | 
 | 370 |     llvm::Value *ArgAsPtrTy = | 
 | 371 |       Builder.CreateBitCast(Arg, | 
 | 372 |                             Types.ConvertType(getContext().VoidPtrTy)); | 
 | 373 |     RV = RValue::get(ArgAsPtrTy); | 
 | 374 |     Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); | 
 | 375 |     // sizeof (Type of Ivar) | 
 | 376 |     uint64_t Size =  getContext().getTypeSize(Ivar->getType()) / 8; | 
 | 377 |     llvm::Value *SizeVal = | 
 | 378 |       llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size); | 
 | 379 |     Args.push_back(std::make_pair(RValue::get(SizeVal), | 
 | 380 |                                   getContext().LongTy)); | 
 | 381 |     llvm::Value *True = | 
 | 382 |       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); | 
 | 383 |     Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy)); | 
 | 384 |     llvm::Value *False = | 
 | 385 |       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); | 
 | 386 |     Args.push_back(std::make_pair(RValue::get(False), getContext().BoolTy)); | 
 | 387 |     EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, | 
 | 388 |                                    FunctionType::ExtInfo()), | 
 | 389 |              GetCopyStructFn, ReturnValueSlot(), Args); | 
| Fariborz Jahanian | 97a73cd | 2010-05-06 15:45:36 +0000 | [diff] [blame] | 390 |   } else if (PID->getSetterCXXAssignment()) { | 
| John McCall | 2a41637 | 2010-12-05 02:00:02 +0000 | [diff] [blame] | 391 |     EmitIgnoredExpr(PID->getSetterCXXAssignment()); | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 392 |   } else { | 
| Daniel Dunbar | 45e8423 | 2009-10-27 19:21:30 +0000 | [diff] [blame] | 393 |     // FIXME: Find a clean way to avoid AST node creation. | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 394 |     SourceLocation Loc = PD->getLocation(); | 
 | 395 |     ValueDecl *Self = OMD->getSelfDecl(); | 
 | 396 |     ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); | 
| John McCall | f89e55a | 2010-11-18 06:31:45 +0000 | [diff] [blame] | 397 |     DeclRefExpr Base(Self, Self->getType(), VK_RValue, Loc); | 
| Chris Lattner | 89951a8 | 2009-02-20 18:43:26 +0000 | [diff] [blame] | 398 |     ParmVarDecl *ArgDecl = *OMD->param_begin(); | 
| John McCall | f89e55a | 2010-11-18 06:31:45 +0000 | [diff] [blame] | 399 |     DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), VK_LValue, Loc); | 
| Daniel Dunbar | 45e8423 | 2009-10-27 19:21:30 +0000 | [diff] [blame] | 400 |     ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true); | 
 | 401 |      | 
 | 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())) { | 
| John McCall | f871d0c | 2010-08-07 06:22:56 +0000 | [diff] [blame] | 406 |       ImplicitCastExpr ArgCasted(ImplicitCastExpr::OnStack, | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 407 |                                  Ivar->getType(), CK_BitCast, &Arg, | 
| John McCall | 5baba9d | 2010-08-25 10:28:54 +0000 | [diff] [blame] | 408 |                                  VK_RValue); | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 409 |       BinaryOperator Assign(&IvarRef, &ArgCasted, BO_Assign, | 
| John McCall | f89e55a | 2010-11-18 06:31:45 +0000 | [diff] [blame] | 410 |                             Ivar->getType(), VK_RValue, OK_Ordinary, Loc); | 
| Daniel Dunbar | 45e8423 | 2009-10-27 19:21:30 +0000 | [diff] [blame] | 411 |       EmitStmt(&Assign); | 
 | 412 |     } else { | 
| John McCall | 2de56d1 | 2010-08-25 11:45:40 +0000 | [diff] [blame] | 413 |       BinaryOperator Assign(&IvarRef, &Arg, BO_Assign, | 
| John McCall | f89e55a | 2010-11-18 06:31:45 +0000 | [diff] [blame] | 414 |                             Ivar->getType(), VK_RValue, OK_Ordinary, Loc); | 
| Daniel Dunbar | 45e8423 | 2009-10-27 19:21:30 +0000 | [diff] [blame] | 415 |       EmitStmt(&Assign); | 
 | 416 |     } | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 417 |   } | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 418 |  | 
 | 419 |   FinishFunction(); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 420 | } | 
 | 421 |  | 
| Fariborz Jahanian | 109dfc6 | 2010-04-28 21:28:56 +0000 | [diff] [blame] | 422 | void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, | 
 | 423 |                                                  ObjCMethodDecl *MD, | 
 | 424 |                                                  bool ctor) { | 
| Sean Hunt | cbb6748 | 2011-01-08 20:30:50 +0000 | [diff] [blame] | 425 |   llvm::SmallVector<CXXCtorInitializer *, 8> IvarInitializers; | 
| Fariborz Jahanian | 109dfc6 | 2010-04-28 21:28:56 +0000 | [diff] [blame] | 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) { | 
| Sean Hunt | cbb6748 | 2011-01-08 20:30:50 +0000 | [diff] [blame] | 430 |     CXXCtorInitializer *Member = (*B); | 
| Fariborz Jahanian | 109dfc6 | 2010-04-28 21:28:56 +0000 | [diff] [blame] | 431 |     IvarInitializers.push_back(Member); | 
 | 432 |   } | 
 | 433 |   if (ctor) { | 
 | 434 |     for (unsigned I = 0, E = IvarInitializers.size(); I != E; ++I) { | 
| Sean Hunt | cbb6748 | 2011-01-08 20:30:50 +0000 | [diff] [blame] | 435 |       CXXCtorInitializer *IvarInit = IvarInitializers[I]; | 
| Francois Pichet | 00eb3f9 | 2010-12-04 09:14:42 +0000 | [diff] [blame] | 436 |       FieldDecl *Field = IvarInit->getAnyMember(); | 
| Fariborz Jahanian | 109dfc6 | 2010-04-28 21:28:56 +0000 | [diff] [blame] | 437 |       QualType FieldType = Field->getType(); | 
| Fariborz Jahanian | 109dfc6 | 2010-04-28 21:28:56 +0000 | [diff] [blame] | 438 |       ObjCIvarDecl  *Ivar = cast<ObjCIvarDecl>(Field); | 
| Fariborz Jahanian | 9b4d4fc | 2010-04-28 22:30:33 +0000 | [diff] [blame] | 439 |       LValue LV = EmitLValueForIvar(TypeOfSelfObject(),  | 
 | 440 |                                     LoadObjCSelf(), Ivar, 0); | 
| John McCall | 558d2ab | 2010-09-15 10:14:12 +0000 | [diff] [blame] | 441 |       EmitAggExpr(IvarInit->getInit(), AggValueSlot::forLValue(LV, true)); | 
| Fariborz Jahanian | 109dfc6 | 2010-04-28 21:28:56 +0000 | [diff] [blame] | 442 |     } | 
 | 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); | 
| Chandler Carruth | bc397cf | 2010-05-06 00:20:39 +0000 | [diff] [blame] | 449 |   } else { | 
| Fariborz Jahanian | 109dfc6 | 2010-04-28 21:28:56 +0000 | [diff] [blame] | 450 |     // dtor | 
 | 451 |     for (size_t i = IvarInitializers.size(); i > 0; --i) { | 
| Francois Pichet | 00eb3f9 | 2010-12-04 09:14:42 +0000 | [diff] [blame] | 452 |       FieldDecl *Field = IvarInitializers[i - 1]->getAnyMember(); | 
| Fariborz Jahanian | 109dfc6 | 2010-04-28 21:28:56 +0000 | [diff] [blame] | 453 |       QualType FieldType = Field->getType(); | 
| Fariborz Jahanian | 9b4d4fc | 2010-04-28 22:30:33 +0000 | [diff] [blame] | 454 |       const ConstantArrayType *Array =  | 
 | 455 |         getContext().getAsConstantArrayType(FieldType); | 
 | 456 |       if (Array) | 
 | 457 |         FieldType = getContext().getBaseElementType(FieldType); | 
 | 458 |        | 
| Fariborz Jahanian | 109dfc6 | 2010-04-28 21:28:56 +0000 | [diff] [blame] | 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()); | 
| Douglas Gregor | 1d110e0 | 2010-07-01 14:13:13 +0000 | [diff] [blame] | 464 |       CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(); | 
| Chandler Carruth | bc397cf | 2010-05-06 00:20:39 +0000 | [diff] [blame] | 465 |       if (!Dtor->isTrivial()) { | 
| Fariborz Jahanian | 8b688ed | 2010-05-04 19:29:32 +0000 | [diff] [blame] | 466 |         if (Array) { | 
 | 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, | 
 | 472 |                                     Array, BaseAddrPtr); | 
| Chandler Carruth | bc397cf | 2010-05-06 00:20:39 +0000 | [diff] [blame] | 473 |         } else { | 
| Fariborz Jahanian | 8b688ed | 2010-05-04 19:29:32 +0000 | [diff] [blame] | 474 |           EmitCXXDestructorCall(Dtor, | 
 | 475 |                                 Dtor_Complete, /*ForVirtualBase=*/false, | 
 | 476 |                                 LV.getAddress()); | 
| Chandler Carruth | bc397cf | 2010-05-06 00:20:39 +0000 | [diff] [blame] | 477 |         } | 
 | 478 |       } | 
 | 479 |     } | 
| Fariborz Jahanian | 109dfc6 | 2010-04-28 21:28:56 +0000 | [diff] [blame] | 480 |   } | 
 | 481 |   FinishFunction(); | 
 | 482 | } | 
 | 483 |  | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 484 | bool CodeGenFunction::IndirectObjCSetterArg(const CGFunctionInfo &FI) { | 
 | 485 |   CGFunctionInfo::const_arg_iterator it = FI.arg_begin(); | 
 | 486 |   it++; it++; | 
 | 487 |   const ABIArgInfo &AI = it->info; | 
 | 488 |   // FIXME. Is this sufficient check? | 
 | 489 |   return (AI.getKind() == ABIArgInfo::Indirect); | 
 | 490 | } | 
 | 491 |  | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 492 | bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) { | 
 | 493 |   if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC) | 
 | 494 |     return false; | 
 | 495 |   if (const RecordType *FDTTy = Ty.getTypePtr()->getAs<RecordType>()) | 
 | 496 |     return FDTTy->getDecl()->hasObjectMember(); | 
 | 497 |   return false; | 
 | 498 | } | 
 | 499 |  | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 500 | llvm::Value *CodeGenFunction::LoadObjCSelf() { | 
| Daniel Dunbar | b7ec246 | 2008-08-16 03:19:19 +0000 | [diff] [blame] | 501 |   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); | 
 | 502 |   return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self"); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 503 | } | 
 | 504 |  | 
| Fariborz Jahanian | 45012a7 | 2009-02-03 00:09:52 +0000 | [diff] [blame] | 505 | QualType CodeGenFunction::TypeOfSelfObject() { | 
 | 506 |   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); | 
 | 507 |   ImplicitParamDecl *selfDecl = OMD->getSelfDecl(); | 
| Steve Naroff | 14108da | 2009-07-10 23:34:53 +0000 | [diff] [blame] | 508 |   const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>( | 
 | 509 |     getContext().getCanonicalType(selfDecl->getType())); | 
| Fariborz Jahanian | 45012a7 | 2009-02-03 00:09:52 +0000 | [diff] [blame] | 510 |   return PTy->getPointeeType(); | 
 | 511 | } | 
 | 512 |  | 
| John McCall | e68b984 | 2010-12-04 03:11:00 +0000 | [diff] [blame] | 513 | LValue | 
 | 514 | CodeGenFunction::EmitObjCPropertyRefLValue(const ObjCPropertyRefExpr *E) { | 
 | 515 |   // This is a special l-value that just issues sends when we load or | 
 | 516 |   // store through it. | 
 | 517 |  | 
 | 518 |   // For certain base kinds, we need to emit the base immediately. | 
 | 519 |   llvm::Value *Base; | 
 | 520 |   if (E->isSuperReceiver()) | 
 | 521 |     Base = LoadObjCSelf(); | 
 | 522 |   else if (E->isClassReceiver()) | 
 | 523 |     Base = CGM.getObjCRuntime().GetClass(Builder, E->getClassReceiver()); | 
 | 524 |   else | 
 | 525 |     Base = EmitScalarExpr(E->getBase()); | 
 | 526 |   return LValue::MakePropertyRef(E, Base); | 
 | 527 | } | 
 | 528 |  | 
 | 529 | static RValue GenerateMessageSendSuper(CodeGenFunction &CGF, | 
 | 530 |                                        ReturnValueSlot Return, | 
 | 531 |                                        QualType ResultType, | 
 | 532 |                                        Selector S, | 
 | 533 |                                        llvm::Value *Receiver, | 
 | 534 |                                        const CallArgList &CallArgs) { | 
 | 535 |   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CGF.CurFuncDecl); | 
| Fariborz Jahanian | f469557 | 2009-03-20 19:18:21 +0000 | [diff] [blame] | 536 |   bool isClassMessage = OMD->isClassMethod(); | 
 | 537 |   bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); | 
| John McCall | e68b984 | 2010-12-04 03:11:00 +0000 | [diff] [blame] | 538 |   return CGF.CGM.getObjCRuntime() | 
 | 539 |                 .GenerateMessageSendSuper(CGF, Return, ResultType, | 
 | 540 |                                           S, OMD->getClassInterface(), | 
 | 541 |                                           isCategoryImpl, Receiver, | 
 | 542 |                                           isClassMessage, CallArgs); | 
| Fariborz Jahanian | f469557 | 2009-03-20 19:18:21 +0000 | [diff] [blame] | 543 | } | 
 | 544 |  | 
| John McCall | 119a1c6 | 2010-12-04 02:32:38 +0000 | [diff] [blame] | 545 | RValue CodeGenFunction::EmitLoadOfPropertyRefLValue(LValue LV, | 
 | 546 |                                                     ReturnValueSlot Return) { | 
 | 547 |   const ObjCPropertyRefExpr *E = LV.getPropertyRefExpr(); | 
| John McCall | 12f78a6 | 2010-12-02 01:19:52 +0000 | [diff] [blame] | 548 |   QualType ResultType; | 
 | 549 |   Selector S; | 
 | 550 |   if (E->isExplicitProperty()) { | 
 | 551 |     const ObjCPropertyDecl *Property = E->getExplicitProperty(); | 
 | 552 |     S = Property->getGetterName(); | 
 | 553 |     ResultType = E->getType(); | 
| Mike Stump | b3589f4 | 2009-07-30 22:28:39 +0000 | [diff] [blame] | 554 |   } else { | 
| John McCall | 12f78a6 | 2010-12-02 01:19:52 +0000 | [diff] [blame] | 555 |     const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter(); | 
 | 556 |     S = Getter->getSelector(); | 
 | 557 |     ResultType = Getter->getResultType(); // with reference! | 
| Fariborz Jahanian | 43f4470 | 2008-11-22 22:30:21 +0000 | [diff] [blame] | 558 |   } | 
| John McCall | 12f78a6 | 2010-12-02 01:19:52 +0000 | [diff] [blame] | 559 |  | 
| John McCall | 119a1c6 | 2010-12-04 02:32:38 +0000 | [diff] [blame] | 560 |   llvm::Value *Receiver = LV.getPropertyRefBaseAddr(); | 
| John McCall | e68b984 | 2010-12-04 03:11:00 +0000 | [diff] [blame] | 561 |  | 
 | 562 |   // Accesses to 'super' follow a different code path. | 
 | 563 |   if (E->isSuperReceiver()) | 
 | 564 |     return GenerateMessageSendSuper(*this, Return, ResultType, | 
 | 565 |                                     S, Receiver, CallArgList()); | 
 | 566 |  | 
| John McCall | 119a1c6 | 2010-12-04 02:32:38 +0000 | [diff] [blame] | 567 |   const ObjCInterfaceDecl *ReceiverClass | 
 | 568 |     = (E->isClassReceiver() ? E->getClassReceiver() : 0); | 
| John McCall | 12f78a6 | 2010-12-02 01:19:52 +0000 | [diff] [blame] | 569 |   return CGM.getObjCRuntime(). | 
 | 570 |              GenerateMessageSend(*this, Return, ResultType, S, | 
 | 571 |                                  Receiver, CallArgList(), ReceiverClass); | 
| Daniel Dunbar | 9c3fc70 | 2008-08-27 06:57:25 +0000 | [diff] [blame] | 572 | } | 
 | 573 |  | 
| John McCall | 119a1c6 | 2010-12-04 02:32:38 +0000 | [diff] [blame] | 574 | void CodeGenFunction::EmitStoreThroughPropertyRefLValue(RValue Src, | 
 | 575 |                                                         LValue Dst) { | 
 | 576 |   const ObjCPropertyRefExpr *E = Dst.getPropertyRefExpr(); | 
| John McCall | 12f78a6 | 2010-12-02 01:19:52 +0000 | [diff] [blame] | 577 |   Selector S = E->getSetterSelector(); | 
 | 578 |   QualType ArgType; | 
 | 579 |   if (E->isImplicitProperty()) { | 
 | 580 |     const ObjCMethodDecl *Setter = E->getImplicitPropertySetter(); | 
 | 581 |     ObjCMethodDecl::param_iterator P = Setter->param_begin();  | 
 | 582 |     ArgType = (*P)->getType(); | 
 | 583 |   } else { | 
 | 584 |     ArgType = E->getType(); | 
 | 585 |   } | 
 | 586 |  | 
| John McCall | e68b984 | 2010-12-04 03:11:00 +0000 | [diff] [blame] | 587 |   CallArgList Args; | 
 | 588 |   Args.push_back(std::make_pair(Src, ArgType)); | 
 | 589 |  | 
 | 590 |   llvm::Value *Receiver = Dst.getPropertyRefBaseAddr(); | 
 | 591 |   QualType ResultType = getContext().VoidTy; | 
 | 592 |  | 
| John McCall | 12f78a6 | 2010-12-02 01:19:52 +0000 | [diff] [blame] | 593 |   if (E->isSuperReceiver()) { | 
| John McCall | e68b984 | 2010-12-04 03:11:00 +0000 | [diff] [blame] | 594 |     GenerateMessageSendSuper(*this, ReturnValueSlot(), | 
 | 595 |                              ResultType, S, Receiver, Args); | 
| John McCall | 12f78a6 | 2010-12-02 01:19:52 +0000 | [diff] [blame] | 596 |     return; | 
 | 597 |   } | 
 | 598 |  | 
| John McCall | 119a1c6 | 2010-12-04 02:32:38 +0000 | [diff] [blame] | 599 |   const ObjCInterfaceDecl *ReceiverClass | 
 | 600 |     = (E->isClassReceiver() ? E->getClassReceiver() : 0); | 
| John McCall | 12f78a6 | 2010-12-02 01:19:52 +0000 | [diff] [blame] | 601 |  | 
| John McCall | 12f78a6 | 2010-12-02 01:19:52 +0000 | [diff] [blame] | 602 |   CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), | 
| John McCall | e68b984 | 2010-12-04 03:11:00 +0000 | [diff] [blame] | 603 |                                            ResultType, S, Receiver, Args, | 
 | 604 |                                            ReceiverClass); | 
| Daniel Dunbar | 85c59ed | 2008-08-29 08:11:39 +0000 | [diff] [blame] | 605 | } | 
 | 606 |  | 
| Chris Lattner | 74391b4 | 2009-03-22 21:03:39 +0000 | [diff] [blame] | 607 | void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 608 |   llvm::Constant *EnumerationMutationFn = | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 609 |     CGM.getObjCRuntime().EnumerationMutationFunction(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 610 |  | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 611 |   if (!EnumerationMutationFn) { | 
 | 612 |     CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime"); | 
 | 613 |     return; | 
 | 614 |   } | 
 | 615 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 616 |   JumpDest LoopEnd = getJumpDestInCurrentScope("forcoll.end"); | 
 | 617 |   JumpDest AfterBody = getJumpDestInCurrentScope("forcoll.next"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 618 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 619 |   // Fast enumeration state. | 
 | 620 |   QualType StateTy = getContext().getObjCFastEnumerationStateType(); | 
| Daniel Dunbar | 195337d | 2010-02-09 02:48:28 +0000 | [diff] [blame] | 621 |   llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr"); | 
| Anders Carlsson | 1884eb0 | 2010-05-22 17:35:42 +0000 | [diff] [blame] | 622 |   EmitNullInitialization(StatePtr, StateTy); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 623 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 624 |   // Number of elements in the items array. | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 625 |   static const unsigned NumItems = 16; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 626 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 627 |   // Fetch the countByEnumeratingWithState:objects:count: selector. | 
| Benjamin Kramer | ad46886 | 2010-03-30 11:36:44 +0000 | [diff] [blame] | 628 |   IdentifierInfo *II[] = { | 
 | 629 |     &CGM.getContext().Idents.get("countByEnumeratingWithState"), | 
 | 630 |     &CGM.getContext().Idents.get("objects"), | 
 | 631 |     &CGM.getContext().Idents.get("count") | 
 | 632 |   }; | 
 | 633 |   Selector FastEnumSel = | 
 | 634 |     CGM.getContext().Selectors.getSelector(llvm::array_lengthof(II), &II[0]); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 635 |  | 
 | 636 |   QualType ItemsTy = | 
 | 637 |     getContext().getConstantArrayType(getContext().getObjCIdType(), | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 638 |                                       llvm::APInt(32, NumItems), | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 639 |                                       ArrayType::Normal, 0); | 
| Daniel Dunbar | 195337d | 2010-02-09 02:48:28 +0000 | [diff] [blame] | 640 |   llvm::Value *ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 641 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 642 |   // Emit the collection pointer. | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 643 |   llvm::Value *Collection = EmitScalarExpr(S.getCollection()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 644 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 645 |   // Send it our message: | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 646 |   CallArgList Args; | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 647 |  | 
 | 648 |   // The first argument is a temporary of the enumeration-state type. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 649 |   Args.push_back(std::make_pair(RValue::get(StatePtr), | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 650 |                                 getContext().getPointerType(StateTy))); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 651 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 652 |   // The second argument is a temporary array with space for NumItems | 
 | 653 |   // pointers.  We'll actually be loading elements from the array | 
 | 654 |   // pointer written into the control state; this buffer is so that | 
 | 655 |   // collections that *aren't* backed by arrays can still queue up | 
 | 656 |   // batches of elements. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 657 |   Args.push_back(std::make_pair(RValue::get(ItemsPtr), | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 658 |                                 getContext().getPointerType(ItemsTy))); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 659 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 660 |   // The third argument is the capacity of that temporary array. | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 661 |   const llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy); | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 662 |   llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 663 |   Args.push_back(std::make_pair(RValue::get(Count), | 
| Daniel Dunbar | 46f45b9 | 2008-09-09 01:06:48 +0000 | [diff] [blame] | 664 |                                 getContext().UnsignedLongTy)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 665 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 666 |   // Start the enumeration. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 667 |   RValue CountRV = | 
| John McCall | ef072fd | 2010-05-22 01:48:05 +0000 | [diff] [blame] | 668 |     CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 669 |                                              getContext().UnsignedLongTy, | 
 | 670 |                                              FastEnumSel, | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame] | 671 |                                              Collection, Args); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 672 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 673 |   // The initial number of objects that were returned in the buffer. | 
 | 674 |   llvm::Value *initialBufferLimit = CountRV.getScalarVal(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 675 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 676 |   llvm::BasicBlock *EmptyBB = createBasicBlock("forcoll.empty"); | 
 | 677 |   llvm::BasicBlock *LoopInitBB = createBasicBlock("forcoll.loopinit"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 678 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 679 |   llvm::Value *zero = llvm::Constant::getNullValue(UnsignedLongLTy); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 680 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 681 |   // If the limit pointer was zero to begin with, the collection is | 
 | 682 |   // empty; skip all this. | 
 | 683 |   Builder.CreateCondBr(Builder.CreateICmpEQ(initialBufferLimit, zero, "iszero"), | 
 | 684 |                        EmptyBB, LoopInitBB); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 685 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 686 |   // Otherwise, initialize the loop. | 
 | 687 |   EmitBlock(LoopInitBB); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 688 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 689 |   // Save the initial mutations value.  This is the value at an | 
 | 690 |   // address that was written into the state object by | 
 | 691 |   // countByEnumeratingWithState:objects:count:. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 692 |   llvm::Value *StateMutationsPtrPtr = | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 693 |     Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 694 |   llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 695 |                                                       "mutationsptr"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 696 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 697 |   llvm::Value *initialMutations = | 
 | 698 |     Builder.CreateLoad(StateMutationsPtr, "forcoll.initial-mutations"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 699 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 700 |   // Start looping.  This is the point we return to whenever we have a | 
 | 701 |   // fresh, non-empty batch of objects. | 
 | 702 |   llvm::BasicBlock *LoopBodyBB = createBasicBlock("forcoll.loopbody"); | 
 | 703 |   EmitBlock(LoopBodyBB); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 704 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 705 |   // The current index into the buffer. | 
 | 706 |   llvm::PHINode *index = Builder.CreatePHI(UnsignedLongLTy, "forcoll.index"); | 
 | 707 |   index->addIncoming(zero, LoopInitBB); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 708 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 709 |   // The current buffer size. | 
 | 710 |   llvm::PHINode *count = Builder.CreatePHI(UnsignedLongLTy, "forcoll.count"); | 
 | 711 |   count->addIncoming(initialBufferLimit, LoopInitBB); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 712 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 713 |   // Check whether the mutations value has changed from where it was | 
 | 714 |   // at start.  StateMutationsPtr should actually be invariant between | 
 | 715 |   // refreshes. | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 716 |   StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 717 |   llvm::Value *currentMutations | 
 | 718 |     = Builder.CreateLoad(StateMutationsPtr, "statemutations"); | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 719 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 720 |   llvm::BasicBlock *WasMutatedBB = createBasicBlock("forcoll.mutated"); | 
 | 721 |   llvm::BasicBlock *WasNotMutatedBB = createBasicBlock("forcool.notmutated"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 722 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 723 |   Builder.CreateCondBr(Builder.CreateICmpEQ(currentMutations, initialMutations), | 
 | 724 |                        WasNotMutatedBB, WasMutatedBB); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 725 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 726 |   // If so, call the enumeration-mutation function. | 
 | 727 |   EmitBlock(WasMutatedBB); | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 728 |   llvm::Value *V = | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 729 |     Builder.CreateBitCast(Collection, | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 730 |                           ConvertType(getContext().getObjCIdType()), | 
 | 731 |                           "tmp"); | 
| Daniel Dunbar | 2b2105e | 2009-02-03 23:55:40 +0000 | [diff] [blame] | 732 |   CallArgList Args2; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 733 |   Args2.push_back(std::make_pair(RValue::get(V), | 
| Daniel Dunbar | 2b2105e | 2009-02-03 23:55:40 +0000 | [diff] [blame] | 734 |                                 getContext().getObjCIdType())); | 
| Mike Stump | f5408fe | 2009-05-16 07:57:57 +0000 | [diff] [blame] | 735 |   // FIXME: We shouldn't need to get the function info here, the runtime already | 
 | 736 |   // should have computed it to build the function. | 
| John McCall | 04a67a6 | 2010-02-05 21:31:56 +0000 | [diff] [blame] | 737 |   EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2, | 
| Rafael Espindola | 264ba48 | 2010-03-30 20:24:48 +0000 | [diff] [blame] | 738 |                                           FunctionType::ExtInfo()), | 
| Anders Carlsson | f3c47c9 | 2009-12-24 19:25:24 +0000 | [diff] [blame] | 739 |            EnumerationMutationFn, ReturnValueSlot(), Args2); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 740 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 741 |   // Otherwise, or if the mutation function returns, just continue. | 
 | 742 |   EmitBlock(WasNotMutatedBB); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 743 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 744 |   // Initialize the element variable. | 
 | 745 |   RunCleanupsScope elementVariableScope(*this); | 
 | 746 |   bool elementIsDecl; | 
 | 747 |   LValue elementLValue; | 
 | 748 |   QualType elementType; | 
 | 749 |   if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) { | 
 | 750 |     EmitStmt(SD); | 
 | 751 |     const VarDecl* D = cast<VarDecl>(SD->getSingleDecl()); | 
 | 752 |  | 
 | 753 |     DeclRefExpr tempDRE(const_cast<VarDecl*>(D), D->getType(), | 
 | 754 |                         VK_LValue, SourceLocation()); | 
 | 755 |     elementLValue = EmitLValue(&tempDRE); | 
 | 756 |     elementType = D->getType(); | 
 | 757 |     elementIsDecl = true; | 
 | 758 |   } else { | 
 | 759 |     elementLValue = LValue(); // suppress warning | 
 | 760 |     elementType = cast<Expr>(S.getElement())->getType(); | 
 | 761 |     elementIsDecl = false; | 
 | 762 |   } | 
 | 763 |   const llvm::Type *convertedElementType = ConvertType(elementType); | 
 | 764 |  | 
 | 765 |   // Fetch the buffer out of the enumeration state. | 
 | 766 |   // TODO: this pointer should actually be invariant between | 
 | 767 |   // refreshes, which would help us do certain loop optimizations. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 768 |   llvm::Value *StateItemsPtr = | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 769 |     Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr"); | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 770 |   llvm::Value *EnumStateItems = | 
 | 771 |     Builder.CreateLoad(StateItemsPtr, "stateitems"); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 772 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 773 |   // Fetch the value at the current index from the buffer. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 774 |   llvm::Value *CurrentItemPtr = | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 775 |     Builder.CreateGEP(EnumStateItems, index, "currentitem.ptr"); | 
 | 776 |   llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 777 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 778 |   // Cast that value to the right type. | 
 | 779 |   CurrentItem = Builder.CreateBitCast(CurrentItem, convertedElementType, | 
 | 780 |                                       "currentitem"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 781 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 782 |   // Make sure we have an l-value.  Yes, this gets evaluated every | 
 | 783 |   // time through the loop. | 
 | 784 |   if (!elementIsDecl) | 
 | 785 |     elementLValue = EmitLValue(cast<Expr>(S.getElement())); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 786 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 787 |   EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, elementType); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 788 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 789 |   // Perform the loop body, setting up break and continue labels. | 
| Anders Carlsson | e4b6d34 | 2009-02-10 05:52:02 +0000 | [diff] [blame] | 790 |   BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody)); | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 791 |   { | 
 | 792 |     RunCleanupsScope Scope(*this); | 
 | 793 |     EmitStmt(S.getBody()); | 
 | 794 |   } | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 795 |   BreakContinueStack.pop_back(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 796 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 797 |   // Destroy the element variable now. | 
 | 798 |   elementVariableScope.ForceCleanup(); | 
 | 799 |  | 
 | 800 |   // Check whether there are more elements. | 
| John McCall | ff8e115 | 2010-07-23 21:56:41 +0000 | [diff] [blame] | 801 |   EmitBlock(AfterBody.getBlock()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 802 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 803 |   llvm::BasicBlock *FetchMoreBB = createBasicBlock("forcoll.refetch"); | 
| Fariborz Jahanian | f0906c4 | 2009-01-06 18:56:31 +0000 | [diff] [blame] | 804 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 805 |   // First we check in the local buffer. | 
 | 806 |   llvm::Value *indexPlusOne | 
 | 807 |     = Builder.CreateAdd(index, llvm::ConstantInt::get(UnsignedLongLTy, 1)); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 808 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 809 |   // If we haven't overrun the buffer yet, we can continue. | 
 | 810 |   Builder.CreateCondBr(Builder.CreateICmpULT(indexPlusOne, count), | 
 | 811 |                        LoopBodyBB, FetchMoreBB); | 
 | 812 |  | 
 | 813 |   index->addIncoming(indexPlusOne, AfterBody.getBlock()); | 
 | 814 |   count->addIncoming(count, AfterBody.getBlock()); | 
 | 815 |  | 
 | 816 |   // Otherwise, we have to fetch more elements. | 
 | 817 |   EmitBlock(FetchMoreBB); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 818 |  | 
 | 819 |   CountRV = | 
| John McCall | ef072fd | 2010-05-22 01:48:05 +0000 | [diff] [blame] | 820 |     CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(), | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 821 |                                              getContext().UnsignedLongTy, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 822 |                                              FastEnumSel, | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame] | 823 |                                              Collection, Args); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 824 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 825 |   // If we got a zero count, we're done. | 
 | 826 |   llvm::Value *refetchCount = CountRV.getScalarVal(); | 
 | 827 |  | 
 | 828 |   // (note that the message send might split FetchMoreBB) | 
 | 829 |   index->addIncoming(zero, Builder.GetInsertBlock()); | 
 | 830 |   count->addIncoming(refetchCount, Builder.GetInsertBlock()); | 
 | 831 |  | 
 | 832 |   Builder.CreateCondBr(Builder.CreateICmpEQ(refetchCount, zero), | 
 | 833 |                        EmptyBB, LoopBodyBB); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 834 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 835 |   // No more elements. | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 836 |   EmitBlock(EmptyBB); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 837 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 838 |   if (!elementIsDecl) { | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 839 |     // If the element was not a declaration, set it to be null. | 
 | 840 |  | 
| John McCall | d88687f | 2011-01-07 01:49:06 +0000 | [diff] [blame] | 841 |     llvm::Value *null = llvm::Constant::getNullValue(convertedElementType); | 
 | 842 |     elementLValue = EmitLValue(cast<Expr>(S.getElement())); | 
 | 843 |     EmitStoreThroughLValue(RValue::get(null), elementLValue, elementType); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 844 |   } | 
 | 845 |  | 
| John McCall | ff8e115 | 2010-07-23 21:56:41 +0000 | [diff] [blame] | 846 |   EmitBlock(LoopEnd.getBlock()); | 
| Anders Carlsson | 3d8400d | 2008-08-30 19:51:14 +0000 | [diff] [blame] | 847 | } | 
 | 848 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 849 | void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) { | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 850 |   CGM.getObjCRuntime().EmitTryStmt(*this, S); | 
| Anders Carlsson | 64d5d6c | 2008-09-09 10:04:29 +0000 | [diff] [blame] | 851 | } | 
 | 852 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 853 | void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) { | 
| Anders Carlsson | 64d5d6c | 2008-09-09 10:04:29 +0000 | [diff] [blame] | 854 |   CGM.getObjCRuntime().EmitThrowStmt(*this, S); | 
 | 855 | } | 
 | 856 |  | 
| Chris Lattner | 10cac6f | 2008-11-15 21:26:17 +0000 | [diff] [blame] | 857 | void CodeGenFunction::EmitObjCAtSynchronizedStmt( | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 858 |                                               const ObjCAtSynchronizedStmt &S) { | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 859 |   CGM.getObjCRuntime().EmitSynchronizedStmt(*this, S); | 
| Chris Lattner | 10cac6f | 2008-11-15 21:26:17 +0000 | [diff] [blame] | 860 | } | 
 | 861 |  | 
| Ted Kremenek | 2979ec7 | 2008-04-09 15:51:31 +0000 | [diff] [blame] | 862 | CGObjCRuntime::~CGObjCRuntime() {} | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 863 |  | 
 | 864 |  |