| 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 |  | 
| Daniel Dunbar | 8f2926b | 2008-08-23 03:46:30 +0000 | [diff] [blame] | 50 | RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 51 |   // Only the lookup mechanism and first two arguments of the method | 
 | 52 |   // implementation vary between runtimes.  We can get the receiver and | 
 | 53 |   // arguments in generic code. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 54 |  | 
| Daniel Dunbar | 208ff5e | 2008-08-11 18:12:00 +0000 | [diff] [blame] | 55 |   CGObjCRuntime &Runtime = CGM.getObjCRuntime(); | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 56 |   bool isSuperMessage = false; | 
| Daniel Dunbar | f56f191 | 2008-08-25 08:19:24 +0000 | [diff] [blame] | 57 |   bool isClassMessage = false; | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame^] | 58 |   ObjCInterfaceDecl *OID = 0; | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 59 |   // Find the receiver | 
| Daniel Dunbar | 0b647a6 | 2010-04-22 03:17:06 +0000 | [diff] [blame] | 60 |   llvm::Value *Receiver = 0; | 
| Douglas Gregor | 04badcf | 2010-04-21 00:45:42 +0000 | [diff] [blame] | 61 |   switch (E->getReceiverKind()) { | 
 | 62 |   case ObjCMessageExpr::Instance: | 
 | 63 |     Receiver = EmitScalarExpr(E->getInstanceReceiver()); | 
 | 64 |     break; | 
| Daniel Dunbar | ddb2a3d | 2008-08-16 00:25:02 +0000 | [diff] [blame] | 65 |  | 
| Douglas Gregor | 04badcf | 2010-04-21 00:45:42 +0000 | [diff] [blame] | 66 |   case ObjCMessageExpr::Class: { | 
 | 67 |     const ObjCInterfaceType *IFace | 
 | 68 |       = E->getClassReceiver()->getAs<ObjCInterfaceType>(); | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame^] | 69 |     OID = IFace->getDecl(); | 
| Douglas Gregor | 04badcf | 2010-04-21 00:45:42 +0000 | [diff] [blame] | 70 |     assert(IFace && "Invalid Objective-C class message send"); | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame^] | 71 |     Receiver = Runtime.GetClass(Builder, OID); | 
| Daniel Dunbar | f56f191 | 2008-08-25 08:19:24 +0000 | [diff] [blame] | 72 |     isClassMessage = true; | 
| Douglas Gregor | 04badcf | 2010-04-21 00:45:42 +0000 | [diff] [blame] | 73 |     break; | 
 | 74 |   } | 
 | 75 |  | 
 | 76 |   case ObjCMessageExpr::SuperInstance: | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 77 |     Receiver = LoadObjCSelf(); | 
| Douglas Gregor | 04badcf | 2010-04-21 00:45:42 +0000 | [diff] [blame] | 78 |     isSuperMessage = true; | 
 | 79 |     break; | 
 | 80 |  | 
 | 81 |   case ObjCMessageExpr::SuperClass: | 
 | 82 |     Receiver = LoadObjCSelf(); | 
 | 83 |     isSuperMessage = true; | 
 | 84 |     isClassMessage = true; | 
 | 85 |     break; | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 86 |   } | 
 | 87 |  | 
| Daniel Dunbar | 19cd87e | 2008-08-30 03:02:31 +0000 | [diff] [blame] | 88 |   CallArgList Args; | 
| Anders Carlsson | 131038e | 2009-04-18 20:29:27 +0000 | [diff] [blame] | 89 |   EmitCallArgs(Args, E->getMethodDecl(), E->arg_begin(), E->arg_end()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 90 |  | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 91 |   if (isSuperMessage) { | 
| Chris Lattner | 9384c76 | 2008-06-26 04:42:20 +0000 | [diff] [blame] | 92 |     // super is only valid in an Objective-C method | 
 | 93 |     const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); | 
| Fariborz Jahanian | 7ce7792 | 2009-02-28 20:07:56 +0000 | [diff] [blame] | 94 |     bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); | 
| Daniel Dunbar | 7f8ea5c | 2008-08-30 05:35:15 +0000 | [diff] [blame] | 95 |     return Runtime.GenerateMessageSendSuper(*this, E->getType(), | 
 | 96 |                                             E->getSelector(), | 
| Daniel Dunbar | f56f191 | 2008-08-25 08:19:24 +0000 | [diff] [blame] | 97 |                                             OMD->getClassInterface(), | 
| Fariborz Jahanian | 7ce7792 | 2009-02-28 20:07:56 +0000 | [diff] [blame] | 98 |                                             isCategoryImpl, | 
| Daniel Dunbar | f56f191 | 2008-08-25 08:19:24 +0000 | [diff] [blame] | 99 |                                             Receiver, | 
| Daniel Dunbar | 19cd87e | 2008-08-30 03:02:31 +0000 | [diff] [blame] | 100 |                                             isClassMessage, | 
| Daniel Dunbar | d6c93d7 | 2009-09-17 04:01:22 +0000 | [diff] [blame] | 101 |                                             Args, | 
 | 102 |                                             E->getMethodDecl()); | 
| Chris Lattner | 8fdf328 | 2008-06-24 17:04:18 +0000 | [diff] [blame] | 103 |   } | 
| Daniel Dunbar | d6c93d7 | 2009-09-17 04:01:22 +0000 | [diff] [blame] | 104 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 105 |   return Runtime.GenerateMessageSend(*this, E->getType(), E->getSelector(), | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame^] | 106 |                                      Receiver, Args, OID, | 
| Fariborz Jahanian | df9ccc6 | 2009-05-05 21:36:57 +0000 | [diff] [blame] | 107 |                                      E->getMethodDecl()); | 
| Anders Carlsson | 5508518 | 2007-08-21 17:43:55 +0000 | [diff] [blame] | 108 | } | 
 | 109 |  | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 110 | /// StartObjCMethod - Begin emission of an ObjCMethod. This generates | 
 | 111 | /// the LLVM function and sets the other context used by | 
 | 112 | /// CodeGenFunction. | 
| Fariborz Jahanian | 679a502 | 2009-01-10 21:06:09 +0000 | [diff] [blame] | 113 | void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, | 
 | 114 |                                       const ObjCContainerDecl *CD) { | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 115 |   FunctionArgList Args; | 
| Devang Patel | 4800ea6 | 2010-04-05 21:09:15 +0000 | [diff] [blame] | 116 |   // Check if we should generate debug info for this method. | 
 | 117 |   if (CGM.getDebugInfo() && !OMD->hasAttr<NoDebugAttr>()) | 
 | 118 |     DebugInfo = CGM.getDebugInfo(); | 
 | 119 |  | 
| Fariborz Jahanian | 679a502 | 2009-01-10 21:06:09 +0000 | [diff] [blame] | 120 |   llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD); | 
| Daniel Dunbar | f80519b | 2008-09-04 23:41:35 +0000 | [diff] [blame] | 121 |  | 
| Daniel Dunbar | 0e4f40e | 2009-04-17 00:48:04 +0000 | [diff] [blame] | 122 |   const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD); | 
 | 123 |   CGM.SetInternalFunctionAttributes(OMD, Fn, FI); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 124 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 125 |   Args.push_back(std::make_pair(OMD->getSelfDecl(), | 
| Daniel Dunbar | 7c08651 | 2008-09-09 23:14:03 +0000 | [diff] [blame] | 126 |                                 OMD->getSelfDecl()->getType())); | 
 | 127 |   Args.push_back(std::make_pair(OMD->getCmdDecl(), | 
 | 128 |                                 OMD->getCmdDecl()->getType())); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 129 |  | 
| Chris Lattner | 89951a8 | 2009-02-20 18:43:26 +0000 | [diff] [blame] | 130 |   for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), | 
 | 131 |        E = OMD->param_end(); PI != E; ++PI) | 
 | 132 |     Args.push_back(std::make_pair(*PI, (*PI)->getType())); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 133 |  | 
| Devang Patel | a92d613 | 2010-02-15 18:08:38 +0000 | [diff] [blame] | 134 |   StartFunction(OMD, OMD->getResultType(), Fn, Args, OMD->getLocStart()); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 135 | } | 
| Daniel Dunbar | b7ec246 | 2008-08-16 03:19:19 +0000 | [diff] [blame] | 136 |  | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 137 | /// 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] | 138 | /// its pointer, name, and types registered in the class struture. | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 139 | void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { | 
| Fariborz Jahanian | 679a502 | 2009-01-10 21:06:09 +0000 | [diff] [blame] | 140 |   StartObjCMethod(OMD, OMD->getClassInterface()); | 
| Argyrios Kyrtzidis | 6fb0aee | 2009-06-30 02:35:26 +0000 | [diff] [blame] | 141 |   EmitStmt(OMD->getBody()); | 
 | 142 |   FinishFunction(OMD->getBodyRBrace()); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 143 | } | 
 | 144 |  | 
| Mike Stump | f5408fe | 2009-05-16 07:57:57 +0000 | [diff] [blame] | 145 | // FIXME: I wasn't sure about the synthesis approach. If we end up generating an | 
 | 146 | // AST for the whole body we can just fall back to having a GenerateFunction | 
 | 147 | // which takes the body Stmt. | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 148 |  | 
 | 149 | /// GenerateObjCGetter - Generate an Objective-C property getter | 
| Steve Naroff | 489034c | 2009-01-10 22:55:25 +0000 | [diff] [blame] | 150 | /// function. The given Decl must be an ObjCImplementationDecl. @synthesize | 
 | 151 | /// is illegal within a category. | 
| Fariborz Jahanian | fef30b5 | 2008-12-09 20:23:04 +0000 | [diff] [blame] | 152 | void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, | 
 | 153 |                                          const ObjCPropertyImplDecl *PID) { | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 154 |   ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 155 |   const ObjCPropertyDecl *PD = PID->getPropertyDecl(); | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 156 |   bool IsAtomic = | 
 | 157 |     !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 158 |   ObjCMethodDecl *OMD = PD->getGetterMethodDecl(); | 
 | 159 |   assert(OMD && "Invalid call to generate getter (empty method)"); | 
| Mike Stump | f5408fe | 2009-05-16 07:57:57 +0000 | [diff] [blame] | 160 |   // FIXME: This is rather murky, we create this here since they will not have | 
 | 161 |   // been created by Sema for us. | 
| Fariborz Jahanian | fef30b5 | 2008-12-09 20:23:04 +0000 | [diff] [blame] | 162 |   OMD->createImplicitParams(getContext(), IMP->getClassInterface()); | 
| Fariborz Jahanian | 679a502 | 2009-01-10 21:06:09 +0000 | [diff] [blame] | 163 |   StartObjCMethod(OMD, IMP->getClassInterface()); | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 164 |    | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 165 |   // Determine if we should use an objc_getProperty call for | 
| Fariborz Jahanian | 447d7ae | 2008-12-08 23:56:17 +0000 | [diff] [blame] | 166 |   // this. Non-atomic properties are directly evaluated. | 
 | 167 |   // atomic 'copy' and 'retain' properties are also directly | 
 | 168 |   // evaluated in gc-only mode. | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 169 |   if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 170 |       IsAtomic && | 
| Fariborz Jahanian | 447d7ae | 2008-12-08 23:56:17 +0000 | [diff] [blame] | 171 |       (PD->getSetterKind() == ObjCPropertyDecl::Copy || | 
 | 172 |        PD->getSetterKind() == ObjCPropertyDecl::Retain)) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 173 |     llvm::Value *GetPropertyFn = | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 174 |       CGM.getObjCRuntime().GetPropertyGetFunction(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 175 |  | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 176 |     if (!GetPropertyFn) { | 
 | 177 |       CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); | 
 | 178 |       FinishFunction(); | 
 | 179 |       return; | 
 | 180 |     } | 
 | 181 |  | 
 | 182 |     // Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true). | 
 | 183 |     // FIXME: Can't this be simpler? This might even be worse than the | 
 | 184 |     // corresponding gcc code. | 
 | 185 |     CodeGenTypes &Types = CGM.getTypes(); | 
 | 186 |     ValueDecl *Cmd = OMD->getCmdDecl(); | 
 | 187 |     llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); | 
 | 188 |     QualType IdTy = getContext().getObjCIdType(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 189 |     llvm::Value *SelfAsId = | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 190 |       Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); | 
| Fariborz Jahanian | fef30b5 | 2008-12-09 20:23:04 +0000 | [diff] [blame] | 191 |     llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 192 |     llvm::Value *True = | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 193 |       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 194 |     CallArgList Args; | 
 | 195 |     Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy)); | 
 | 196 |     Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); | 
 | 197 |     Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); | 
 | 198 |     Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy)); | 
| Daniel Dunbar | e4be5a6 | 2009-02-03 23:43:59 +0000 | [diff] [blame] | 199 |     // FIXME: We shouldn't need to get the function info here, the | 
 | 200 |     // runtime already should have computed it to build the function. | 
| John McCall | 04a67a6 | 2010-02-05 21:31:56 +0000 | [diff] [blame] | 201 |     RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args, | 
| Rafael Espindola | 264ba48 | 2010-03-30 20:24:48 +0000 | [diff] [blame] | 202 |                                                FunctionType::ExtInfo()), | 
| Anders Carlsson | f3c47c9 | 2009-12-24 19:25:24 +0000 | [diff] [blame] | 203 |                          GetPropertyFn, ReturnValueSlot(), Args); | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 204 |     // We need to fix the type here. Ivars with copy & retain are | 
 | 205 |     // always objects so we don't need to worry about complex or | 
 | 206 |     // aggregates. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 207 |     RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 208 |                                            Types.ConvertType(PD->getType()))); | 
 | 209 |     EmitReturnOfRValue(RV, PD->getType()); | 
 | 210 |   } else { | 
| Daniel Dunbar | 525c9b7 | 2009-04-21 01:19:28 +0000 | [diff] [blame] | 211 |     LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); | 
| Fariborz Jahanian | 1b23fe6 | 2010-03-25 21:56:43 +0000 | [diff] [blame] | 212 |     if (Ivar->getType()->isAnyComplexType()) { | 
 | 213 |       ComplexPairTy Pair = LoadComplexFromAddr(LV.getAddress(), | 
 | 214 |                                                LV.isVolatileQualified()); | 
 | 215 |       StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified()); | 
 | 216 |     } | 
 | 217 |     else if (hasAggregateLLVMType(Ivar->getType())) { | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 218 |       bool IsStrong = false; | 
 | 219 |       if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(Ivar->getType()))) | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 220 |           && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect | 
 | 221 |           && CGM.getObjCRuntime().GetCopyStructFunction()) { | 
 | 222 |         llvm::Value *GetCopyStructFn = | 
 | 223 |           CGM.getObjCRuntime().GetCopyStructFunction(); | 
 | 224 |         CodeGenTypes &Types = CGM.getTypes(); | 
 | 225 |         // objc_copyStruct (ReturnValue, &structIvar,  | 
 | 226 |         //                  sizeof (Type of Ivar), isAtomic, false); | 
 | 227 |         CallArgList Args; | 
 | 228 |         RValue RV = RValue::get(Builder.CreateBitCast(ReturnValue, | 
 | 229 |                                     Types.ConvertType(getContext().VoidPtrTy))); | 
 | 230 |         Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); | 
 | 231 |         RV = RValue::get(Builder.CreateBitCast(LV.getAddress(), | 
 | 232 |                                     Types.ConvertType(getContext().VoidPtrTy))); | 
 | 233 |         Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); | 
 | 234 |         // sizeof (Type of Ivar) | 
 | 235 |         uint64_t Size =  getContext().getTypeSize(Ivar->getType()) / 8; | 
 | 236 |         llvm::Value *SizeVal = | 
 | 237 |           llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size); | 
 | 238 |         Args.push_back(std::make_pair(RValue::get(SizeVal), | 
 | 239 |                                       getContext().LongTy)); | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 240 |         llvm::Value *isAtomic = | 
| Fariborz Jahanian | 08adf32 | 2010-04-13 18:43:37 +0000 | [diff] [blame] | 241 |           llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),  | 
 | 242 |                                  IsAtomic ? 1 : 0); | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 243 |         Args.push_back(std::make_pair(RValue::get(isAtomic),  | 
 | 244 |                                       getContext().BoolTy)); | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 245 |         llvm::Value *hasStrong = | 
 | 246 |           llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy),  | 
 | 247 |                                  IsStrong ? 1 : 0); | 
 | 248 |         Args.push_back(std::make_pair(RValue::get(hasStrong),  | 
 | 249 |                                       getContext().BoolTy)); | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 250 |         EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, | 
 | 251 |                                        FunctionType::ExtInfo()), | 
 | 252 |                  GetCopyStructFn, ReturnValueSlot(), Args); | 
 | 253 |       } | 
 | 254 |       else | 
 | 255 |         EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType()); | 
| Mike Stump | b3589f4 | 2009-07-30 22:28:39 +0000 | [diff] [blame] | 256 |     } else { | 
| Fariborz Jahanian | ed1d29d | 2009-03-03 18:49:40 +0000 | [diff] [blame] | 257 |       CodeGenTypes &Types = CGM.getTypes(); | 
 | 258 |       RValue RV = EmitLoadOfLValue(LV, Ivar->getType()); | 
 | 259 |       RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 260 |                        Types.ConvertType(PD->getType()))); | 
| Fariborz Jahanian | ed1d29d | 2009-03-03 18:49:40 +0000 | [diff] [blame] | 261 |       EmitReturnOfRValue(RV, PD->getType()); | 
 | 262 |     } | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 263 |   } | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 264 |  | 
 | 265 |   FinishFunction(); | 
 | 266 | } | 
 | 267 |  | 
 | 268 | /// GenerateObjCSetter - Generate an Objective-C property setter | 
| Steve Naroff | 489034c | 2009-01-10 22:55:25 +0000 | [diff] [blame] | 269 | /// function. The given Decl must be an ObjCImplementationDecl. @synthesize | 
 | 270 | /// is illegal within a category. | 
| Fariborz Jahanian | fef30b5 | 2008-12-09 20:23:04 +0000 | [diff] [blame] | 271 | void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, | 
 | 272 |                                          const ObjCPropertyImplDecl *PID) { | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 273 |   ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 274 |   const ObjCPropertyDecl *PD = PID->getPropertyDecl(); | 
 | 275 |   ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); | 
 | 276 |   assert(OMD && "Invalid call to generate setter (empty method)"); | 
| Mike Stump | f5408fe | 2009-05-16 07:57:57 +0000 | [diff] [blame] | 277 |   // FIXME: This is rather murky, we create this here since they will not have | 
 | 278 |   // been created by Sema for us. | 
| Fariborz Jahanian | fef30b5 | 2008-12-09 20:23:04 +0000 | [diff] [blame] | 279 |   OMD->createImplicitParams(getContext(), IMP->getClassInterface()); | 
| Fariborz Jahanian | 679a502 | 2009-01-10 21:06:09 +0000 | [diff] [blame] | 280 |   StartObjCMethod(OMD, IMP->getClassInterface()); | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 281 |  | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 282 |   bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 283 |   bool IsAtomic = | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 284 |     !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); | 
 | 285 |  | 
 | 286 |   // Determine if we should use an objc_setProperty call for | 
 | 287 |   // this. Properties with 'copy' semantics always use it, as do | 
 | 288 |   // non-atomic properties with 'release' semantics as long as we are | 
 | 289 |   // not in gc-only mode. | 
 | 290 |   if (IsCopy || | 
 | 291 |       (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && | 
 | 292 |        PD->getSetterKind() == ObjCPropertyDecl::Retain)) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 293 |     llvm::Value *SetPropertyFn = | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 294 |       CGM.getObjCRuntime().GetPropertySetFunction(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 295 |  | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 296 |     if (!SetPropertyFn) { | 
 | 297 |       CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); | 
 | 298 |       FinishFunction(); | 
 | 299 |       return; | 
 | 300 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 301 |  | 
 | 302 |     // Emit objc_setProperty((id) self, _cmd, offset, arg, | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 303 |     //                       <is-atomic>, <is-copy>). | 
 | 304 |     // FIXME: Can't this be simpler? This might even be worse than the | 
 | 305 |     // corresponding gcc code. | 
 | 306 |     CodeGenTypes &Types = CGM.getTypes(); | 
 | 307 |     ValueDecl *Cmd = OMD->getCmdDecl(); | 
 | 308 |     llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); | 
 | 309 |     QualType IdTy = getContext().getObjCIdType(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 310 |     llvm::Value *SelfAsId = | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 311 |       Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); | 
| Fariborz Jahanian | fef30b5 | 2008-12-09 20:23:04 +0000 | [diff] [blame] | 312 |     llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); | 
| Chris Lattner | 89951a8 | 2009-02-20 18:43:26 +0000 | [diff] [blame] | 313 |     llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 314 |     llvm::Value *ArgAsId = | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 315 |       Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"), | 
 | 316 |                             Types.ConvertType(IdTy)); | 
 | 317 |     llvm::Value *True = | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 318 |       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 319 |     llvm::Value *False = | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 320 |       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 321 |     CallArgList Args; | 
 | 322 |     Args.push_back(std::make_pair(RValue::get(SelfAsId), IdTy)); | 
 | 323 |     Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); | 
 | 324 |     Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); | 
 | 325 |     Args.push_back(std::make_pair(RValue::get(ArgAsId), IdTy)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 326 |     Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False), | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 327 |                                   getContext().BoolTy)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 328 |     Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False), | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 329 |                                   getContext().BoolTy)); | 
| Mike Stump | f5408fe | 2009-05-16 07:57:57 +0000 | [diff] [blame] | 330 |     // FIXME: We shouldn't need to get the function info here, the runtime | 
 | 331 |     // already should have computed it to build the function. | 
| John McCall | 04a67a6 | 2010-02-05 21:31:56 +0000 | [diff] [blame] | 332 |     EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, | 
| Rafael Espindola | 264ba48 | 2010-03-30 20:24:48 +0000 | [diff] [blame] | 333 |                                    FunctionType::ExtInfo()), | 
 | 334 |              SetPropertyFn, | 
| Anders Carlsson | f3c47c9 | 2009-12-24 19:25:24 +0000 | [diff] [blame] | 335 |              ReturnValueSlot(), Args); | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 336 |   } else if (IsAtomic && hasAggregateLLVMType(Ivar->getType()) && | 
 | 337 |              !Ivar->getType()->isAnyComplexType() && | 
 | 338 |              IndirectObjCSetterArg(*CurFnInfo) | 
 | 339 |              && CGM.getObjCRuntime().GetCopyStructFunction()) { | 
 | 340 |     // objc_copyStruct (&structIvar, &Arg,  | 
 | 341 |     //                  sizeof (struct something), true, false); | 
 | 342 |     llvm::Value *GetCopyStructFn = | 
 | 343 |       CGM.getObjCRuntime().GetCopyStructFunction(); | 
 | 344 |     CodeGenTypes &Types = CGM.getTypes(); | 
 | 345 |     CallArgList Args; | 
 | 346 |     LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); | 
 | 347 |     RValue RV = RValue::get(Builder.CreateBitCast(LV.getAddress(), | 
 | 348 |                                     Types.ConvertType(getContext().VoidPtrTy))); | 
 | 349 |     Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); | 
 | 350 |     llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; | 
 | 351 |     llvm::Value *ArgAsPtrTy = | 
 | 352 |       Builder.CreateBitCast(Arg, | 
 | 353 |                             Types.ConvertType(getContext().VoidPtrTy)); | 
 | 354 |     RV = RValue::get(ArgAsPtrTy); | 
 | 355 |     Args.push_back(std::make_pair(RV, getContext().VoidPtrTy)); | 
 | 356 |     // sizeof (Type of Ivar) | 
 | 357 |     uint64_t Size =  getContext().getTypeSize(Ivar->getType()) / 8; | 
 | 358 |     llvm::Value *SizeVal = | 
 | 359 |       llvm::ConstantInt::get(Types.ConvertType(getContext().LongTy), Size); | 
 | 360 |     Args.push_back(std::make_pair(RValue::get(SizeVal), | 
 | 361 |                                   getContext().LongTy)); | 
 | 362 |     llvm::Value *True = | 
 | 363 |       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1); | 
 | 364 |     Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy)); | 
 | 365 |     llvm::Value *False = | 
 | 366 |       llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0); | 
 | 367 |     Args.push_back(std::make_pair(RValue::get(False), getContext().BoolTy)); | 
 | 368 |     EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args, | 
 | 369 |                                    FunctionType::ExtInfo()), | 
 | 370 |              GetCopyStructFn, ReturnValueSlot(), Args); | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 371 |   } else { | 
| Daniel Dunbar | 45e8423 | 2009-10-27 19:21:30 +0000 | [diff] [blame] | 372 |     // FIXME: Find a clean way to avoid AST node creation. | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 373 |     SourceLocation Loc = PD->getLocation(); | 
 | 374 |     ValueDecl *Self = OMD->getSelfDecl(); | 
 | 375 |     ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl(); | 
 | 376 |     DeclRefExpr Base(Self, Self->getType(), Loc); | 
| Chris Lattner | 89951a8 | 2009-02-20 18:43:26 +0000 | [diff] [blame] | 377 |     ParmVarDecl *ArgDecl = *OMD->param_begin(); | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 378 |     DeclRefExpr Arg(ArgDecl, ArgDecl->getType(), Loc); | 
| Daniel Dunbar | 45e8423 | 2009-10-27 19:21:30 +0000 | [diff] [blame] | 379 |     ObjCIvarRefExpr IvarRef(Ivar, Ivar->getType(), Loc, &Base, true, true); | 
 | 380 |      | 
 | 381 |     // The property type can differ from the ivar type in some situations with | 
 | 382 |     // Objective-C pointer types, we can always bit cast the RHS in these cases. | 
 | 383 |     if (getContext().getCanonicalType(Ivar->getType()) != | 
 | 384 |         getContext().getCanonicalType(ArgDecl->getType())) { | 
 | 385 |       ImplicitCastExpr ArgCasted(Ivar->getType(), CastExpr::CK_BitCast, &Arg, | 
| Anders Carlsson | f1b48b7 | 2010-04-24 16:57:13 +0000 | [diff] [blame] | 386 |                                  CXXBaseSpecifierArray(), false); | 
| Daniel Dunbar | 45e8423 | 2009-10-27 19:21:30 +0000 | [diff] [blame] | 387 |       BinaryOperator Assign(&IvarRef, &ArgCasted, BinaryOperator::Assign, | 
 | 388 |                             Ivar->getType(), Loc); | 
 | 389 |       EmitStmt(&Assign); | 
 | 390 |     } else { | 
 | 391 |       BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign, | 
 | 392 |                             Ivar->getType(), Loc); | 
 | 393 |       EmitStmt(&Assign); | 
 | 394 |     } | 
| Daniel Dunbar | 86957eb | 2008-09-24 06:32:09 +0000 | [diff] [blame] | 395 |   } | 
| Daniel Dunbar | af05bb9 | 2008-08-26 08:29:31 +0000 | [diff] [blame] | 396 |  | 
 | 397 |   FinishFunction(); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 398 | } | 
 | 399 |  | 
| Fariborz Jahanian | 0b2bd47 | 2010-04-13 00:38:05 +0000 | [diff] [blame] | 400 | bool CodeGenFunction::IndirectObjCSetterArg(const CGFunctionInfo &FI) { | 
 | 401 |   CGFunctionInfo::const_arg_iterator it = FI.arg_begin(); | 
 | 402 |   it++; it++; | 
 | 403 |   const ABIArgInfo &AI = it->info; | 
 | 404 |   // FIXME. Is this sufficient check? | 
 | 405 |   return (AI.getKind() == ABIArgInfo::Indirect); | 
 | 406 | } | 
 | 407 |  | 
| Fariborz Jahanian | 15bd588 | 2010-04-13 18:32:24 +0000 | [diff] [blame] | 408 | bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) { | 
 | 409 |   if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC) | 
 | 410 |     return false; | 
 | 411 |   if (const RecordType *FDTTy = Ty.getTypePtr()->getAs<RecordType>()) | 
 | 412 |     return FDTTy->getDecl()->hasObjectMember(); | 
 | 413 |   return false; | 
 | 414 | } | 
 | 415 |  | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 416 | llvm::Value *CodeGenFunction::LoadObjCSelf() { | 
| Daniel Dunbar | b7ec246 | 2008-08-16 03:19:19 +0000 | [diff] [blame] | 417 |   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); | 
| Mike Stump | 6cc88f7 | 2009-03-20 21:53:12 +0000 | [diff] [blame] | 418 |   // See if we need to lazily forward self inside a block literal. | 
 | 419 |   BlockForwardSelf(); | 
| Daniel Dunbar | b7ec246 | 2008-08-16 03:19:19 +0000 | [diff] [blame] | 420 |   return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self"); | 
| Chris Lattner | 4111024 | 2008-06-17 18:05:57 +0000 | [diff] [blame] | 421 | } | 
 | 422 |  | 
| Fariborz Jahanian | 45012a7 | 2009-02-03 00:09:52 +0000 | [diff] [blame] | 423 | QualType CodeGenFunction::TypeOfSelfObject() { | 
 | 424 |   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); | 
 | 425 |   ImplicitParamDecl *selfDecl = OMD->getSelfDecl(); | 
| Steve Naroff | 14108da | 2009-07-10 23:34:53 +0000 | [diff] [blame] | 426 |   const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>( | 
 | 427 |     getContext().getCanonicalType(selfDecl->getType())); | 
| Fariborz Jahanian | 45012a7 | 2009-02-03 00:09:52 +0000 | [diff] [blame] | 428 |   return PTy->getPointeeType(); | 
 | 429 | } | 
 | 430 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 431 | RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp, | 
| Fariborz Jahanian | f469557 | 2009-03-20 19:18:21 +0000 | [diff] [blame] | 432 |                                                  const Selector &S) { | 
 | 433 |   llvm::Value *Receiver = LoadObjCSelf(); | 
 | 434 |   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); | 
 | 435 |   bool isClassMessage = OMD->isClassMethod(); | 
 | 436 |   bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 437 |   return CGM.getObjCRuntime().GenerateMessageSendSuper(*this, | 
| Fariborz Jahanian | f469557 | 2009-03-20 19:18:21 +0000 | [diff] [blame] | 438 |                                                        Exp->getType(), | 
 | 439 |                                                        S, | 
 | 440 |                                                        OMD->getClassInterface(), | 
 | 441 |                                                        isCategoryImpl, | 
 | 442 |                                                        Receiver, | 
 | 443 |                                                        isClassMessage, | 
 | 444 |                                                        CallArgList()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 445 |  | 
| Fariborz Jahanian | f469557 | 2009-03-20 19:18:21 +0000 | [diff] [blame] | 446 | } | 
 | 447 |  | 
| Fariborz Jahanian | 5daf570 | 2008-11-22 18:39:36 +0000 | [diff] [blame] | 448 | RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp) { | 
| Fariborz Jahanian | d2e1eb0 | 2009-09-01 17:02:21 +0000 | [diff] [blame] | 449 |   Exp = Exp->IgnoreParens(); | 
| Fariborz Jahanian | 43f4470 | 2008-11-22 22:30:21 +0000 | [diff] [blame] | 450 |   // FIXME: Split it into two separate routines. | 
| Fariborz Jahanian | 5daf570 | 2008-11-22 18:39:36 +0000 | [diff] [blame] | 451 |   if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) { | 
 | 452 |     Selector S = E->getProperty()->getGetterName(); | 
| Fariborz Jahanian | f469557 | 2009-03-20 19:18:21 +0000 | [diff] [blame] | 453 |     if (isa<ObjCSuperExpr>(E->getBase())) | 
 | 454 |       return EmitObjCSuperPropertyGet(E, S); | 
| Fariborz Jahanian | 5daf570 | 2008-11-22 18:39:36 +0000 | [diff] [blame] | 455 |     return CGM.getObjCRuntime(). | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 456 |              GenerateMessageSend(*this, Exp->getType(), S, | 
 | 457 |                                  EmitScalarExpr(E->getBase()), | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame^] | 458 |                                  CallArgList()); | 
| Mike Stump | b3589f4 | 2009-07-30 22:28:39 +0000 | [diff] [blame] | 459 |   } else { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 460 |     const ObjCImplicitSetterGetterRefExpr *KE = | 
| Fariborz Jahanian | 09105f5 | 2009-08-20 17:02:02 +0000 | [diff] [blame] | 461 |       cast<ObjCImplicitSetterGetterRefExpr>(Exp); | 
| Daniel Dunbar | f479cea | 2009-01-16 01:50:29 +0000 | [diff] [blame] | 462 |     Selector S = KE->getGetterMethod()->getSelector(); | 
| Fariborz Jahanian | 3523d4f | 2009-03-10 18:03:11 +0000 | [diff] [blame] | 463 |     llvm::Value *Receiver; | 
| Fariborz Jahanian | d2ae5aa | 2009-08-18 21:37:33 +0000 | [diff] [blame] | 464 |     if (KE->getInterfaceDecl()) { | 
 | 465 |       const ObjCInterfaceDecl *OID = KE->getInterfaceDecl(); | 
| Fariborz Jahanian | 3523d4f | 2009-03-10 18:03:11 +0000 | [diff] [blame] | 466 |       Receiver = CGM.getObjCRuntime().GetClass(Builder, OID); | 
| Mike Stump | b3589f4 | 2009-07-30 22:28:39 +0000 | [diff] [blame] | 467 |     } else if (isa<ObjCSuperExpr>(KE->getBase())) | 
| Fariborz Jahanian | f469557 | 2009-03-20 19:18:21 +0000 | [diff] [blame] | 468 |       return EmitObjCSuperPropertyGet(KE, S); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 469 |     else | 
| Fariborz Jahanian | 3523d4f | 2009-03-10 18:03:11 +0000 | [diff] [blame] | 470 |       Receiver = EmitScalarExpr(KE->getBase()); | 
| Fariborz Jahanian | 43f4470 | 2008-11-22 22:30:21 +0000 | [diff] [blame] | 471 |     return CGM.getObjCRuntime(). | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 472 |              GenerateMessageSend(*this, Exp->getType(), S, | 
 | 473 |                                  Receiver, | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame^] | 474 |                                  CallArgList(), KE->getInterfaceDecl()); | 
| Fariborz Jahanian | 43f4470 | 2008-11-22 22:30:21 +0000 | [diff] [blame] | 475 |   } | 
| Daniel Dunbar | 9c3fc70 | 2008-08-27 06:57:25 +0000 | [diff] [blame] | 476 | } | 
 | 477 |  | 
| Fariborz Jahanian | f469557 | 2009-03-20 19:18:21 +0000 | [diff] [blame] | 478 | void CodeGenFunction::EmitObjCSuperPropertySet(const Expr *Exp, | 
 | 479 |                                                const Selector &S, | 
 | 480 |                                                RValue Src) { | 
 | 481 |   CallArgList Args; | 
 | 482 |   llvm::Value *Receiver = LoadObjCSelf(); | 
 | 483 |   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); | 
 | 484 |   bool isClassMessage = OMD->isClassMethod(); | 
 | 485 |   bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); | 
 | 486 |   Args.push_back(std::make_pair(Src, Exp->getType())); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 487 |   CGM.getObjCRuntime().GenerateMessageSendSuper(*this, | 
| Fariborz Jahanian | f469557 | 2009-03-20 19:18:21 +0000 | [diff] [blame] | 488 |                                                 Exp->getType(), | 
 | 489 |                                                 S, | 
 | 490 |                                                 OMD->getClassInterface(), | 
 | 491 |                                                 isCategoryImpl, | 
 | 492 |                                                 Receiver, | 
 | 493 |                                                 isClassMessage, | 
 | 494 |                                                 Args); | 
 | 495 |   return; | 
 | 496 | } | 
 | 497 |  | 
| Fariborz Jahanian | 43f4470 | 2008-11-22 22:30:21 +0000 | [diff] [blame] | 498 | void CodeGenFunction::EmitObjCPropertySet(const Expr *Exp, | 
| Daniel Dunbar | 85c59ed | 2008-08-29 08:11:39 +0000 | [diff] [blame] | 499 |                                           RValue Src) { | 
| Fariborz Jahanian | 43f4470 | 2008-11-22 22:30:21 +0000 | [diff] [blame] | 500 |   // FIXME: Split it into two separate routines. | 
 | 501 |   if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) { | 
 | 502 |     Selector S = E->getProperty()->getSetterName(); | 
| Fariborz Jahanian | f469557 | 2009-03-20 19:18:21 +0000 | [diff] [blame] | 503 |     if (isa<ObjCSuperExpr>(E->getBase())) { | 
 | 504 |       EmitObjCSuperPropertySet(E, S, Src); | 
 | 505 |       return; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 506 |     } | 
| Fariborz Jahanian | 43f4470 | 2008-11-22 22:30:21 +0000 | [diff] [blame] | 507 |     CallArgList Args; | 
 | 508 |     Args.push_back(std::make_pair(Src, E->getType())); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 509 |     CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, | 
 | 510 |                                              EmitScalarExpr(E->getBase()), | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame^] | 511 |                                              Args); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 512 |   } else if (const ObjCImplicitSetterGetterRefExpr *E = | 
| Fariborz Jahanian | 09105f5 | 2009-08-20 17:02:02 +0000 | [diff] [blame] | 513 |                dyn_cast<ObjCImplicitSetterGetterRefExpr>(Exp)) { | 
| Fariborz Jahanian | 43f4470 | 2008-11-22 22:30:21 +0000 | [diff] [blame] | 514 |     Selector S = E->getSetterMethod()->getSelector(); | 
 | 515 |     CallArgList Args; | 
| Fariborz Jahanian | 3523d4f | 2009-03-10 18:03:11 +0000 | [diff] [blame] | 516 |     llvm::Value *Receiver; | 
| Fariborz Jahanian | d2ae5aa | 2009-08-18 21:37:33 +0000 | [diff] [blame] | 517 |     if (E->getInterfaceDecl()) { | 
 | 518 |       const ObjCInterfaceDecl *OID = E->getInterfaceDecl(); | 
| Fariborz Jahanian | 3523d4f | 2009-03-10 18:03:11 +0000 | [diff] [blame] | 519 |       Receiver = CGM.getObjCRuntime().GetClass(Builder, OID); | 
| Mike Stump | b3589f4 | 2009-07-30 22:28:39 +0000 | [diff] [blame] | 520 |     } else if (isa<ObjCSuperExpr>(E->getBase())) { | 
| Fariborz Jahanian | f469557 | 2009-03-20 19:18:21 +0000 | [diff] [blame] | 521 |       EmitObjCSuperPropertySet(E, S, Src); | 
| Fariborz Jahanian | 8e5d232 | 2009-03-20 17:22:23 +0000 | [diff] [blame] | 522 |       return; | 
| Mike Stump | b3589f4 | 2009-07-30 22:28:39 +0000 | [diff] [blame] | 523 |     } else | 
| Fariborz Jahanian | 3523d4f | 2009-03-10 18:03:11 +0000 | [diff] [blame] | 524 |       Receiver = EmitScalarExpr(E->getBase()); | 
| Fariborz Jahanian | 43f4470 | 2008-11-22 22:30:21 +0000 | [diff] [blame] | 525 |     Args.push_back(std::make_pair(Src, E->getType())); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 526 |     CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, | 
 | 527 |                                              Receiver, | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame^] | 528 |                                              Args, E->getInterfaceDecl()); | 
| Mike Stump | b3589f4 | 2009-07-30 22:28:39 +0000 | [diff] [blame] | 529 |   } else | 
| Fariborz Jahanian | 43f4470 | 2008-11-22 22:30:21 +0000 | [diff] [blame] | 530 |     assert (0 && "bad expression node in EmitObjCPropertySet"); | 
| Daniel Dunbar | 85c59ed | 2008-08-29 08:11:39 +0000 | [diff] [blame] | 531 | } | 
 | 532 |  | 
| Chris Lattner | 74391b4 | 2009-03-22 21:03:39 +0000 | [diff] [blame] | 533 | void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 534 |   llvm::Constant *EnumerationMutationFn = | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 535 |     CGM.getObjCRuntime().EnumerationMutationFunction(); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 536 |   llvm::Value *DeclAddress; | 
 | 537 |   QualType ElementTy; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 538 |  | 
| Daniel Dunbar | c1cf4a5 | 2008-09-24 04:04:31 +0000 | [diff] [blame] | 539 |   if (!EnumerationMutationFn) { | 
 | 540 |     CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime"); | 
 | 541 |     return; | 
 | 542 |   } | 
 | 543 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 544 |   if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) { | 
 | 545 |     EmitStmt(SD); | 
| Daniel Dunbar | a448fb2 | 2008-11-11 23:11:34 +0000 | [diff] [blame] | 546 |     assert(HaveInsertPoint() && "DeclStmt destroyed insert point!"); | 
| Chris Lattner | 7e24e82 | 2009-03-28 06:33:19 +0000 | [diff] [blame] | 547 |     const Decl* D = SD->getSingleDecl(); | 
| Ted Kremenek | 39741ce | 2008-10-06 20:59:48 +0000 | [diff] [blame] | 548 |     ElementTy = cast<ValueDecl>(D)->getType(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 549 |     DeclAddress = LocalDeclMap[D]; | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 550 |   } else { | 
 | 551 |     ElementTy = cast<Expr>(S.getElement())->getType(); | 
 | 552 |     DeclAddress = 0; | 
 | 553 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 554 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 555 |   // Fast enumeration state. | 
 | 556 |   QualType StateTy = getContext().getObjCFastEnumerationStateType(); | 
| Daniel Dunbar | 195337d | 2010-02-09 02:48:28 +0000 | [diff] [blame] | 557 |   llvm::Value *StatePtr = CreateMemTemp(StateTy, "state.ptr"); | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 558 |   EmitMemSetToZero(StatePtr, StateTy); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 559 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 560 |   // Number of elements in the items array. | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 561 |   static const unsigned NumItems = 16; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 562 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 563 |   // Get selector | 
| Benjamin Kramer | ad46886 | 2010-03-30 11:36:44 +0000 | [diff] [blame] | 564 |   IdentifierInfo *II[] = { | 
 | 565 |     &CGM.getContext().Idents.get("countByEnumeratingWithState"), | 
 | 566 |     &CGM.getContext().Idents.get("objects"), | 
 | 567 |     &CGM.getContext().Idents.get("count") | 
 | 568 |   }; | 
 | 569 |   Selector FastEnumSel = | 
 | 570 |     CGM.getContext().Selectors.getSelector(llvm::array_lengthof(II), &II[0]); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 571 |  | 
 | 572 |   QualType ItemsTy = | 
 | 573 |     getContext().getConstantArrayType(getContext().getObjCIdType(), | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 574 |                                       llvm::APInt(32, NumItems), | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 575 |                                       ArrayType::Normal, 0); | 
| Daniel Dunbar | 195337d | 2010-02-09 02:48:28 +0000 | [diff] [blame] | 576 |   llvm::Value *ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 577 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 578 |   llvm::Value *Collection = EmitScalarExpr(S.getCollection()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 579 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 580 |   CallArgList Args; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 581 |   Args.push_back(std::make_pair(RValue::get(StatePtr), | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 582 |                                 getContext().getPointerType(StateTy))); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 583 |  | 
 | 584 |   Args.push_back(std::make_pair(RValue::get(ItemsPtr), | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 585 |                                 getContext().getPointerType(ItemsTy))); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 586 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 587 |   const llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy); | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 588 |   llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 589 |   Args.push_back(std::make_pair(RValue::get(Count), | 
| Daniel Dunbar | 46f45b9 | 2008-09-09 01:06:48 +0000 | [diff] [blame] | 590 |                                 getContext().UnsignedLongTy)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 591 |  | 
 | 592 |   RValue CountRV = | 
 | 593 |     CGM.getObjCRuntime().GenerateMessageSend(*this, | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 594 |                                              getContext().UnsignedLongTy, | 
 | 595 |                                              FastEnumSel, | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame^] | 596 |                                              Collection, Args); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 597 |  | 
| Daniel Dunbar | 195337d | 2010-02-09 02:48:28 +0000 | [diff] [blame] | 598 |   llvm::Value *LimitPtr = CreateMemTemp(getContext().UnsignedLongTy, | 
 | 599 |                                         "limit.ptr"); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 600 |   Builder.CreateStore(CountRV.getScalarVal(), LimitPtr); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 601 |  | 
| Daniel Dunbar | 55e8742 | 2008-11-11 02:29:29 +0000 | [diff] [blame] | 602 |   llvm::BasicBlock *NoElements = createBasicBlock("noelements"); | 
 | 603 |   llvm::BasicBlock *SetStartMutations = createBasicBlock("setstartmutations"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 604 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 605 |   llvm::Value *Limit = Builder.CreateLoad(LimitPtr); | 
| Owen Anderson | c9c88b4 | 2009-07-31 20:28:54 +0000 | [diff] [blame] | 606 |   llvm::Value *Zero = llvm::Constant::getNullValue(UnsignedLongLTy); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 607 |  | 
 | 608 |   llvm::Value *IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero"); | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 609 |   Builder.CreateCondBr(IsZero, NoElements, SetStartMutations); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 610 |  | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 611 |   EmitBlock(SetStartMutations); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 612 |  | 
| Daniel Dunbar | 195337d | 2010-02-09 02:48:28 +0000 | [diff] [blame] | 613 |   llvm::Value *StartMutationsPtr = CreateMemTemp(getContext().UnsignedLongTy); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 614 |  | 
 | 615 |   llvm::Value *StateMutationsPtrPtr = | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 616 |     Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 617 |   llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 618 |                                                       "mutationsptr"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 619 |  | 
 | 620 |   llvm::Value *StateMutations = Builder.CreateLoad(StateMutationsPtr, | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 621 |                                                    "mutations"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 622 |  | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 623 |   Builder.CreateStore(StateMutations, StartMutationsPtr); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 624 |  | 
| Daniel Dunbar | 55e8742 | 2008-11-11 02:29:29 +0000 | [diff] [blame] | 625 |   llvm::BasicBlock *LoopStart = createBasicBlock("loopstart"); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 626 |   EmitBlock(LoopStart); | 
 | 627 |  | 
| Daniel Dunbar | 195337d | 2010-02-09 02:48:28 +0000 | [diff] [blame] | 628 |   llvm::Value *CounterPtr = CreateMemTemp(getContext().UnsignedLongTy, | 
 | 629 |                                        "counter.ptr"); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 630 |   Builder.CreateStore(Zero, CounterPtr); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 631 |  | 
 | 632 |   llvm::BasicBlock *LoopBody = createBasicBlock("loopbody"); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 633 |   EmitBlock(LoopBody); | 
 | 634 |  | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 635 |   StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); | 
 | 636 |   StateMutations = Builder.CreateLoad(StateMutationsPtr, "statemutations"); | 
 | 637 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 638 |   llvm::Value *StartMutations = Builder.CreateLoad(StartMutationsPtr, | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 639 |                                                    "mutations"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 640 |   llvm::Value *MutationsEqual = Builder.CreateICmpEQ(StateMutations, | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 641 |                                                      StartMutations, | 
 | 642 |                                                      "tobool"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 643 |  | 
 | 644 |  | 
| Daniel Dunbar | 55e8742 | 2008-11-11 02:29:29 +0000 | [diff] [blame] | 645 |   llvm::BasicBlock *WasMutated = createBasicBlock("wasmutated"); | 
 | 646 |   llvm::BasicBlock *WasNotMutated = createBasicBlock("wasnotmutated"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 647 |  | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 648 |   Builder.CreateCondBr(MutationsEqual, WasNotMutated, WasMutated); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 649 |  | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 650 |   EmitBlock(WasMutated); | 
 | 651 |   llvm::Value *V = | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 652 |     Builder.CreateBitCast(Collection, | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 653 |                           ConvertType(getContext().getObjCIdType()), | 
 | 654 |                           "tmp"); | 
| Daniel Dunbar | 2b2105e | 2009-02-03 23:55:40 +0000 | [diff] [blame] | 655 |   CallArgList Args2; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 656 |   Args2.push_back(std::make_pair(RValue::get(V), | 
| Daniel Dunbar | 2b2105e | 2009-02-03 23:55:40 +0000 | [diff] [blame] | 657 |                                 getContext().getObjCIdType())); | 
| Mike Stump | f5408fe | 2009-05-16 07:57:57 +0000 | [diff] [blame] | 658 |   // FIXME: We shouldn't need to get the function info here, the runtime already | 
 | 659 |   // should have computed it to build the function. | 
| John McCall | 04a67a6 | 2010-02-05 21:31:56 +0000 | [diff] [blame] | 660 |   EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2, | 
| Rafael Espindola | 264ba48 | 2010-03-30 20:24:48 +0000 | [diff] [blame] | 661 |                                           FunctionType::ExtInfo()), | 
| Anders Carlsson | f3c47c9 | 2009-12-24 19:25:24 +0000 | [diff] [blame] | 662 |            EnumerationMutationFn, ReturnValueSlot(), Args2); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 663 |  | 
| Anders Carlsson | 2abd89c | 2008-08-31 04:05:03 +0000 | [diff] [blame] | 664 |   EmitBlock(WasNotMutated); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 665 |  | 
 | 666 |   llvm::Value *StateItemsPtr = | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 667 |     Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr"); | 
 | 668 |  | 
 | 669 |   llvm::Value *Counter = Builder.CreateLoad(CounterPtr, "counter"); | 
 | 670 |  | 
 | 671 |   llvm::Value *EnumStateItems = Builder.CreateLoad(StateItemsPtr, | 
 | 672 |                                                    "stateitems"); | 
 | 673 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 674 |   llvm::Value *CurrentItemPtr = | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 675 |     Builder.CreateGEP(EnumStateItems, Counter, "currentitem.ptr"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 676 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 677 |   llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr, "currentitem"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 678 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 679 |   // Cast the item to the right type. | 
 | 680 |   CurrentItem = Builder.CreateBitCast(CurrentItem, | 
 | 681 |                                       ConvertType(ElementTy), "tmp"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 682 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 683 |   if (!DeclAddress) { | 
 | 684 |     LValue LV = EmitLValue(cast<Expr>(S.getElement())); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 685 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 686 |     // Set the value to null. | 
 | 687 |     Builder.CreateStore(CurrentItem, LV.getAddress()); | 
 | 688 |   } else | 
 | 689 |     Builder.CreateStore(CurrentItem, DeclAddress); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 690 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 691 |   // Increment the counter. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 692 |   Counter = Builder.CreateAdd(Counter, | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 693 |                               llvm::ConstantInt::get(UnsignedLongLTy, 1)); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 694 |   Builder.CreateStore(Counter, CounterPtr); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 695 |  | 
| Daniel Dunbar | 55e8742 | 2008-11-11 02:29:29 +0000 | [diff] [blame] | 696 |   llvm::BasicBlock *LoopEnd = createBasicBlock("loopend"); | 
 | 697 |   llvm::BasicBlock *AfterBody = createBasicBlock("afterbody"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 698 |  | 
| Anders Carlsson | e4b6d34 | 2009-02-10 05:52:02 +0000 | [diff] [blame] | 699 |   BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody)); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 700 |  | 
 | 701 |   EmitStmt(S.getBody()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 702 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 703 |   BreakContinueStack.pop_back(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 704 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 705 |   EmitBlock(AfterBody); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 706 |  | 
| Daniel Dunbar | 55e8742 | 2008-11-11 02:29:29 +0000 | [diff] [blame] | 707 |   llvm::BasicBlock *FetchMore = createBasicBlock("fetchmore"); | 
| Fariborz Jahanian | f0906c4 | 2009-01-06 18:56:31 +0000 | [diff] [blame] | 708 |  | 
 | 709 |   Counter = Builder.CreateLoad(CounterPtr); | 
 | 710 |   Limit = Builder.CreateLoad(LimitPtr); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 711 |   llvm::Value *IsLess = Builder.CreateICmpULT(Counter, Limit, "isless"); | 
| Daniel Dunbar | fe2b2c0 | 2008-09-04 21:54:37 +0000 | [diff] [blame] | 712 |   Builder.CreateCondBr(IsLess, LoopBody, FetchMore); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 713 |  | 
 | 714 |   // Fetch more elements. | 
 | 715 |   EmitBlock(FetchMore); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 716 |  | 
 | 717 |   CountRV = | 
 | 718 |     CGM.getObjCRuntime().GenerateMessageSend(*this, | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 719 |                                              getContext().UnsignedLongTy, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 720 |                                              FastEnumSel, | 
| David Chisnall | c6cd5fd | 2010-04-28 19:33:36 +0000 | [diff] [blame^] | 721 |                                              Collection, Args); | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 722 |   Builder.CreateStore(CountRV.getScalarVal(), LimitPtr); | 
 | 723 |   Limit = Builder.CreateLoad(LimitPtr); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 724 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 725 |   IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero"); | 
 | 726 |   Builder.CreateCondBr(IsZero, NoElements, LoopStart); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 727 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 728 |   // No more elements. | 
 | 729 |   EmitBlock(NoElements); | 
 | 730 |  | 
 | 731 |   if (!DeclAddress) { | 
 | 732 |     // If the element was not a declaration, set it to be null. | 
 | 733 |  | 
 | 734 |     LValue LV = EmitLValue(cast<Expr>(S.getElement())); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 735 |  | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 736 |     // Set the value to null. | 
| Owen Anderson | c9c88b4 | 2009-07-31 20:28:54 +0000 | [diff] [blame] | 737 |     Builder.CreateStore(llvm::Constant::getNullValue(ConvertType(ElementTy)), | 
| Anders Carlsson | f484c31 | 2008-08-31 02:33:12 +0000 | [diff] [blame] | 738 |                         LV.getAddress()); | 
 | 739 |   } | 
 | 740 |  | 
 | 741 |   EmitBlock(LoopEnd); | 
| Anders Carlsson | 3d8400d | 2008-08-30 19:51:14 +0000 | [diff] [blame] | 742 | } | 
 | 743 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 744 | void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) { | 
| Fariborz Jahanian | bd71be4 | 2008-11-21 00:49:24 +0000 | [diff] [blame] | 745 |   CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S); | 
| Anders Carlsson | 64d5d6c | 2008-09-09 10:04:29 +0000 | [diff] [blame] | 746 | } | 
 | 747 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 748 | void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) { | 
| Anders Carlsson | 64d5d6c | 2008-09-09 10:04:29 +0000 | [diff] [blame] | 749 |   CGM.getObjCRuntime().EmitThrowStmt(*this, S); | 
 | 750 | } | 
 | 751 |  | 
| Chris Lattner | 10cac6f | 2008-11-15 21:26:17 +0000 | [diff] [blame] | 752 | void CodeGenFunction::EmitObjCAtSynchronizedStmt( | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 753 |                                               const ObjCAtSynchronizedStmt &S) { | 
| Fariborz Jahanian | bd71be4 | 2008-11-21 00:49:24 +0000 | [diff] [blame] | 754 |   CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S); | 
| Chris Lattner | 10cac6f | 2008-11-15 21:26:17 +0000 | [diff] [blame] | 755 | } | 
 | 756 |  | 
| Ted Kremenek | 2979ec7 | 2008-04-09 15:51:31 +0000 | [diff] [blame] | 757 | CGObjCRuntime::~CGObjCRuntime() {} |