12437cbfaSAnders Carlsson //===--- CGBlocks.cpp - Emit LLVM Code for declarations -------------------===// 22437cbfaSAnders Carlsson // 32437cbfaSAnders Carlsson // The LLVM Compiler Infrastructure 42437cbfaSAnders Carlsson // 52437cbfaSAnders Carlsson // This file is distributed under the University of Illinois Open Source 62437cbfaSAnders Carlsson // License. See LICENSE.TXT for details. 72437cbfaSAnders Carlsson // 82437cbfaSAnders Carlsson //===----------------------------------------------------------------------===// 92437cbfaSAnders Carlsson // 102437cbfaSAnders Carlsson // This contains code to emit blocks. 112437cbfaSAnders Carlsson // 122437cbfaSAnders Carlsson //===----------------------------------------------------------------------===// 132437cbfaSAnders Carlsson 14ad7c5c16SJohn McCall #include "CGBlocks.h" 153a02247dSChandler Carruth #include "CGDebugInfo.h" 163a02247dSChandler Carruth #include "CGObjCRuntime.h" 173a02247dSChandler Carruth #include "CodeGenFunction.h" 183a02247dSChandler Carruth #include "CodeGenModule.h" 19692c6e37SMike Stump #include "clang/AST/DeclObjC.h" 209e2e1c90SBenjamin Kramer #include "llvm/ADT/SmallSet.h" 21c80ceea9SChandler Carruth #include "llvm/IR/CallSite.h" 22ffd5551bSChandler Carruth #include "llvm/IR/DataLayout.h" 23ffd5551bSChandler Carruth #include "llvm/IR/Module.h" 242437cbfaSAnders Carlsson #include <algorithm> 25983ae49aSFariborz Jahanian #include <cstdio> 26db714924STorok Edwin 272437cbfaSAnders Carlsson using namespace clang; 282437cbfaSAnders Carlsson using namespace CodeGen; 292437cbfaSAnders Carlsson 3008ef4660SJohn McCall CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name) 3108ef4660SJohn McCall : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), 3223290b05SFariborz Jahanian HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false), 3323290b05SFariborz Jahanian StructureType(0), Block(block), 34f4beacd0SJohn McCall DominatingIP(0) { 359d42f0f1SJohn McCall 3608ef4660SJohn McCall // Skip asm prefix, if any. 'name' is usually taken directly from 3708ef4660SJohn McCall // the mangled name of the enclosing function. 3808ef4660SJohn McCall if (!name.empty() && name[0] == '\01') 3908ef4660SJohn McCall name = name.substr(1); 409d42f0f1SJohn McCall } 419d42f0f1SJohn McCall 42f9b056b0SJohn McCall // Anchor the vtable to this translation unit. 43f9b056b0SJohn McCall CodeGenModule::ByrefHelpers::~ByrefHelpers() {} 44f9b056b0SJohn McCall 45351762cdSJohn McCall /// Build the given block as a global block. 46351762cdSJohn McCall static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, 47351762cdSJohn McCall const CGBlockInfo &blockInfo, 48351762cdSJohn McCall llvm::Constant *blockFn); 499d42f0f1SJohn McCall 50351762cdSJohn McCall /// Build the helper function to copy a block. 51351762cdSJohn McCall static llvm::Constant *buildCopyHelper(CodeGenModule &CGM, 52351762cdSJohn McCall const CGBlockInfo &blockInfo) { 53351762cdSJohn McCall return CodeGenFunction(CGM).GenerateCopyHelperFunction(blockInfo); 54351762cdSJohn McCall } 55351762cdSJohn McCall 56f6a24ce4SAlp Toker /// Build the helper function to dispose of a block. 57351762cdSJohn McCall static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM, 58351762cdSJohn McCall const CGBlockInfo &blockInfo) { 59351762cdSJohn McCall return CodeGenFunction(CGM).GenerateDestroyHelperFunction(blockInfo); 60351762cdSJohn McCall } 61351762cdSJohn McCall 62bf7bf291SFariborz Jahanian /// buildBlockDescriptor - Build the block descriptor meta-data for a block. 63bf7bf291SFariborz Jahanian /// buildBlockDescriptor is accessed from 5th field of the Block_literal 64bf7bf291SFariborz Jahanian /// meta-data and contains stationary information about the block literal. 65bf7bf291SFariborz Jahanian /// Its definition will have 4 (or optinally 6) words. 666c96ba2dSDmitri Gribenko /// \code 67bf7bf291SFariborz Jahanian /// struct Block_descriptor { 68bf7bf291SFariborz Jahanian /// unsigned long reserved; 69bf7bf291SFariborz Jahanian /// unsigned long size; // size of Block_literal metadata in bytes. 70bf7bf291SFariborz Jahanian /// void *copy_func_helper_decl; // optional copy helper. 71bf7bf291SFariborz Jahanian /// void *destroy_func_decl; // optioanl destructor helper. 726c96ba2dSDmitri Gribenko /// void *block_method_encoding_address; // @encode for block literal signature. 73bf7bf291SFariborz Jahanian /// void *block_layout_info; // encoding of captured block variables. 74bf7bf291SFariborz Jahanian /// }; 756c96ba2dSDmitri Gribenko /// \endcode 76351762cdSJohn McCall static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM, 77351762cdSJohn McCall const CGBlockInfo &blockInfo) { 78351762cdSJohn McCall ASTContext &C = CGM.getContext(); 79351762cdSJohn McCall 802192fe50SChris Lattner llvm::Type *ulong = CGM.getTypes().ConvertType(C.UnsignedLongTy); 812192fe50SChris Lattner llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy); 82351762cdSJohn McCall 830e62c1ccSChris Lattner SmallVector<llvm::Constant*, 6> elements; 8485284bacSMike Stump 8585284bacSMike Stump // reserved 86351762cdSJohn McCall elements.push_back(llvm::ConstantInt::get(ulong, 0)); 8785284bacSMike Stump 8885284bacSMike Stump // Size 892ac40a9fSMike Stump // FIXME: What is the right way to say this doesn't fit? We should give 902ac40a9fSMike Stump // a user diagnostic in that case. Better fix would be to change the 912ac40a9fSMike Stump // API to size_t. 92351762cdSJohn McCall elements.push_back(llvm::ConstantInt::get(ulong, 93351762cdSJohn McCall blockInfo.BlockSize.getQuantity())); 9485284bacSMike Stump 95351762cdSJohn McCall // Optional copy/dispose helpers. 96351762cdSJohn McCall if (blockInfo.NeedsCopyDispose) { 9785284bacSMike Stump // copy_func_helper_decl 98351762cdSJohn McCall elements.push_back(buildCopyHelper(CGM, blockInfo)); 9985284bacSMike Stump 10085284bacSMike Stump // destroy_func_decl 101351762cdSJohn McCall elements.push_back(buildDisposeHelper(CGM, blockInfo)); 10285284bacSMike Stump } 10385284bacSMike Stump 104351762cdSJohn McCall // Signature. Mandatory ObjC-style method descriptor @encode sequence. 105351762cdSJohn McCall std::string typeAtEncoding = 106351762cdSJohn McCall CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr()); 107351762cdSJohn McCall elements.push_back(llvm::ConstantExpr::getBitCast( 108351762cdSJohn McCall CGM.GetAddrOfConstantCString(typeAtEncoding), i8p)); 109fc83aa04SBlaine Garst 110351762cdSJohn McCall // GC layout. 1110c58ce93SFariborz Jahanian if (C.getLangOpts().ObjC1) { 1120c58ce93SFariborz Jahanian if (CGM.getLangOpts().getGC() != LangOptions::NonGC) 113351762cdSJohn McCall elements.push_back(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo)); 114351762cdSJohn McCall else 1150c58ce93SFariborz Jahanian elements.push_back(CGM.getObjCRuntime().BuildRCBlockLayout(CGM, blockInfo)); 1160c58ce93SFariborz Jahanian } 1170c58ce93SFariborz Jahanian else 118351762cdSJohn McCall elements.push_back(llvm::Constant::getNullValue(i8p)); 119fc83aa04SBlaine Garst 120e64d7ba1SChris Lattner llvm::Constant *init = llvm::ConstantStruct::getAnon(elements); 121c05349e5SFariborz Jahanian 122351762cdSJohn McCall llvm::GlobalVariable *global = 123351762cdSJohn McCall new llvm::GlobalVariable(CGM.getModule(), init->getType(), true, 12485284bacSMike Stump llvm::GlobalValue::InternalLinkage, 125351762cdSJohn McCall init, "__block_descriptor_tmp"); 12685284bacSMike Stump 127351762cdSJohn McCall return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType()); 128ed5e69feSAnders Carlsson } 129ed5e69feSAnders Carlsson 130351762cdSJohn McCall /* 131351762cdSJohn McCall Purely notional variadic template describing the layout of a block. 132ed5e69feSAnders Carlsson 133351762cdSJohn McCall template <class _ResultType, class... _ParamTypes, class... _CaptureTypes> 134351762cdSJohn McCall struct Block_literal { 135351762cdSJohn McCall /// Initialized to one of: 136351762cdSJohn McCall /// extern void *_NSConcreteStackBlock[]; 137351762cdSJohn McCall /// extern void *_NSConcreteGlobalBlock[]; 138351762cdSJohn McCall /// 139351762cdSJohn McCall /// In theory, we could start one off malloc'ed by setting 140351762cdSJohn McCall /// BLOCK_NEEDS_FREE, giving it a refcount of 1, and using 141351762cdSJohn McCall /// this isa: 142351762cdSJohn McCall /// extern void *_NSConcreteMallocBlock[]; 143351762cdSJohn McCall struct objc_class *isa; 14485284bacSMike Stump 145351762cdSJohn McCall /// These are the flags (with corresponding bit number) that the 146351762cdSJohn McCall /// compiler is actually supposed to know about. 147351762cdSJohn McCall /// 25. BLOCK_HAS_COPY_DISPOSE - indicates that the block 148351762cdSJohn McCall /// descriptor provides copy and dispose helper functions 149351762cdSJohn McCall /// 26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured 150351762cdSJohn McCall /// object with a nontrivial destructor or copy constructor 151351762cdSJohn McCall /// 28. BLOCK_IS_GLOBAL - indicates that the block is allocated 152351762cdSJohn McCall /// as global memory 153351762cdSJohn McCall /// 29. BLOCK_USE_STRET - indicates that the block function 154351762cdSJohn McCall /// uses stret, which objc_msgSend needs to know about 155351762cdSJohn McCall /// 30. BLOCK_HAS_SIGNATURE - indicates that the block has an 156351762cdSJohn McCall /// @encoded signature string 157351762cdSJohn McCall /// And we're not supposed to manipulate these: 158351762cdSJohn McCall /// 24. BLOCK_NEEDS_FREE - indicates that the block has been moved 159351762cdSJohn McCall /// to malloc'ed memory 160351762cdSJohn McCall /// 27. BLOCK_IS_GC - indicates that the block has been moved to 161351762cdSJohn McCall /// to GC-allocated memory 162351762cdSJohn McCall /// Additionally, the bottom 16 bits are a reference count which 163351762cdSJohn McCall /// should be zero on the stack. 164351762cdSJohn McCall int flags; 165950a9518SDavid Chisnall 166351762cdSJohn McCall /// Reserved; should be zero-initialized. 167351762cdSJohn McCall int reserved; 168950a9518SDavid Chisnall 169351762cdSJohn McCall /// Function pointer generated from block literal. 170351762cdSJohn McCall _ResultType (*invoke)(Block_literal *, _ParamTypes...); 17185284bacSMike Stump 172351762cdSJohn McCall /// Block description metadata generated from block literal. 173351762cdSJohn McCall struct Block_descriptor *block_descriptor; 1743882ace2SJohn McCall 175351762cdSJohn McCall /// Captured values follow. 176351762cdSJohn McCall _CapturesTypes captures...; 177351762cdSJohn McCall }; 178351762cdSJohn McCall */ 179950a9518SDavid Chisnall 180351762cdSJohn McCall /// The number of fields in a block header. 181351762cdSJohn McCall const unsigned BlockHeaderSize = 5; 1824446dcf0SMike Stump 183351762cdSJohn McCall namespace { 184351762cdSJohn McCall /// A chunk of data that we actually have to capture in the block. 185351762cdSJohn McCall struct BlockLayoutChunk { 186351762cdSJohn McCall CharUnits Alignment; 187351762cdSJohn McCall CharUnits Size; 188c8892055SFariborz Jahanian Qualifiers::ObjCLifetime Lifetime; 189351762cdSJohn McCall const BlockDecl::Capture *Capture; // null for 'this' 1907c57be3eSJay Foad llvm::Type *Type; 19185284bacSMike Stump 192351762cdSJohn McCall BlockLayoutChunk(CharUnits align, CharUnits size, 193c8892055SFariborz Jahanian Qualifiers::ObjCLifetime lifetime, 194351762cdSJohn McCall const BlockDecl::Capture *capture, 1957c57be3eSJay Foad llvm::Type *type) 196c8892055SFariborz Jahanian : Alignment(align), Size(size), Lifetime(lifetime), 197c8892055SFariborz Jahanian Capture(capture), Type(type) {} 19885284bacSMike Stump 199351762cdSJohn McCall /// Tell the block info that this chunk has the given field index. 200351762cdSJohn McCall void setIndex(CGBlockInfo &info, unsigned index) { 201351762cdSJohn McCall if (!Capture) 202351762cdSJohn McCall info.CXXThisIndex = index; 203b750d928SMike Stump else 204351762cdSJohn McCall info.Captures[Capture->getVariable()] 205351762cdSJohn McCall = CGBlockInfo::Capture::makeIndex(index); 206b750d928SMike Stump } 207351762cdSJohn McCall }; 208d6ef62f0SMike Stump 209c8892055SFariborz Jahanian /// Order by 1) all __strong together 2) next, all byfref together 3) next, 210c8892055SFariborz Jahanian /// all __weak together. Preserve descending alignment in all situations. 211351762cdSJohn McCall bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) { 212c8892055SFariborz Jahanian CharUnits LeftValue, RightValue; 213c8892055SFariborz Jahanian bool LeftByref = left.Capture ? left.Capture->isByRef() : false; 214c8892055SFariborz Jahanian bool RightByref = right.Capture ? right.Capture->isByRef() : false; 215c8892055SFariborz Jahanian 216c8892055SFariborz Jahanian if (left.Lifetime == Qualifiers::OCL_Strong && 217c8892055SFariborz Jahanian left.Alignment >= right.Alignment) 218c8892055SFariborz Jahanian LeftValue = CharUnits::fromQuantity(64); 219c8892055SFariborz Jahanian else if (LeftByref && left.Alignment >= right.Alignment) 220c8892055SFariborz Jahanian LeftValue = CharUnits::fromQuantity(32); 221c8892055SFariborz Jahanian else if (left.Lifetime == Qualifiers::OCL_Weak && 222c8892055SFariborz Jahanian left.Alignment >= right.Alignment) 223c8892055SFariborz Jahanian LeftValue = CharUnits::fromQuantity(16); 224c8892055SFariborz Jahanian else 225c8892055SFariborz Jahanian LeftValue = left.Alignment; 226c8892055SFariborz Jahanian if (right.Lifetime == Qualifiers::OCL_Strong && 227c8892055SFariborz Jahanian right.Alignment >= left.Alignment) 228c8892055SFariborz Jahanian RightValue = CharUnits::fromQuantity(64); 229c8892055SFariborz Jahanian else if (RightByref && right.Alignment >= left.Alignment) 230c8892055SFariborz Jahanian RightValue = CharUnits::fromQuantity(32); 231c8892055SFariborz Jahanian else if (right.Lifetime == Qualifiers::OCL_Weak && 232c8892055SFariborz Jahanian right.Alignment >= left.Alignment) 233c8892055SFariborz Jahanian RightValue = CharUnits::fromQuantity(16); 234c8892055SFariborz Jahanian else 235c8892055SFariborz Jahanian RightValue = right.Alignment; 236c8892055SFariborz Jahanian 237c8892055SFariborz Jahanian return LeftValue > RightValue; 238351762cdSJohn McCall } 239b750d928SMike Stump } 240b750d928SMike Stump 241b0a3ecb4SJohn McCall /// Determines if the given type is safe for constant capture in C++. 242b0a3ecb4SJohn McCall static bool isSafeForCXXConstantCapture(QualType type) { 243b0a3ecb4SJohn McCall const RecordType *recordType = 244b0a3ecb4SJohn McCall type->getBaseElementTypeUnsafe()->getAs<RecordType>(); 245b0a3ecb4SJohn McCall 246b0a3ecb4SJohn McCall // Only records can be unsafe. 247b0a3ecb4SJohn McCall if (!recordType) return true; 248b0a3ecb4SJohn McCall 249b0a3ecb4SJohn McCall const CXXRecordDecl *record = cast<CXXRecordDecl>(recordType->getDecl()); 250b0a3ecb4SJohn McCall 251b0a3ecb4SJohn McCall // Maintain semantics for classes with non-trivial dtors or copy ctors. 252b0a3ecb4SJohn McCall if (!record->hasTrivialDestructor()) return false; 25316488472SRichard Smith if (record->hasNonTrivialCopyConstructor()) return false; 254b0a3ecb4SJohn McCall 255b0a3ecb4SJohn McCall // Otherwise, we just have to make sure there aren't any mutable 256b0a3ecb4SJohn McCall // fields that might have changed since initialization. 25761226d3fSDouglas Gregor return !record->hasMutableFields(); 258b0a3ecb4SJohn McCall } 259b0a3ecb4SJohn McCall 260351762cdSJohn McCall /// It is illegal to modify a const object after initialization. 261351762cdSJohn McCall /// Therefore, if a const object has a constant initializer, we don't 262351762cdSJohn McCall /// actually need to keep storage for it in the block; we'll just 263351762cdSJohn McCall /// rematerialize it at the start of the block function. This is 264351762cdSJohn McCall /// acceptable because we make no promises about address stability of 265351762cdSJohn McCall /// captured variables. 266351762cdSJohn McCall static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM, 267dafff947SRichard Smith CodeGenFunction *CGF, 268351762cdSJohn McCall const VarDecl *var) { 269351762cdSJohn McCall QualType type = var->getType(); 270351762cdSJohn McCall 271351762cdSJohn McCall // We can only do this if the variable is const. 272351762cdSJohn McCall if (!type.isConstQualified()) return 0; 273351762cdSJohn McCall 274b0a3ecb4SJohn McCall // Furthermore, in C++ we have to worry about mutable fields: 275b0a3ecb4SJohn McCall // C++ [dcl.type.cv]p4: 276b0a3ecb4SJohn McCall // Except that any class member declared mutable can be 277b0a3ecb4SJohn McCall // modified, any attempt to modify a const object during its 278b0a3ecb4SJohn McCall // lifetime results in undefined behavior. 279bbafb8a7SDavid Blaikie if (CGM.getLangOpts().CPlusPlus && !isSafeForCXXConstantCapture(type)) 280351762cdSJohn McCall return 0; 281351762cdSJohn McCall 282351762cdSJohn McCall // If the variable doesn't have any initializer (shouldn't this be 283351762cdSJohn McCall // invalid?), it's not clear what we should do. Maybe capture as 284351762cdSJohn McCall // zero? 285351762cdSJohn McCall const Expr *init = var->getInit(); 286351762cdSJohn McCall if (!init) return 0; 287351762cdSJohn McCall 288dafff947SRichard Smith return CGM.EmitConstantInit(*var, CGF); 289351762cdSJohn McCall } 290351762cdSJohn McCall 291351762cdSJohn McCall /// Get the low bit of a nonzero character count. This is the 292351762cdSJohn McCall /// alignment of the nth byte if the 0th byte is universally aligned. 293351762cdSJohn McCall static CharUnits getLowBit(CharUnits v) { 294351762cdSJohn McCall return CharUnits::fromQuantity(v.getQuantity() & (~v.getQuantity() + 1)); 295351762cdSJohn McCall } 296351762cdSJohn McCall 297351762cdSJohn McCall static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info, 2980e62c1ccSChris Lattner SmallVectorImpl<llvm::Type*> &elementTypes) { 299351762cdSJohn McCall ASTContext &C = CGM.getContext(); 300351762cdSJohn McCall 301351762cdSJohn McCall // The header is basically a 'struct { void *; int; int; void *; void *; }'. 302351762cdSJohn McCall CharUnits ptrSize, ptrAlign, intSize, intAlign; 303867ea1d4SBenjamin Kramer std::tie(ptrSize, ptrAlign) = C.getTypeInfoInChars(C.VoidPtrTy); 304867ea1d4SBenjamin Kramer std::tie(intSize, intAlign) = C.getTypeInfoInChars(C.IntTy); 305351762cdSJohn McCall 306351762cdSJohn McCall // Are there crazy embedded platforms where this isn't true? 307351762cdSJohn McCall assert(intSize <= ptrSize && "layout assumptions horribly violated"); 308351762cdSJohn McCall 309351762cdSJohn McCall CharUnits headerSize = ptrSize; 310351762cdSJohn McCall if (2 * intSize < ptrAlign) headerSize += ptrSize; 311351762cdSJohn McCall else headerSize += 2 * intSize; 312351762cdSJohn McCall headerSize += 2 * ptrSize; 313351762cdSJohn McCall 314351762cdSJohn McCall info.BlockAlign = ptrAlign; 315351762cdSJohn McCall info.BlockSize = headerSize; 316351762cdSJohn McCall 317351762cdSJohn McCall assert(elementTypes.empty()); 3187c57be3eSJay Foad llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy); 3197c57be3eSJay Foad llvm::Type *intTy = CGM.getTypes().ConvertType(C.IntTy); 320351762cdSJohn McCall elementTypes.push_back(i8p); 321351762cdSJohn McCall elementTypes.push_back(intTy); 322351762cdSJohn McCall elementTypes.push_back(intTy); 323351762cdSJohn McCall elementTypes.push_back(i8p); 324351762cdSJohn McCall elementTypes.push_back(CGM.getBlockDescriptorType()); 325351762cdSJohn McCall 326351762cdSJohn McCall assert(elementTypes.size() == BlockHeaderSize); 327351762cdSJohn McCall } 328351762cdSJohn McCall 329351762cdSJohn McCall /// Compute the layout of the given block. Attempts to lay the block 330351762cdSJohn McCall /// out with minimal space requirements. 331dafff947SRichard Smith static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, 332dafff947SRichard Smith CGBlockInfo &info) { 333351762cdSJohn McCall ASTContext &C = CGM.getContext(); 334351762cdSJohn McCall const BlockDecl *block = info.getBlockDecl(); 335351762cdSJohn McCall 3360e62c1ccSChris Lattner SmallVector<llvm::Type*, 8> elementTypes; 337351762cdSJohn McCall initializeForBlockHeader(CGM, info, elementTypes); 338351762cdSJohn McCall 339351762cdSJohn McCall if (!block->hasCaptures()) { 340351762cdSJohn McCall info.StructureType = 341351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 342351762cdSJohn McCall info.CanBeGlobal = true; 343351762cdSJohn McCall return; 344351762cdSJohn McCall } 34523290b05SFariborz Jahanian else if (C.getLangOpts().ObjC1 && 34623290b05SFariborz Jahanian CGM.getLangOpts().getGC() == LangOptions::NonGC) 34723290b05SFariborz Jahanian info.HasCapturedVariableLayout = true; 348351762cdSJohn McCall 349351762cdSJohn McCall // Collect the layout chunks. 3500e62c1ccSChris Lattner SmallVector<BlockLayoutChunk, 16> layout; 351351762cdSJohn McCall layout.reserve(block->capturesCXXThis() + 352351762cdSJohn McCall (block->capture_end() - block->capture_begin())); 353351762cdSJohn McCall 354351762cdSJohn McCall CharUnits maxFieldAlign; 355351762cdSJohn McCall 356351762cdSJohn McCall // First, 'this'. 357351762cdSJohn McCall if (block->capturesCXXThis()) { 358c6036aa8SEli Friedman assert(CGF && CGF->CurFuncDecl && isa<CXXMethodDecl>(CGF->CurFuncDecl) && 359c6036aa8SEli Friedman "Can't capture 'this' outside a method"); 360c6036aa8SEli Friedman QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType(C); 361351762cdSJohn McCall 3627c57be3eSJay Foad llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType); 363351762cdSJohn McCall std::pair<CharUnits,CharUnits> tinfo 364351762cdSJohn McCall = CGM.getContext().getTypeInfoInChars(thisType); 365351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, tinfo.second); 366351762cdSJohn McCall 367c8892055SFariborz Jahanian layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, 368c8892055SFariborz Jahanian Qualifiers::OCL_None, 369c8892055SFariborz Jahanian 0, llvmType)); 370351762cdSJohn McCall } 371351762cdSJohn McCall 372351762cdSJohn McCall // Next, all the block captures. 373351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 374351762cdSJohn McCall ce = block->capture_end(); ci != ce; ++ci) { 375351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 376351762cdSJohn McCall 377351762cdSJohn McCall if (ci->isByRef()) { 378351762cdSJohn McCall // We have to copy/dispose of the __block reference. 379351762cdSJohn McCall info.NeedsCopyDispose = true; 380351762cdSJohn McCall 381351762cdSJohn McCall // Just use void* instead of a pointer to the byref type. 382351762cdSJohn McCall QualType byRefPtrTy = C.VoidPtrTy; 383351762cdSJohn McCall 3847c57be3eSJay Foad llvm::Type *llvmType = CGM.getTypes().ConvertType(byRefPtrTy); 385351762cdSJohn McCall std::pair<CharUnits,CharUnits> tinfo 386351762cdSJohn McCall = CGM.getContext().getTypeInfoInChars(byRefPtrTy); 387351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, tinfo.second); 388351762cdSJohn McCall 389351762cdSJohn McCall layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, 390c8892055SFariborz Jahanian Qualifiers::OCL_None, 391351762cdSJohn McCall &*ci, llvmType)); 392351762cdSJohn McCall continue; 393351762cdSJohn McCall } 394351762cdSJohn McCall 395351762cdSJohn McCall // Otherwise, build a layout chunk with the size and alignment of 396351762cdSJohn McCall // the declaration. 397dafff947SRichard Smith if (llvm::Constant *constant = tryCaptureAsConstant(CGM, CGF, variable)) { 398351762cdSJohn McCall info.Captures[variable] = CGBlockInfo::Capture::makeConstant(constant); 399351762cdSJohn McCall continue; 400351762cdSJohn McCall } 401351762cdSJohn McCall 40231168b07SJohn McCall // If we have a lifetime qualifier, honor it for capture purposes. 40331168b07SJohn McCall // That includes *not* copying it if it's __unsafe_unretained. 404c8892055SFariborz Jahanian Qualifiers::ObjCLifetime lifetime = 405c8892055SFariborz Jahanian variable->getType().getObjCLifetime(); 406c8892055SFariborz Jahanian if (lifetime) { 40731168b07SJohn McCall switch (lifetime) { 40831168b07SJohn McCall case Qualifiers::OCL_None: llvm_unreachable("impossible"); 40931168b07SJohn McCall case Qualifiers::OCL_ExplicitNone: 41031168b07SJohn McCall case Qualifiers::OCL_Autoreleasing: 41131168b07SJohn McCall break; 412351762cdSJohn McCall 41331168b07SJohn McCall case Qualifiers::OCL_Strong: 41431168b07SJohn McCall case Qualifiers::OCL_Weak: 41531168b07SJohn McCall info.NeedsCopyDispose = true; 41631168b07SJohn McCall } 41731168b07SJohn McCall 41831168b07SJohn McCall // Block pointers require copy/dispose. So do Objective-C pointers. 41931168b07SJohn McCall } else if (variable->getType()->isObjCRetainableType()) { 420351762cdSJohn McCall info.NeedsCopyDispose = true; 421c8892055SFariborz Jahanian // used for mrr below. 422c8892055SFariborz Jahanian lifetime = Qualifiers::OCL_Strong; 423351762cdSJohn McCall 424351762cdSJohn McCall // So do types that require non-trivial copy construction. 425351762cdSJohn McCall } else if (ci->hasCopyExpr()) { 426351762cdSJohn McCall info.NeedsCopyDispose = true; 427351762cdSJohn McCall info.HasCXXObject = true; 428351762cdSJohn McCall 429351762cdSJohn McCall // And so do types with destructors. 430bbafb8a7SDavid Blaikie } else if (CGM.getLangOpts().CPlusPlus) { 431351762cdSJohn McCall if (const CXXRecordDecl *record = 432351762cdSJohn McCall variable->getType()->getAsCXXRecordDecl()) { 433351762cdSJohn McCall if (!record->hasTrivialDestructor()) { 434351762cdSJohn McCall info.HasCXXObject = true; 435351762cdSJohn McCall info.NeedsCopyDispose = true; 436351762cdSJohn McCall } 437351762cdSJohn McCall } 438351762cdSJohn McCall } 439351762cdSJohn McCall 44010317eaaSFariborz Jahanian QualType VT = variable->getType(); 441f0cda639SFariborz Jahanian CharUnits size = C.getTypeSizeInChars(VT); 44210317eaaSFariborz Jahanian CharUnits align = C.getDeclAlign(variable); 443f0cda639SFariborz Jahanian 444351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, align); 445351762cdSJohn McCall 4467c57be3eSJay Foad llvm::Type *llvmType = 447f0cda639SFariborz Jahanian CGM.getTypes().ConvertTypeForMem(VT); 448351762cdSJohn McCall 449c8892055SFariborz Jahanian layout.push_back(BlockLayoutChunk(align, size, lifetime, &*ci, llvmType)); 450351762cdSJohn McCall } 451351762cdSJohn McCall 452351762cdSJohn McCall // If that was everything, we're done here. 453351762cdSJohn McCall if (layout.empty()) { 454351762cdSJohn McCall info.StructureType = 455351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 456351762cdSJohn McCall info.CanBeGlobal = true; 457351762cdSJohn McCall return; 458351762cdSJohn McCall } 459351762cdSJohn McCall 460351762cdSJohn McCall // Sort the layout by alignment. We have to use a stable sort here 461351762cdSJohn McCall // to get reproducible results. There should probably be an 462351762cdSJohn McCall // llvm::array_pod_stable_sort. 463351762cdSJohn McCall std::stable_sort(layout.begin(), layout.end()); 464351762cdSJohn McCall 4654cf177e2SFariborz Jahanian // Needed for blocks layout info. 4664cf177e2SFariborz Jahanian info.BlockHeaderForcedGapOffset = info.BlockSize; 4674cf177e2SFariborz Jahanian info.BlockHeaderForcedGapSize = CharUnits::Zero(); 4684cf177e2SFariborz Jahanian 469351762cdSJohn McCall CharUnits &blockSize = info.BlockSize; 470351762cdSJohn McCall info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign); 471351762cdSJohn McCall 472351762cdSJohn McCall // Assuming that the first byte in the header is maximally aligned, 473351762cdSJohn McCall // get the alignment of the first byte following the header. 474351762cdSJohn McCall CharUnits endAlign = getLowBit(blockSize); 475351762cdSJohn McCall 476351762cdSJohn McCall // If the end of the header isn't satisfactorily aligned for the 477351762cdSJohn McCall // maximum thing, look for things that are okay with the header-end 478351762cdSJohn McCall // alignment, and keep appending them until we get something that's 479351762cdSJohn McCall // aligned right. This algorithm is only guaranteed optimal if 480351762cdSJohn McCall // that condition is satisfied at some point; otherwise we can get 481351762cdSJohn McCall // things like: 482351762cdSJohn McCall // header // next byte has alignment 4 483351762cdSJohn McCall // something_with_size_5; // next byte has alignment 1 484351762cdSJohn McCall // something_with_alignment_8; 485351762cdSJohn McCall // which has 7 bytes of padding, as opposed to the naive solution 486351762cdSJohn McCall // which might have less (?). 487351762cdSJohn McCall if (endAlign < maxFieldAlign) { 4880e62c1ccSChris Lattner SmallVectorImpl<BlockLayoutChunk>::iterator 489351762cdSJohn McCall li = layout.begin() + 1, le = layout.end(); 490351762cdSJohn McCall 491351762cdSJohn McCall // Look for something that the header end is already 492351762cdSJohn McCall // satisfactorily aligned for. 493351762cdSJohn McCall for (; li != le && endAlign < li->Alignment; ++li) 494351762cdSJohn McCall ; 495351762cdSJohn McCall 496351762cdSJohn McCall // If we found something that's naturally aligned for the end of 497351762cdSJohn McCall // the header, keep adding things... 498351762cdSJohn McCall if (li != le) { 4990e62c1ccSChris Lattner SmallVectorImpl<BlockLayoutChunk>::iterator first = li; 500351762cdSJohn McCall for (; li != le; ++li) { 501351762cdSJohn McCall assert(endAlign >= li->Alignment); 502351762cdSJohn McCall 503351762cdSJohn McCall li->setIndex(info, elementTypes.size()); 504351762cdSJohn McCall elementTypes.push_back(li->Type); 505351762cdSJohn McCall blockSize += li->Size; 506351762cdSJohn McCall endAlign = getLowBit(blockSize); 507351762cdSJohn McCall 508351762cdSJohn McCall // ...until we get to the alignment of the maximum field. 5094cf177e2SFariborz Jahanian if (endAlign >= maxFieldAlign) { 5104cf177e2SFariborz Jahanian if (li == first) { 5114cf177e2SFariborz Jahanian // No user field was appended. So, a gap was added. 5124cf177e2SFariborz Jahanian // Save total gap size for use in block layout bit map. 5134cf177e2SFariborz Jahanian info.BlockHeaderForcedGapSize = li->Size; 5144cf177e2SFariborz Jahanian } 515351762cdSJohn McCall break; 516351762cdSJohn McCall } 5174cf177e2SFariborz Jahanian } 518351762cdSJohn McCall // Don't re-append everything we just appended. 519351762cdSJohn McCall layout.erase(first, li); 520351762cdSJohn McCall } 521351762cdSJohn McCall } 522351762cdSJohn McCall 523ac0350a3SJohn McCall assert(endAlign == getLowBit(blockSize)); 524ac0350a3SJohn McCall 525351762cdSJohn McCall // At this point, we just have to add padding if the end align still 526351762cdSJohn McCall // isn't aligned right. 527351762cdSJohn McCall if (endAlign < maxFieldAlign) { 528ac0350a3SJohn McCall CharUnits newBlockSize = blockSize.RoundUpToAlignment(maxFieldAlign); 529ac0350a3SJohn McCall CharUnits padding = newBlockSize - blockSize; 530351762cdSJohn McCall 531e3dc1707SJohn McCall elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty, 532e3dc1707SJohn McCall padding.getQuantity())); 533ac0350a3SJohn McCall blockSize = newBlockSize; 5341db0a2faSJohn McCall endAlign = getLowBit(blockSize); // might be > maxFieldAlign 535351762cdSJohn McCall } 536351762cdSJohn McCall 5371db0a2faSJohn McCall assert(endAlign >= maxFieldAlign); 538ac0350a3SJohn McCall assert(endAlign == getLowBit(blockSize)); 539351762cdSJohn McCall // Slam everything else on now. This works because they have 540351762cdSJohn McCall // strictly decreasing alignment and we expect that size is always a 541351762cdSJohn McCall // multiple of alignment. 5420e62c1ccSChris Lattner for (SmallVectorImpl<BlockLayoutChunk>::iterator 543351762cdSJohn McCall li = layout.begin(), le = layout.end(); li != le; ++li) { 544351762cdSJohn McCall assert(endAlign >= li->Alignment); 545351762cdSJohn McCall li->setIndex(info, elementTypes.size()); 546351762cdSJohn McCall elementTypes.push_back(li->Type); 547351762cdSJohn McCall blockSize += li->Size; 548351762cdSJohn McCall endAlign = getLowBit(blockSize); 549351762cdSJohn McCall } 550351762cdSJohn McCall 551351762cdSJohn McCall info.StructureType = 552351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 553351762cdSJohn McCall } 554351762cdSJohn McCall 55508ef4660SJohn McCall /// Enter the scope of a block. This should be run at the entrance to 55608ef4660SJohn McCall /// a full-expression so that the block's cleanups are pushed at the 55708ef4660SJohn McCall /// right place in the stack. 55808ef4660SJohn McCall static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) { 5598c38d35bSJohn McCall assert(CGF.HaveInsertPoint()); 5608c38d35bSJohn McCall 56108ef4660SJohn McCall // Allocate the block info and place it at the head of the list. 56208ef4660SJohn McCall CGBlockInfo &blockInfo = 56308ef4660SJohn McCall *new CGBlockInfo(block, CGF.CurFn->getName()); 56408ef4660SJohn McCall blockInfo.NextBlockInfo = CGF.FirstBlockInfo; 56508ef4660SJohn McCall CGF.FirstBlockInfo = &blockInfo; 56608ef4660SJohn McCall 56708ef4660SJohn McCall // Compute information about the layout, etc., of this block, 56808ef4660SJohn McCall // pushing cleanups as necessary. 569dafff947SRichard Smith computeBlockInfo(CGF.CGM, &CGF, blockInfo); 57008ef4660SJohn McCall 57108ef4660SJohn McCall // Nothing else to do if it can be global. 57208ef4660SJohn McCall if (blockInfo.CanBeGlobal) return; 57308ef4660SJohn McCall 57408ef4660SJohn McCall // Make the allocation for the block. 57508ef4660SJohn McCall blockInfo.Address = 57608ef4660SJohn McCall CGF.CreateTempAlloca(blockInfo.StructureType, "block"); 57708ef4660SJohn McCall blockInfo.Address->setAlignment(blockInfo.BlockAlign.getQuantity()); 57808ef4660SJohn McCall 57908ef4660SJohn McCall // If there are cleanups to emit, enter them (but inactive). 58008ef4660SJohn McCall if (!blockInfo.NeedsCopyDispose) return; 58108ef4660SJohn McCall 58208ef4660SJohn McCall // Walk through the captures (in order) and find the ones not 58308ef4660SJohn McCall // captured by constant. 58408ef4660SJohn McCall for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 58508ef4660SJohn McCall ce = block->capture_end(); ci != ce; ++ci) { 58608ef4660SJohn McCall // Ignore __block captures; there's nothing special in the 58708ef4660SJohn McCall // on-stack block that we need to do for them. 58808ef4660SJohn McCall if (ci->isByRef()) continue; 58908ef4660SJohn McCall 59008ef4660SJohn McCall // Ignore variables that are constant-captured. 59108ef4660SJohn McCall const VarDecl *variable = ci->getVariable(); 59208ef4660SJohn McCall CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 59308ef4660SJohn McCall if (capture.isConstant()) continue; 59408ef4660SJohn McCall 59508ef4660SJohn McCall // Ignore objects that aren't destructed. 59608ef4660SJohn McCall QualType::DestructionKind dtorKind = 59708ef4660SJohn McCall variable->getType().isDestructedType(); 59808ef4660SJohn McCall if (dtorKind == QualType::DK_none) continue; 59908ef4660SJohn McCall 60008ef4660SJohn McCall CodeGenFunction::Destroyer *destroyer; 60108ef4660SJohn McCall 60208ef4660SJohn McCall // Block captures count as local values and have imprecise semantics. 60308ef4660SJohn McCall // They also can't be arrays, so need to worry about that. 60408ef4660SJohn McCall if (dtorKind == QualType::DK_objc_strong_lifetime) { 6051425b455SPeter Collingbourne destroyer = CodeGenFunction::destroyARCStrongImprecise; 60608ef4660SJohn McCall } else { 6071425b455SPeter Collingbourne destroyer = CGF.getDestroyer(dtorKind); 60808ef4660SJohn McCall } 60908ef4660SJohn McCall 61008ef4660SJohn McCall // GEP down to the address. 61108ef4660SJohn McCall llvm::Value *addr = CGF.Builder.CreateStructGEP(blockInfo.Address, 61208ef4660SJohn McCall capture.getIndex()); 61308ef4660SJohn McCall 614f4beacd0SJohn McCall // We can use that GEP as the dominating IP. 615f4beacd0SJohn McCall if (!blockInfo.DominatingIP) 616f4beacd0SJohn McCall blockInfo.DominatingIP = cast<llvm::Instruction>(addr); 617f4beacd0SJohn McCall 61808ef4660SJohn McCall CleanupKind cleanupKind = InactiveNormalCleanup; 61908ef4660SJohn McCall bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind); 62008ef4660SJohn McCall if (useArrayEHCleanup) 62108ef4660SJohn McCall cleanupKind = InactiveNormalAndEHCleanup; 62208ef4660SJohn McCall 62308ef4660SJohn McCall CGF.pushDestroy(cleanupKind, addr, variable->getType(), 6241425b455SPeter Collingbourne destroyer, useArrayEHCleanup); 62508ef4660SJohn McCall 62608ef4660SJohn McCall // Remember where that cleanup was. 62708ef4660SJohn McCall capture.setCleanup(CGF.EHStack.stable_begin()); 62808ef4660SJohn McCall } 62908ef4660SJohn McCall } 63008ef4660SJohn McCall 63108ef4660SJohn McCall /// Enter a full-expression with a non-trivial number of objects to 63208ef4660SJohn McCall /// clean up. This is in this file because, at the moment, the only 63308ef4660SJohn McCall /// kind of cleanup object is a BlockDecl*. 63408ef4660SJohn McCall void CodeGenFunction::enterNonTrivialFullExpression(const ExprWithCleanups *E) { 63508ef4660SJohn McCall assert(E->getNumObjects() != 0); 63608ef4660SJohn McCall ArrayRef<ExprWithCleanups::CleanupObject> cleanups = E->getObjects(); 63708ef4660SJohn McCall for (ArrayRef<ExprWithCleanups::CleanupObject>::iterator 63808ef4660SJohn McCall i = cleanups.begin(), e = cleanups.end(); i != e; ++i) { 63908ef4660SJohn McCall enterBlockScope(*this, *i); 64008ef4660SJohn McCall } 64108ef4660SJohn McCall } 64208ef4660SJohn McCall 64308ef4660SJohn McCall /// Find the layout for the given block in a linked list and remove it. 64408ef4660SJohn McCall static CGBlockInfo *findAndRemoveBlockInfo(CGBlockInfo **head, 64508ef4660SJohn McCall const BlockDecl *block) { 64608ef4660SJohn McCall while (true) { 64708ef4660SJohn McCall assert(head && *head); 64808ef4660SJohn McCall CGBlockInfo *cur = *head; 64908ef4660SJohn McCall 65008ef4660SJohn McCall // If this is the block we're looking for, splice it out of the list. 65108ef4660SJohn McCall if (cur->getBlockDecl() == block) { 65208ef4660SJohn McCall *head = cur->NextBlockInfo; 65308ef4660SJohn McCall return cur; 65408ef4660SJohn McCall } 65508ef4660SJohn McCall 65608ef4660SJohn McCall head = &cur->NextBlockInfo; 65708ef4660SJohn McCall } 65808ef4660SJohn McCall } 65908ef4660SJohn McCall 66008ef4660SJohn McCall /// Destroy a chain of block layouts. 66108ef4660SJohn McCall void CodeGenFunction::destroyBlockInfos(CGBlockInfo *head) { 66208ef4660SJohn McCall assert(head && "destroying an empty chain"); 66308ef4660SJohn McCall do { 66408ef4660SJohn McCall CGBlockInfo *cur = head; 66508ef4660SJohn McCall head = cur->NextBlockInfo; 66608ef4660SJohn McCall delete cur; 66708ef4660SJohn McCall } while (head != 0); 66808ef4660SJohn McCall } 66908ef4660SJohn McCall 670351762cdSJohn McCall /// Emit a block literal expression in the current function. 671351762cdSJohn McCall llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { 67208ef4660SJohn McCall // If the block has no captures, we won't have a pre-computed 67308ef4660SJohn McCall // layout for it. 67408ef4660SJohn McCall if (!blockExpr->getBlockDecl()->hasCaptures()) { 67508ef4660SJohn McCall CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName()); 676dafff947SRichard Smith computeBlockInfo(CGM, this, blockInfo); 67708ef4660SJohn McCall blockInfo.BlockExpression = blockExpr; 67808ef4660SJohn McCall return EmitBlockLiteral(blockInfo); 67908ef4660SJohn McCall } 680351762cdSJohn McCall 68108ef4660SJohn McCall // Find the block info for this block and take ownership of it. 682e2778999SDylan Noblesmith OwningPtr<CGBlockInfo> blockInfo; 68308ef4660SJohn McCall blockInfo.reset(findAndRemoveBlockInfo(&FirstBlockInfo, 68408ef4660SJohn McCall blockExpr->getBlockDecl())); 68508ef4660SJohn McCall 68608ef4660SJohn McCall blockInfo->BlockExpression = blockExpr; 68708ef4660SJohn McCall return EmitBlockLiteral(*blockInfo); 68808ef4660SJohn McCall } 68908ef4660SJohn McCall 69008ef4660SJohn McCall llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { 69108ef4660SJohn McCall // Using the computed layout, generate the actual block function. 69298b01edcSEli Friedman bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda(); 693351762cdSJohn McCall llvm::Constant *blockFn 6946362803cSFariborz Jahanian = CodeGenFunction(CGM, true).GenerateBlockFunction(CurGD, blockInfo, 695dec348f7SJohn McCall LocalDeclMap, 69698b01edcSEli Friedman isLambdaConv); 697e3dc1707SJohn McCall blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); 698351762cdSJohn McCall 699351762cdSJohn McCall // If there is nothing to capture, we can emit this as a global block. 700351762cdSJohn McCall if (blockInfo.CanBeGlobal) 701351762cdSJohn McCall return buildGlobalBlock(CGM, blockInfo, blockFn); 702351762cdSJohn McCall 703351762cdSJohn McCall // Otherwise, we have to emit this as a local block. 704351762cdSJohn McCall 705351762cdSJohn McCall llvm::Constant *isa = CGM.getNSConcreteStackBlock(); 706e3dc1707SJohn McCall isa = llvm::ConstantExpr::getBitCast(isa, VoidPtrTy); 707351762cdSJohn McCall 708351762cdSJohn McCall // Build the block descriptor. 709351762cdSJohn McCall llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo); 710351762cdSJohn McCall 71108ef4660SJohn McCall llvm::AllocaInst *blockAddr = blockInfo.Address; 71208ef4660SJohn McCall assert(blockAddr && "block has no address!"); 713351762cdSJohn McCall 714351762cdSJohn McCall // Compute the initial on-stack block flags. 715ad7c5c16SJohn McCall BlockFlags flags = BLOCK_HAS_SIGNATURE; 71623290b05SFariborz Jahanian if (blockInfo.HasCapturedVariableLayout) flags |= BLOCK_HAS_EXTENDED_LAYOUT; 717351762cdSJohn McCall if (blockInfo.NeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE; 718351762cdSJohn McCall if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ; 71985915250SJohn McCall if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; 720351762cdSJohn McCall 721351762cdSJohn McCall // Initialize the block literal. 722351762cdSJohn McCall Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa")); 72308ef4660SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()), 724351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, 1, "block.flags")); 72508ef4660SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(IntTy, 0), 726351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, 2, "block.reserved")); 727351762cdSJohn McCall Builder.CreateStore(blockFn, Builder.CreateStructGEP(blockAddr, 3, 728351762cdSJohn McCall "block.invoke")); 729351762cdSJohn McCall Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockAddr, 4, 730351762cdSJohn McCall "block.descriptor")); 731351762cdSJohn McCall 732351762cdSJohn McCall // Finally, capture all the values into the block. 733351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 734351762cdSJohn McCall 735351762cdSJohn McCall // First, 'this'. 736351762cdSJohn McCall if (blockDecl->capturesCXXThis()) { 737351762cdSJohn McCall llvm::Value *addr = Builder.CreateStructGEP(blockAddr, 738351762cdSJohn McCall blockInfo.CXXThisIndex, 739351762cdSJohn McCall "block.captured-this.addr"); 740351762cdSJohn McCall Builder.CreateStore(LoadCXXThis(), addr); 741351762cdSJohn McCall } 742351762cdSJohn McCall 743351762cdSJohn McCall // Next, captured variables. 744351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 745351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 746351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 747351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 748351762cdSJohn McCall 749351762cdSJohn McCall // Ignore constant captures. 750351762cdSJohn McCall if (capture.isConstant()) continue; 751351762cdSJohn McCall 752351762cdSJohn McCall QualType type = variable->getType(); 7534d14a90aSJohn McCall CharUnits align = getContext().getDeclAlign(variable); 754351762cdSJohn McCall 755351762cdSJohn McCall // This will be a [[type]]*, except that a byref entry will just be 756351762cdSJohn McCall // an i8**. 757351762cdSJohn McCall llvm::Value *blockField = 758351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, capture.getIndex(), 759351762cdSJohn McCall "block.captured"); 760351762cdSJohn McCall 761351762cdSJohn McCall // Compute the address of the thing we're going to move into the 762351762cdSJohn McCall // block literal. 763351762cdSJohn McCall llvm::Value *src; 76426b51746SDouglas Gregor if (BlockInfo && ci->isNested()) { 765351762cdSJohn McCall // We need to use the capture from the enclosing block. 766351762cdSJohn McCall const CGBlockInfo::Capture &enclosingCapture = 767351762cdSJohn McCall BlockInfo->getCapture(variable); 768351762cdSJohn McCall 769351762cdSJohn McCall // This is a [[type]]*, except that a byref entry wil just be an i8**. 770351762cdSJohn McCall src = Builder.CreateStructGEP(LoadBlockStruct(), 771351762cdSJohn McCall enclosingCapture.getIndex(), 772351762cdSJohn McCall "block.capture.addr"); 77398b01edcSEli Friedman } else if (blockDecl->isConversionFromLambda()) { 7742495ab08SEli Friedman // The lambda capture in a lambda's conversion-to-block-pointer is 77598b01edcSEli Friedman // special; we'll simply emit it directly. 77698b01edcSEli Friedman src = 0; 777351762cdSJohn McCall } else { 778a37c2fa4SJohn McCall // Just look it up in the locals map, which will give us back a 779a37c2fa4SJohn McCall // [[type]]*. If that doesn't work, do the more elaborate DRE 780a37c2fa4SJohn McCall // emission. 781a37c2fa4SJohn McCall src = LocalDeclMap.lookup(variable); 782a37c2fa4SJohn McCall if (!src) { 783a37c2fa4SJohn McCall DeclRefExpr declRef(const_cast<VarDecl*>(variable), 784a37c2fa4SJohn McCall /*refersToEnclosing*/ ci->isNested(), type, 785a37c2fa4SJohn McCall VK_LValue, SourceLocation()); 786a37c2fa4SJohn McCall src = EmitDeclRefLValue(&declRef).getAddress(); 787a37c2fa4SJohn McCall } 788351762cdSJohn McCall } 789351762cdSJohn McCall 790351762cdSJohn McCall // For byrefs, we just write the pointer to the byref struct into 791351762cdSJohn McCall // the block field. There's no need to chase the forwarding 792351762cdSJohn McCall // pointer at this point, since we're building something that will 793351762cdSJohn McCall // live a shorter life than the stack byref anyway. 794351762cdSJohn McCall if (ci->isByRef()) { 795e3dc1707SJohn McCall // Get a void* that points to the byref struct. 796351762cdSJohn McCall if (ci->isNested()) 7974d14a90aSJohn McCall src = Builder.CreateAlignedLoad(src, align.getQuantity(), 7984d14a90aSJohn McCall "byref.capture"); 799351762cdSJohn McCall else 800e3dc1707SJohn McCall src = Builder.CreateBitCast(src, VoidPtrTy); 801351762cdSJohn McCall 802e3dc1707SJohn McCall // Write that void* into the capture field. 8034d14a90aSJohn McCall Builder.CreateAlignedStore(src, blockField, align.getQuantity()); 804351762cdSJohn McCall 805351762cdSJohn McCall // If we have a copy constructor, evaluate that into the block field. 806351762cdSJohn McCall } else if (const Expr *copyExpr = ci->getCopyExpr()) { 80798b01edcSEli Friedman if (blockDecl->isConversionFromLambda()) { 80898b01edcSEli Friedman // If we have a lambda conversion, emit the expression 80998b01edcSEli Friedman // directly into the block instead. 81098b01edcSEli Friedman AggValueSlot Slot = 8114d14a90aSJohn McCall AggValueSlot::forAddr(blockField, align, Qualifiers(), 81298b01edcSEli Friedman AggValueSlot::IsDestructed, 81398b01edcSEli Friedman AggValueSlot::DoesNotNeedGCBarriers, 814615ed1a3SChad Rosier AggValueSlot::IsNotAliased); 81598b01edcSEli Friedman EmitAggExpr(copyExpr, Slot); 81698b01edcSEli Friedman } else { 817351762cdSJohn McCall EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr); 81898b01edcSEli Friedman } 819351762cdSJohn McCall 820351762cdSJohn McCall // If it's a reference variable, copy the reference into the block field. 82110317eaaSFariborz Jahanian } else if (type->isReferenceType()) { 8224d14a90aSJohn McCall llvm::Value *ref = 8234d14a90aSJohn McCall Builder.CreateAlignedLoad(src, align.getQuantity(), "ref.val"); 8244d14a90aSJohn McCall Builder.CreateAlignedStore(ref, blockField, align.getQuantity()); 8254d14a90aSJohn McCall 8264d14a90aSJohn McCall // If this is an ARC __strong block-pointer variable, don't do a 8274d14a90aSJohn McCall // block copy. 8284d14a90aSJohn McCall // 8294d14a90aSJohn McCall // TODO: this can be generalized into the normal initialization logic: 8304d14a90aSJohn McCall // we should never need to do a block-copy when initializing a local 8314d14a90aSJohn McCall // variable, because the local variable's lifetime should be strictly 8324d14a90aSJohn McCall // contained within the stack block's. 8334d14a90aSJohn McCall } else if (type.getObjCLifetime() == Qualifiers::OCL_Strong && 8344d14a90aSJohn McCall type->isBlockPointerType()) { 8354d14a90aSJohn McCall // Load the block and do a simple retain. 8364d14a90aSJohn McCall LValue srcLV = MakeAddrLValue(src, type, align); 8372d84e842SNick Lewycky llvm::Value *value = EmitLoadOfScalar(srcLV, SourceLocation()); 8384d14a90aSJohn McCall value = EmitARCRetainNonBlock(value); 8394d14a90aSJohn McCall 8404d14a90aSJohn McCall // Do a primitive store to the block field. 8414d14a90aSJohn McCall LValue destLV = MakeAddrLValue(blockField, type, align); 8424d14a90aSJohn McCall EmitStoreOfScalar(value, destLV, /*init*/ true); 843351762cdSJohn McCall 844351762cdSJohn McCall // Otherwise, fake up a POD copy into the block field. 845351762cdSJohn McCall } else { 84631168b07SJohn McCall // Fake up a new variable so that EmitScalarInit doesn't think 84731168b07SJohn McCall // we're referring to the variable in its own initializer. 84831168b07SJohn McCall ImplicitParamDecl blockFieldPseudoVar(/*DC*/ 0, SourceLocation(), 84910317eaaSFariborz Jahanian /*name*/ 0, type); 85031168b07SJohn McCall 85193be3f75SJohn McCall // We use one of these or the other depending on whether the 85293be3f75SJohn McCall // reference is nested. 853113bee05SJohn McCall DeclRefExpr declRef(const_cast<VarDecl*>(variable), 854113bee05SJohn McCall /*refersToEnclosing*/ ci->isNested(), type, 855113bee05SJohn McCall VK_LValue, SourceLocation()); 85693be3f75SJohn McCall 85710317eaaSFariborz Jahanian ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue, 858113bee05SJohn McCall &declRef, VK_RValue); 8591553b190SJohn McCall EmitExprAsInit(&l2r, &blockFieldPseudoVar, 8604d14a90aSJohn McCall MakeAddrLValue(blockField, type, align), 8615c8f6c47SJohn McCall /*captured by init*/ false); 862351762cdSJohn McCall } 863351762cdSJohn McCall 86408ef4660SJohn McCall // Activate the cleanup if layout pushed one. 86531168b07SJohn McCall if (!ci->isByRef()) { 86608ef4660SJohn McCall EHScopeStack::stable_iterator cleanup = capture.getCleanup(); 86708ef4660SJohn McCall if (cleanup.isValid()) 868f4beacd0SJohn McCall ActivateCleanupBlock(cleanup, blockInfo.DominatingIP); 86931168b07SJohn McCall } 870351762cdSJohn McCall } 871351762cdSJohn McCall 872351762cdSJohn McCall // Cast to the converted block-pointer type, which happens (somewhat 873351762cdSJohn McCall // unfortunately) to be a pointer to function type. 874351762cdSJohn McCall llvm::Value *result = 875351762cdSJohn McCall Builder.CreateBitCast(blockAddr, 876351762cdSJohn McCall ConvertType(blockInfo.getBlockExpr()->getType())); 8773882ace2SJohn McCall 878351762cdSJohn McCall return result; 879b750d928SMike Stump } 88085284bacSMike Stump 88185284bacSMike Stump 882a5f58b05SChris Lattner llvm::Type *CodeGenModule::getBlockDescriptorType() { 883650c932dSMike Stump if (BlockDescriptorType) 884650c932dSMike Stump return BlockDescriptorType; 8852437cbfaSAnders Carlsson 886a5f58b05SChris Lattner llvm::Type *UnsignedLongTy = 887650c932dSMike Stump getTypes().ConvertType(getContext().UnsignedLongTy); 8882437cbfaSAnders Carlsson 8892437cbfaSAnders Carlsson // struct __block_descriptor { 8902437cbfaSAnders Carlsson // unsigned long reserved; 8912437cbfaSAnders Carlsson // unsigned long block_size; 892fc83aa04SBlaine Garst // 893fc83aa04SBlaine Garst // // later, the following will be added 894fc83aa04SBlaine Garst // 895fc83aa04SBlaine Garst // struct { 896fc83aa04SBlaine Garst // void (*copyHelper)(); 897fc83aa04SBlaine Garst // void (*copyHelper)(); 898fc83aa04SBlaine Garst // } helpers; // !!! optional 899fc83aa04SBlaine Garst // 900fc83aa04SBlaine Garst // const char *signature; // the block signature 901fc83aa04SBlaine Garst // const char *layout; // reserved 9022437cbfaSAnders Carlsson // }; 903845511feSChris Lattner BlockDescriptorType = 9045ec04a51SChris Lattner llvm::StructType::create("struct.__block_descriptor", 905a5f58b05SChris Lattner UnsignedLongTy, UnsignedLongTy, NULL); 9062437cbfaSAnders Carlsson 907351762cdSJohn McCall // Now form a pointer to that. 908351762cdSJohn McCall BlockDescriptorType = llvm::PointerType::getUnqual(BlockDescriptorType); 909650c932dSMike Stump return BlockDescriptorType; 9102437cbfaSAnders Carlsson } 9112437cbfaSAnders Carlsson 912a5f58b05SChris Lattner llvm::Type *CodeGenModule::getGenericBlockLiteralType() { 913005c9a62SMike Stump if (GenericBlockLiteralType) 914005c9a62SMike Stump return GenericBlockLiteralType; 9152437cbfaSAnders Carlsson 916a5f58b05SChris Lattner llvm::Type *BlockDescPtrTy = getBlockDescriptorType(); 9172437cbfaSAnders Carlsson 9182437cbfaSAnders Carlsson // struct __block_literal_generic { 9195d2534adSMike Stump // void *__isa; 9205d2534adSMike Stump // int __flags; 9215d2534adSMike Stump // int __reserved; 9225d2534adSMike Stump // void (*__invoke)(void *); 9235d2534adSMike Stump // struct __block_descriptor *__descriptor; 9242437cbfaSAnders Carlsson // }; 925a5f58b05SChris Lattner GenericBlockLiteralType = 9265ec04a51SChris Lattner llvm::StructType::create("struct.__block_literal_generic", 9275ec04a51SChris Lattner VoidPtrTy, IntTy, IntTy, VoidPtrTy, 9285ec04a51SChris Lattner BlockDescPtrTy, NULL); 9292437cbfaSAnders Carlsson 930005c9a62SMike Stump return GenericBlockLiteralType; 9312437cbfaSAnders Carlsson } 9322437cbfaSAnders Carlsson 9335d2534adSMike Stump 934bfb3671bSAnders Carlsson RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E, 935bfb3671bSAnders Carlsson ReturnValueSlot ReturnValue) { 9362437cbfaSAnders Carlsson const BlockPointerType *BPT = 937c23c7e6aSTed Kremenek E->getCallee()->getType()->getAs<BlockPointerType>(); 9382437cbfaSAnders Carlsson 9392437cbfaSAnders Carlsson llvm::Value *Callee = EmitScalarExpr(E->getCallee()); 9402437cbfaSAnders Carlsson 9412437cbfaSAnders Carlsson // Get a pointer to the generic block literal. 9422192fe50SChris Lattner llvm::Type *BlockLiteralTy = 9439793f0e4SOwen Anderson llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType()); 9442437cbfaSAnders Carlsson 9452437cbfaSAnders Carlsson // Bitcast the callee to a block literal. 9462437cbfaSAnders Carlsson llvm::Value *BlockLiteral = 9472437cbfaSAnders Carlsson Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal"); 9482437cbfaSAnders Carlsson 9492437cbfaSAnders Carlsson // Get the function pointer from the literal. 95076399eb2SBenjamin Kramer llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3); 9512437cbfaSAnders Carlsson 95276399eb2SBenjamin Kramer BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy); 9532437cbfaSAnders Carlsson 9542437cbfaSAnders Carlsson // Add the block literal. 9552437cbfaSAnders Carlsson CallArgList Args; 9569dc0db21SJohn McCall Args.add(RValue::get(BlockLiteral), getContext().VoidPtrTy); 9572437cbfaSAnders Carlsson 958479e6fc7SAnders Carlsson QualType FnType = BPT->getPointeeType(); 959479e6fc7SAnders Carlsson 9602437cbfaSAnders Carlsson // And the rest of the arguments. 9619dd450bbSJohn McCall EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), 962479e6fc7SAnders Carlsson E->arg_begin(), E->arg_end()); 9632437cbfaSAnders Carlsson 9645f50c651SAnders Carlsson // Load the function. 96576399eb2SBenjamin Kramer llvm::Value *Func = Builder.CreateLoad(FuncPtr); 9665f50c651SAnders Carlsson 96785915250SJohn McCall const FunctionType *FuncTy = FnType->castAs<FunctionType>(); 968a729c62bSJohn McCall const CGFunctionInfo &FnInfo = 969c818bbb8SJohn McCall CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy); 9705f50c651SAnders Carlsson 9715f50c651SAnders Carlsson // Cast the function pointer to the right type. 972a729c62bSJohn McCall llvm::Type *BlockFTy = CGM.getTypes().GetFunctionType(FnInfo); 9735f50c651SAnders Carlsson 9742192fe50SChris Lattner llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); 9755f50c651SAnders Carlsson Func = Builder.CreateBitCast(Func, BlockFTyPtr); 9765f50c651SAnders Carlsson 9772437cbfaSAnders Carlsson // And call the block. 978bfb3671bSAnders Carlsson return EmitCall(FnInfo, Func, ReturnValue, Args); 9792437cbfaSAnders Carlsson } 9806a60fa24SAnders Carlsson 981351762cdSJohn McCall llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable, 982351762cdSJohn McCall bool isByRef) { 983351762cdSJohn McCall assert(BlockInfo && "evaluating block ref without block information?"); 984351762cdSJohn McCall const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable); 98587fe5d56SJohn McCall 986351762cdSJohn McCall // Handle constant captures. 987351762cdSJohn McCall if (capture.isConstant()) return LocalDeclMap[variable]; 98887fe5d56SJohn McCall 989351762cdSJohn McCall llvm::Value *addr = 990351762cdSJohn McCall Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(), 991351762cdSJohn McCall "block.capture.addr"); 992351762cdSJohn McCall 993351762cdSJohn McCall if (isByRef) { 994351762cdSJohn McCall // addr should be a void** right now. Load, then cast the result 995351762cdSJohn McCall // to byref*. 996351762cdSJohn McCall 997351762cdSJohn McCall addr = Builder.CreateLoad(addr); 9982192fe50SChris Lattner llvm::PointerType *byrefPointerType 999351762cdSJohn McCall = llvm::PointerType::get(BuildByRefType(variable), 0); 1000351762cdSJohn McCall addr = Builder.CreateBitCast(addr, byrefPointerType, 1001351762cdSJohn McCall "byref.addr"); 1002351762cdSJohn McCall 1003351762cdSJohn McCall // Follow the forwarding pointer. 1004351762cdSJohn McCall addr = Builder.CreateStructGEP(addr, 1, "byref.forwarding"); 1005351762cdSJohn McCall addr = Builder.CreateLoad(addr, "byref.addr.forwarded"); 1006351762cdSJohn McCall 1007351762cdSJohn McCall // Cast back to byref* and GEP over to the actual object. 1008351762cdSJohn McCall addr = Builder.CreateBitCast(addr, byrefPointerType); 1009351762cdSJohn McCall addr = Builder.CreateStructGEP(addr, getByRefValueLLVMField(variable), 1010351762cdSJohn McCall variable->getNameAsString()); 101187fe5d56SJohn McCall } 101287fe5d56SJohn McCall 101310317eaaSFariborz Jahanian if (variable->getType()->isReferenceType()) 1014351762cdSJohn McCall addr = Builder.CreateLoad(addr, "ref.tmp"); 10150168f4b2SAnders Carlsson 1016351762cdSJohn McCall return addr; 101797d01d50SMike Stump } 101897d01d50SMike Stump 10192d5a2878SMike Stump llvm::Constant * 1020ad7c5c16SJohn McCall CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr, 1021351762cdSJohn McCall const char *name) { 102208ef4660SJohn McCall CGBlockInfo blockInfo(blockExpr->getBlockDecl(), name); 102308ef4660SJohn McCall blockInfo.BlockExpression = blockExpr; 10246a60fa24SAnders Carlsson 1025351762cdSJohn McCall // Compute information about the layout, etc., of this block. 1026dafff947SRichard Smith computeBlockInfo(*this, 0, blockInfo); 10276a60fa24SAnders Carlsson 1028351762cdSJohn McCall // Using that metadata, generate the actual block function. 1029351762cdSJohn McCall llvm::Constant *blockFn; 1030351762cdSJohn McCall { 10315469f29aSMike Stump llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap; 1032ad7c5c16SJohn McCall blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(), 1033351762cdSJohn McCall blockInfo, 1034dec348f7SJohn McCall LocalDeclMap, 10352495ab08SEli Friedman false); 1036351762cdSJohn McCall } 1037e3dc1707SJohn McCall blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); 10386a60fa24SAnders Carlsson 1039ad7c5c16SJohn McCall return buildGlobalBlock(*this, blockInfo, blockFn); 10406a60fa24SAnders Carlsson } 10416a60fa24SAnders Carlsson 1042351762cdSJohn McCall static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, 1043351762cdSJohn McCall const CGBlockInfo &blockInfo, 1044351762cdSJohn McCall llvm::Constant *blockFn) { 1045351762cdSJohn McCall assert(blockInfo.CanBeGlobal); 1046351762cdSJohn McCall 1047351762cdSJohn McCall // Generate the constants for the block literal initializer. 1048351762cdSJohn McCall llvm::Constant *fields[BlockHeaderSize]; 1049351762cdSJohn McCall 1050351762cdSJohn McCall // isa 1051351762cdSJohn McCall fields[0] = CGM.getNSConcreteGlobalBlock(); 1052351762cdSJohn McCall 1053351762cdSJohn McCall // __flags 105485915250SJohn McCall BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE; 105585915250SJohn McCall if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; 105685915250SJohn McCall 1057e3dc1707SJohn McCall fields[1] = llvm::ConstantInt::get(CGM.IntTy, flags.getBitMask()); 1058351762cdSJohn McCall 1059351762cdSJohn McCall // Reserved 1060e3dc1707SJohn McCall fields[2] = llvm::Constant::getNullValue(CGM.IntTy); 1061351762cdSJohn McCall 1062351762cdSJohn McCall // Function 1063351762cdSJohn McCall fields[3] = blockFn; 1064351762cdSJohn McCall 1065351762cdSJohn McCall // Descriptor 1066351762cdSJohn McCall fields[4] = buildBlockDescriptor(CGM, blockInfo); 1067351762cdSJohn McCall 1068e64d7ba1SChris Lattner llvm::Constant *init = llvm::ConstantStruct::getAnon(fields); 1069351762cdSJohn McCall 1070351762cdSJohn McCall llvm::GlobalVariable *literal = 1071351762cdSJohn McCall new llvm::GlobalVariable(CGM.getModule(), 1072351762cdSJohn McCall init->getType(), 1073351762cdSJohn McCall /*constant*/ true, 1074351762cdSJohn McCall llvm::GlobalVariable::InternalLinkage, 1075351762cdSJohn McCall init, 1076351762cdSJohn McCall "__block_literal_global"); 1077351762cdSJohn McCall literal->setAlignment(blockInfo.BlockAlign.getQuantity()); 1078351762cdSJohn McCall 1079351762cdSJohn McCall // Return a constant of the appropriately-casted type. 10802192fe50SChris Lattner llvm::Type *requiredType = 1081351762cdSJohn McCall CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType()); 1082351762cdSJohn McCall return llvm::ConstantExpr::getBitCast(literal, requiredType); 1083cb2fbcb0SMike Stump } 1084cb2fbcb0SMike Stump 10854446dcf0SMike Stump llvm::Function * 1086351762cdSJohn McCall CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, 1087351762cdSJohn McCall const CGBlockInfo &blockInfo, 10882495ab08SEli Friedman const DeclMapTy &ldm, 10892495ab08SEli Friedman bool IsLambdaConversionToBlock) { 1090351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 10919074ed8cSDevang Patel 10926362803cSFariborz Jahanian CurGD = GD; 10936e40c615SDevang Patel 1094351762cdSJohn McCall BlockInfo = &blockInfo; 10959074ed8cSDevang Patel 10965469f29aSMike Stump // Arrange for local static and local extern declarations to appear 1097351762cdSJohn McCall // to be local to this function as well, in case they're directly 1098351762cdSJohn McCall // referenced in a block. 1099351762cdSJohn McCall for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) { 1100351762cdSJohn McCall const VarDecl *var = dyn_cast<VarDecl>(i->first); 1101351762cdSJohn McCall if (var && !var->hasLocalStorage()) 1102351762cdSJohn McCall LocalDeclMap[var] = i->second; 11035469f29aSMike Stump } 11045469f29aSMike Stump 1105351762cdSJohn McCall // Begin building the function declaration. 110609a9b6e3SEli Friedman 1107351762cdSJohn McCall // Build the argument list. 1108351762cdSJohn McCall FunctionArgList args; 11096a60fa24SAnders Carlsson 1110351762cdSJohn McCall // The first argument is the block pointer. Just take it as a void* 1111351762cdSJohn McCall // and cast it later. 1112351762cdSJohn McCall QualType selfTy = getContext().VoidPtrTy; 11137fe9cc1dSMike Stump IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); 1114d015328fSMike Stump 1115147d021bSJohn McCall ImplicitParamDecl selfDecl(const_cast<BlockDecl*>(blockDecl), 1116351762cdSJohn McCall SourceLocation(), II, selfTy); 1117a738c25fSJohn McCall args.push_back(&selfDecl); 11187fe9cc1dSMike Stump 1119351762cdSJohn McCall // Now add the rest of the parameters. 1120351762cdSJohn McCall for (BlockDecl::param_const_iterator i = blockDecl->param_begin(), 1121351762cdSJohn McCall e = blockDecl->param_end(); i != e; ++i) 1122a738c25fSJohn McCall args.push_back(*i); 1123afa3c0a8SFariborz Jahanian 1124351762cdSJohn McCall // Create the function declaration. 1125a729c62bSJohn McCall const FunctionProtoType *fnType = blockInfo.getBlockExpr()->getFunctionType(); 11264982b82bSReid Kleckner const CGFunctionInfo &fnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration( 1127314cc81bSAlp Toker fnType->getReturnType(), args, fnType->getExtInfo(), 1128a729c62bSJohn McCall fnType->isVariadic()); 112985915250SJohn McCall if (CGM.ReturnTypeUsesSRet(fnInfo)) 113085915250SJohn McCall blockInfo.UsesStret = true; 113185915250SJohn McCall 1132a729c62bSJohn McCall llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo); 113387fe5d56SJohn McCall 1134351762cdSJohn McCall MangleBuffer name; 1135351762cdSJohn McCall CGM.getBlockMangledName(GD, name, blockDecl); 1136351762cdSJohn McCall llvm::Function *fn = 1137351762cdSJohn McCall llvm::Function::Create(fnLLVMType, llvm::GlobalValue::InternalLinkage, 1138351762cdSJohn McCall name.getString(), &CGM.getModule()); 1139351762cdSJohn McCall CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo); 11406a60fa24SAnders Carlsson 1141351762cdSJohn McCall // Begin generating the function. 1142314cc81bSAlp Toker StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args, 11435f070a51SDevang Patel blockInfo.getBlockExpr()->getBody()->getLocStart()); 11446a60fa24SAnders Carlsson 1145147d021bSJohn McCall // Okay. Undo some of what StartFunction did. 1146147d021bSJohn McCall 1147147d021bSJohn McCall // Pull the 'self' reference out of the local decl map. 1148147d021bSJohn McCall llvm::Value *blockAddr = LocalDeclMap[&selfDecl]; 1149147d021bSJohn McCall LocalDeclMap.erase(&selfDecl); 1150351762cdSJohn McCall BlockPointer = Builder.CreateBitCast(blockAddr, 1151351762cdSJohn McCall blockInfo.StructureType->getPointerTo(), 1152351762cdSJohn McCall "block"); 11530f6df00eSAdrian Prantl // At -O0 we generate an explicit alloca for the BlockPointer, so the RA 11540f6df00eSAdrian Prantl // won't delete the dbg.declare intrinsics for captured variables. 11550f6df00eSAdrian Prantl llvm::Value *BlockPointerDbgLoc = BlockPointer; 11560f6df00eSAdrian Prantl if (CGM.getCodeGenOpts().OptimizationLevel == 0) { 11570f6df00eSAdrian Prantl // Allocate a stack slot for it, so we can point the debugger to it 11580f6df00eSAdrian Prantl llvm::AllocaInst *Alloca = CreateTempAlloca(BlockPointer->getType(), 11590f6df00eSAdrian Prantl "block.addr"); 11600f6df00eSAdrian Prantl unsigned Align = getContext().getDeclAlign(&selfDecl).getQuantity(); 11610f6df00eSAdrian Prantl Alloca->setAlignment(Align); 11622832b4e8SAdrian Prantl // Set the DebugLocation to empty, so the store is recognized as a 11632832b4e8SAdrian Prantl // frame setup instruction by llvm::DwarfDebug::beginFunction(). 11642e0637ffSAdrian Prantl NoLocation NL(*this, Builder); 11650f6df00eSAdrian Prantl Builder.CreateAlignedStore(BlockPointer, Alloca, Align); 11660f6df00eSAdrian Prantl BlockPointerDbgLoc = Alloca; 11670f6df00eSAdrian Prantl } 1168017460abSMike Stump 116987fe5d56SJohn McCall // If we have a C++ 'this' reference, go ahead and force it into 117087fe5d56SJohn McCall // existence now. 1171351762cdSJohn McCall if (blockDecl->capturesCXXThis()) { 1172351762cdSJohn McCall llvm::Value *addr = Builder.CreateStructGEP(BlockPointer, 1173351762cdSJohn McCall blockInfo.CXXThisIndex, 1174351762cdSJohn McCall "block.captured-this"); 1175351762cdSJohn McCall CXXThisValue = Builder.CreateLoad(addr, "this"); 117687fe5d56SJohn McCall } 117787fe5d56SJohn McCall 1178351762cdSJohn McCall // Also force all the constant captures. 1179351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1180351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1181351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1182351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1183351762cdSJohn McCall if (!capture.isConstant()) continue; 1184351762cdSJohn McCall 1185351762cdSJohn McCall unsigned align = getContext().getDeclAlign(variable).getQuantity(); 1186351762cdSJohn McCall 1187351762cdSJohn McCall llvm::AllocaInst *alloca = 1188351762cdSJohn McCall CreateMemTemp(variable->getType(), "block.captured-const"); 1189351762cdSJohn McCall alloca->setAlignment(align); 1190351762cdSJohn McCall 119151936dd0SAdrian Prantl Builder.CreateAlignedStore(capture.getConstant(), alloca, align); 1192351762cdSJohn McCall 1193351762cdSJohn McCall LocalDeclMap[variable] = alloca; 11949d42f0f1SJohn McCall } 11959d42f0f1SJohn McCall 1196113bee05SJohn McCall // Save a spot to insert the debug information for all the DeclRefExprs. 1197017460abSMike Stump llvm::BasicBlock *entry = Builder.GetInsertBlock(); 1198017460abSMike Stump llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint(); 1199017460abSMike Stump --entry_ptr; 1200017460abSMike Stump 12012495ab08SEli Friedman if (IsLambdaConversionToBlock) 12022495ab08SEli Friedman EmitLambdaBlockInvokeBody(); 1203*c845c00aSBob Wilson else { 1204*c845c00aSBob Wilson PGO.assignRegionCounters(blockDecl, fn); 1205*c845c00aSBob Wilson RegionCounter Cnt = getPGORegionCounter(blockDecl->getBody()); 1206*c845c00aSBob Wilson Cnt.beginRegion(Builder); 1207351762cdSJohn McCall EmitStmt(blockDecl->getBody()); 1208*c845c00aSBob Wilson PGO.emitWriteoutFunction(); 1209*c845c00aSBob Wilson PGO.destroyRegionCounters(); 1210*c845c00aSBob Wilson } 1211017460abSMike Stump 12127d69911aSMike Stump // Remember where we were... 12137d69911aSMike Stump llvm::BasicBlock *resume = Builder.GetInsertBlock(); 1214017460abSMike Stump 12157d69911aSMike Stump // Go back to the entry. 1216017460abSMike Stump ++entry_ptr; 1217017460abSMike Stump Builder.SetInsertPoint(entry, entry_ptr); 1218017460abSMike Stump 1219113bee05SJohn McCall // Emit debug information for all the DeclRefExprs. 122087fe5d56SJohn McCall // FIXME: also for 'this' 1221351762cdSJohn McCall if (CGDebugInfo *DI = getDebugInfo()) { 1222351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1223351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1224351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 12257cdf9486SEric Christopher DI->EmitLocation(Builder, variable->getLocation()); 1226351762cdSJohn McCall 1227b0eea8b5SDouglas Gregor if (CGM.getCodeGenOpts().getDebugInfo() 1228b0eea8b5SDouglas Gregor >= CodeGenOptions::LimitedDebugInfo) { 1229351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1230351762cdSJohn McCall if (capture.isConstant()) { 1231351762cdSJohn McCall DI->EmitDeclareOfAutoVariable(variable, LocalDeclMap[variable], 1232351762cdSJohn McCall Builder); 1233351762cdSJohn McCall continue; 1234351762cdSJohn McCall } 1235351762cdSJohn McCall 12360f6df00eSAdrian Prantl DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointerDbgLoc, 1237351762cdSJohn McCall Builder, blockInfo); 12382e722b91SMike Stump } 12392e722b91SMike Stump } 1240ab08a9adSManman Ren // Recover location if it was changed in the above loop. 1241ab08a9adSManman Ren DI->EmitLocation(Builder, 1242ab08a9adSManman Ren cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc()); 124374a3868dSAlexey Samsonov } 1244351762cdSJohn McCall 12457d69911aSMike Stump // And resume where we left off. 12467d69911aSMike Stump if (resume == 0) 12477d69911aSMike Stump Builder.ClearInsertionPoint(); 12487d69911aSMike Stump else 12497d69911aSMike Stump Builder.SetInsertPoint(resume); 12502e722b91SMike Stump 1251351762cdSJohn McCall FinishFunction(cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc()); 12526a60fa24SAnders Carlsson 1253351762cdSJohn McCall return fn; 12546a60fa24SAnders Carlsson } 12551db7d04bSMike Stump 1256351762cdSJohn McCall /* 1257351762cdSJohn McCall notes.push_back(HelperInfo()); 1258351762cdSJohn McCall HelperInfo ¬e = notes.back(); 1259351762cdSJohn McCall note.index = capture.getIndex(); 1260351762cdSJohn McCall note.RequiresCopying = (ci->hasCopyExpr() || BlockRequiresCopying(type)); 1261351762cdSJohn McCall note.cxxbar_import = ci->getCopyExpr(); 12621db7d04bSMike Stump 1263351762cdSJohn McCall if (ci->isByRef()) { 1264351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_BYREF; 1265351762cdSJohn McCall if (type.isObjCGCWeak()) 1266351762cdSJohn McCall note.flag |= BLOCK_FIELD_IS_WEAK; 1267351762cdSJohn McCall } else if (type->isBlockPointerType()) { 1268351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_BLOCK; 1269351762cdSJohn McCall } else { 1270351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_OBJECT; 12711db7d04bSMike Stump } 1272351762cdSJohn McCall */ 12731db7d04bSMike Stump 127497d01d50SMike Stump 1275f593b10dSJohn McCall /// Generate the copy-helper function for a block closure object: 1276f593b10dSJohn McCall /// static void block_copy_helper(block_t *dst, block_t *src); 1277f593b10dSJohn McCall /// The runtime will have previously initialized 'dst' by doing a 1278f593b10dSJohn McCall /// bit-copy of 'src'. 1279f593b10dSJohn McCall /// 1280f593b10dSJohn McCall /// Note that this copies an entire block closure object to the heap; 1281f593b10dSJohn McCall /// it should not be confused with a 'byref copy helper', which moves 1282f593b10dSJohn McCall /// the contents of an individual __block variable to the heap. 1283351762cdSJohn McCall llvm::Constant * 1284ad7c5c16SJohn McCall CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { 1285351762cdSJohn McCall ASTContext &C = getContext(); 1286351762cdSJohn McCall 1287351762cdSJohn McCall FunctionArgList args; 1288a738c25fSJohn McCall ImplicitParamDecl dstDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1289a738c25fSJohn McCall args.push_back(&dstDecl); 1290a738c25fSJohn McCall ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1291a738c25fSJohn McCall args.push_back(&srcDecl); 12920c743277SMike Stump 12934982b82bSReid Kleckner const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( 12944982b82bSReid Kleckner C.VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false); 12950c743277SMike Stump 1296351762cdSJohn McCall // FIXME: it would be nice if these were mergeable with things with 1297351762cdSJohn McCall // identical semantics. 1298a729c62bSJohn McCall llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); 12990c743277SMike Stump 13000c743277SMike Stump llvm::Function *Fn = 13010c743277SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1302d6b28fc6SBenjamin Kramer "__copy_helper_block_", &CGM.getModule()); 13030c743277SMike Stump 13040c743277SMike Stump IdentifierInfo *II 13050c743277SMike Stump = &CGM.getContext().Idents.get("__copy_helper_block_"); 13060c743277SMike Stump 1307351762cdSJohn McCall FunctionDecl *FD = FunctionDecl::Create(C, 1308351762cdSJohn McCall C.getTranslationUnitDecl(), 1309dff1930bSAbramo Bagnara SourceLocation(), 1310351762cdSJohn McCall SourceLocation(), II, C.VoidTy, 0, 13118e7d656aSJohn McCall SC_Static, 1312c4df4076SDouglas Gregor false, 131356ef3746SEric Christopher false); 131449a78563SAdrian Prantl // Create a scope with an artificial location for the body of this function. 1315b75016d2SAdrian Prantl ArtificialLocation AL(*this, Builder); 131649a78563SAdrian Prantl StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); 131749a78563SAdrian Prantl AL.Emit(); 1318aeb0ffd5SMike Stump 13192192fe50SChris Lattner llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); 132067645930SMike Stump 1321a738c25fSJohn McCall llvm::Value *src = GetAddrOfLocalVar(&srcDecl); 1322ad7c5c16SJohn McCall src = Builder.CreateLoad(src); 1323ad7c5c16SJohn McCall src = Builder.CreateBitCast(src, structPtrTy, "block.source"); 132467645930SMike Stump 1325a738c25fSJohn McCall llvm::Value *dst = GetAddrOfLocalVar(&dstDecl); 1326ad7c5c16SJohn McCall dst = Builder.CreateLoad(dst); 1327ad7c5c16SJohn McCall dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest"); 1328aeb0ffd5SMike Stump 1329351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1330aeb0ffd5SMike Stump 1331351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1332351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1333351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1334351762cdSJohn McCall QualType type = variable->getType(); 1335aeb0ffd5SMike Stump 1336351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1337351762cdSJohn McCall if (capture.isConstant()) continue; 1338351762cdSJohn McCall 1339351762cdSJohn McCall const Expr *copyExpr = ci->getCopyExpr(); 134031168b07SJohn McCall BlockFieldFlags flags; 134131168b07SJohn McCall 1342e68b8f4dSJohn McCall bool useARCWeakCopy = false; 1343e68b8f4dSJohn McCall bool useARCStrongCopy = false; 1344351762cdSJohn McCall 1345351762cdSJohn McCall if (copyExpr) { 1346351762cdSJohn McCall assert(!ci->isByRef()); 1347351762cdSJohn McCall // don't bother computing flags 134831168b07SJohn McCall 1349351762cdSJohn McCall } else if (ci->isByRef()) { 1350351762cdSJohn McCall flags = BLOCK_FIELD_IS_BYREF; 135131168b07SJohn McCall if (type.isObjCGCWeak()) 135231168b07SJohn McCall flags |= BLOCK_FIELD_IS_WEAK; 1353351762cdSJohn McCall 135431168b07SJohn McCall } else if (type->isObjCRetainableType()) { 135531168b07SJohn McCall flags = BLOCK_FIELD_IS_OBJECT; 1356e68b8f4dSJohn McCall bool isBlockPointer = type->isBlockPointerType(); 1357e68b8f4dSJohn McCall if (isBlockPointer) 135831168b07SJohn McCall flags = BLOCK_FIELD_IS_BLOCK; 135931168b07SJohn McCall 136031168b07SJohn McCall // Special rules for ARC captures: 1361bbafb8a7SDavid Blaikie if (getLangOpts().ObjCAutoRefCount) { 136231168b07SJohn McCall Qualifiers qs = type.getQualifiers(); 136331168b07SJohn McCall 1364e68b8f4dSJohn McCall // We need to register __weak direct captures with the runtime. 1365e68b8f4dSJohn McCall if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) { 1366e68b8f4dSJohn McCall useARCWeakCopy = true; 136731168b07SJohn McCall 1368e68b8f4dSJohn McCall // We need to retain the copied value for __strong direct captures. 1369e68b8f4dSJohn McCall } else if (qs.getObjCLifetime() == Qualifiers::OCL_Strong) { 1370e68b8f4dSJohn McCall // If it's a block pointer, we have to copy the block and 1371e68b8f4dSJohn McCall // assign that to the destination pointer, so we might as 1372e68b8f4dSJohn McCall // well use _Block_object_assign. Otherwise we can avoid that. 1373e68b8f4dSJohn McCall if (!isBlockPointer) 1374e68b8f4dSJohn McCall useARCStrongCopy = true; 1375e68b8f4dSJohn McCall 1376e68b8f4dSJohn McCall // Otherwise the memcpy is fine. 1377e68b8f4dSJohn McCall } else { 1378e68b8f4dSJohn McCall continue; 1379e68b8f4dSJohn McCall } 1380e68b8f4dSJohn McCall 1381e68b8f4dSJohn McCall // Non-ARC captures of retainable pointers are strong and 1382e68b8f4dSJohn McCall // therefore require a call to _Block_object_assign. 1383e68b8f4dSJohn McCall } else { 1384e68b8f4dSJohn McCall // fall through 138531168b07SJohn McCall } 138631168b07SJohn McCall } else { 138731168b07SJohn McCall continue; 138831168b07SJohn McCall } 1389351762cdSJohn McCall 1390351762cdSJohn McCall unsigned index = capture.getIndex(); 1391ad7c5c16SJohn McCall llvm::Value *srcField = Builder.CreateStructGEP(src, index); 1392ad7c5c16SJohn McCall llvm::Value *dstField = Builder.CreateStructGEP(dst, index); 1393351762cdSJohn McCall 1394351762cdSJohn McCall // If there's an explicit copy expression, we do that. 1395351762cdSJohn McCall if (copyExpr) { 1396ad7c5c16SJohn McCall EmitSynthesizedCXXCopyCtor(dstField, srcField, copyExpr); 1397e68b8f4dSJohn McCall } else if (useARCWeakCopy) { 139831168b07SJohn McCall EmitARCCopyWeak(dstField, srcField); 1399351762cdSJohn McCall } else { 1400351762cdSJohn McCall llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); 1401e68b8f4dSJohn McCall if (useARCStrongCopy) { 1402e68b8f4dSJohn McCall // At -O0, store null into the destination field (so that the 1403e68b8f4dSJohn McCall // storeStrong doesn't over-release) and then call storeStrong. 1404e68b8f4dSJohn McCall // This is a workaround to not having an initStrong call. 1405e68b8f4dSJohn McCall if (CGM.getCodeGenOpts().OptimizationLevel == 0) { 1406e68b8f4dSJohn McCall llvm::PointerType *ty = cast<llvm::PointerType>(srcValue->getType()); 1407e68b8f4dSJohn McCall llvm::Value *null = llvm::ConstantPointerNull::get(ty); 1408e68b8f4dSJohn McCall Builder.CreateStore(null, dstField); 1409e68b8f4dSJohn McCall EmitARCStoreStrongCall(dstField, srcValue, true); 1410e68b8f4dSJohn McCall 1411e68b8f4dSJohn McCall // With optimization enabled, take advantage of the fact that 1412e68b8f4dSJohn McCall // the blocks runtime guarantees a memcpy of the block data, and 1413e68b8f4dSJohn McCall // just emit a retain of the src field. 1414e68b8f4dSJohn McCall } else { 1415e68b8f4dSJohn McCall EmitARCRetainNonBlock(srcValue); 1416e68b8f4dSJohn McCall 1417e68b8f4dSJohn McCall // We don't need this anymore, so kill it. It's not quite 1418e68b8f4dSJohn McCall // worth the annoyance to avoid creating it in the first place. 1419e68b8f4dSJohn McCall cast<llvm::Instruction>(dstField)->eraseFromParent(); 1420e68b8f4dSJohn McCall } 1421e68b8f4dSJohn McCall } else { 1422e3dc1707SJohn McCall srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy); 1423e3dc1707SJohn McCall llvm::Value *dstAddr = Builder.CreateBitCast(dstField, VoidPtrTy); 1424882987f3SJohn McCall llvm::Value *args[] = { 1425882987f3SJohn McCall dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask()) 1426882987f3SJohn McCall }; 1427882987f3SJohn McCall 1428882987f3SJohn McCall bool copyCanThrow = false; 1429882987f3SJohn McCall if (ci->isByRef() && variable->getType()->getAsCXXRecordDecl()) { 1430882987f3SJohn McCall const Expr *copyExpr = 1431882987f3SJohn McCall CGM.getContext().getBlockVarCopyInits(variable); 1432882987f3SJohn McCall if (copyExpr) { 1433882987f3SJohn McCall copyCanThrow = true; // FIXME: reuse the noexcept logic 1434882987f3SJohn McCall } 1435882987f3SJohn McCall } 1436882987f3SJohn McCall 1437882987f3SJohn McCall if (copyCanThrow) { 1438882987f3SJohn McCall EmitRuntimeCallOrInvoke(CGM.getBlockObjectAssign(), args); 1439882987f3SJohn McCall } else { 1440882987f3SJohn McCall EmitNounwindRuntimeCall(CGM.getBlockObjectAssign(), args); 1441882987f3SJohn McCall } 144267645930SMike Stump } 1443e988bdacSFariborz Jahanian } 1444e68b8f4dSJohn McCall } 1445aeb0ffd5SMike Stump 1446ad7c5c16SJohn McCall FinishFunction(); 14470c743277SMike Stump 1448e3dc1707SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); 144997d01d50SMike Stump } 145097d01d50SMike Stump 1451f593b10dSJohn McCall /// Generate the destroy-helper function for a block closure object: 1452f593b10dSJohn McCall /// static void block_destroy_helper(block_t *theBlock); 1453f593b10dSJohn McCall /// 1454f593b10dSJohn McCall /// Note that this destroys a heap-allocated block closure object; 1455f593b10dSJohn McCall /// it should not be confused with a 'byref destroy helper', which 1456f593b10dSJohn McCall /// destroys the heap-allocated contents of an individual __block 1457f593b10dSJohn McCall /// variable. 1458351762cdSJohn McCall llvm::Constant * 1459ad7c5c16SJohn McCall CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { 1460351762cdSJohn McCall ASTContext &C = getContext(); 14610c743277SMike Stump 1462351762cdSJohn McCall FunctionArgList args; 1463a738c25fSJohn McCall ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1464a738c25fSJohn McCall args.push_back(&srcDecl); 14650c743277SMike Stump 14664982b82bSReid Kleckner const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( 14674982b82bSReid Kleckner C.VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false); 14680c743277SMike Stump 1469cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1470cbc2bcafSMike Stump // internal linkage. 1471a729c62bSJohn McCall llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); 14720c743277SMike Stump 14730c743277SMike Stump llvm::Function *Fn = 14740c743277SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1475d6b28fc6SBenjamin Kramer "__destroy_helper_block_", &CGM.getModule()); 14760c743277SMike Stump 14770c743277SMike Stump IdentifierInfo *II 14780c743277SMike Stump = &CGM.getContext().Idents.get("__destroy_helper_block_"); 14790c743277SMike Stump 1480351762cdSJohn McCall FunctionDecl *FD = FunctionDecl::Create(C, C.getTranslationUnitDecl(), 1481dff1930bSAbramo Bagnara SourceLocation(), 1482351762cdSJohn McCall SourceLocation(), II, C.VoidTy, 0, 14838e7d656aSJohn McCall SC_Static, 148456ef3746SEric Christopher false, false); 148549a78563SAdrian Prantl // Create a scope with an artificial location for the body of this function. 1486b75016d2SAdrian Prantl ArtificialLocation AL(*this, Builder); 148749a78563SAdrian Prantl StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); 148849a78563SAdrian Prantl AL.Emit(); 14896f7d9f87SMike Stump 14902192fe50SChris Lattner llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); 149167645930SMike Stump 1492a738c25fSJohn McCall llvm::Value *src = GetAddrOfLocalVar(&srcDecl); 1493ad7c5c16SJohn McCall src = Builder.CreateLoad(src); 1494ad7c5c16SJohn McCall src = Builder.CreateBitCast(src, structPtrTy, "block"); 14956f7d9f87SMike Stump 1496351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1497351762cdSJohn McCall 1498ad7c5c16SJohn McCall CodeGenFunction::RunCleanupsScope cleanups(*this); 1499351762cdSJohn McCall 1500351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1501351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1502351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1503351762cdSJohn McCall QualType type = variable->getType(); 1504351762cdSJohn McCall 1505351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1506351762cdSJohn McCall if (capture.isConstant()) continue; 1507351762cdSJohn McCall 1508ad7c5c16SJohn McCall BlockFieldFlags flags; 1509351762cdSJohn McCall const CXXDestructorDecl *dtor = 0; 1510351762cdSJohn McCall 1511e68b8f4dSJohn McCall bool useARCWeakDestroy = false; 1512e68b8f4dSJohn McCall bool useARCStrongDestroy = false; 151331168b07SJohn McCall 1514351762cdSJohn McCall if (ci->isByRef()) { 1515351762cdSJohn McCall flags = BLOCK_FIELD_IS_BYREF; 151631168b07SJohn McCall if (type.isObjCGCWeak()) 151731168b07SJohn McCall flags |= BLOCK_FIELD_IS_WEAK; 151831168b07SJohn McCall } else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) { 151931168b07SJohn McCall if (record->hasTrivialDestructor()) 152031168b07SJohn McCall continue; 1521351762cdSJohn McCall dtor = record->getDestructor(); 152231168b07SJohn McCall } else if (type->isObjCRetainableType()) { 152331168b07SJohn McCall flags = BLOCK_FIELD_IS_OBJECT; 152431168b07SJohn McCall if (type->isBlockPointerType()) 152531168b07SJohn McCall flags = BLOCK_FIELD_IS_BLOCK; 1526351762cdSJohn McCall 152731168b07SJohn McCall // Special rules for ARC captures. 1528bbafb8a7SDavid Blaikie if (getLangOpts().ObjCAutoRefCount) { 152931168b07SJohn McCall Qualifiers qs = type.getQualifiers(); 153031168b07SJohn McCall 153131168b07SJohn McCall // Don't generate special dispose logic for a captured object 153231168b07SJohn McCall // unless it's __strong or __weak. 153331168b07SJohn McCall if (!qs.hasStrongOrWeakObjCLifetime()) 153431168b07SJohn McCall continue; 153531168b07SJohn McCall 153631168b07SJohn McCall // Support __weak direct captures. 153731168b07SJohn McCall if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) 1538e68b8f4dSJohn McCall useARCWeakDestroy = true; 1539e68b8f4dSJohn McCall 1540e68b8f4dSJohn McCall // Tools really want us to use objc_storeStrong here. 1541e68b8f4dSJohn McCall else 1542e68b8f4dSJohn McCall useARCStrongDestroy = true; 154331168b07SJohn McCall } 154431168b07SJohn McCall } else { 154531168b07SJohn McCall continue; 154631168b07SJohn McCall } 1547351762cdSJohn McCall 1548351762cdSJohn McCall unsigned index = capture.getIndex(); 1549ad7c5c16SJohn McCall llvm::Value *srcField = Builder.CreateStructGEP(src, index); 1550351762cdSJohn McCall 1551351762cdSJohn McCall // If there's an explicit copy expression, we do that. 1552351762cdSJohn McCall if (dtor) { 1553ad7c5c16SJohn McCall PushDestructorCleanup(dtor, srcField); 1554351762cdSJohn McCall 155531168b07SJohn McCall // If this is a __weak capture, emit the release directly. 1556e68b8f4dSJohn McCall } else if (useARCWeakDestroy) { 155731168b07SJohn McCall EmitARCDestroyWeak(srcField); 155831168b07SJohn McCall 1559e68b8f4dSJohn McCall // Destroy strong objects with a call if requested. 1560e68b8f4dSJohn McCall } else if (useARCStrongDestroy) { 1561cdda29c9SJohn McCall EmitARCDestroyStrong(srcField, ARCImpreciseLifetime); 1562e68b8f4dSJohn McCall 1563351762cdSJohn McCall // Otherwise we call _Block_object_dispose. It wouldn't be too 1564351762cdSJohn McCall // hard to just emit this as a cleanup if we wanted to make sure 1565351762cdSJohn McCall // that things were done in reverse. 1566351762cdSJohn McCall } else { 1567351762cdSJohn McCall llvm::Value *value = Builder.CreateLoad(srcField); 1568e3dc1707SJohn McCall value = Builder.CreateBitCast(value, VoidPtrTy); 1569351762cdSJohn McCall BuildBlockRelease(value, flags); 15706f7d9f87SMike Stump } 15716f7d9f87SMike Stump } 1572351762cdSJohn McCall 1573351762cdSJohn McCall cleanups.ForceCleanup(); 15746f7d9f87SMike Stump 1575ad7c5c16SJohn McCall FinishFunction(); 15760c743277SMike Stump 1577e3dc1707SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); 15780c743277SMike Stump } 15790c743277SMike Stump 1580f9b056b0SJohn McCall namespace { 1581f9b056b0SJohn McCall 1582f9b056b0SJohn McCall /// Emits the copy/dispose helper functions for a __block object of id type. 1583f9b056b0SJohn McCall class ObjectByrefHelpers : public CodeGenModule::ByrefHelpers { 1584f9b056b0SJohn McCall BlockFieldFlags Flags; 1585f9b056b0SJohn McCall 1586f9b056b0SJohn McCall public: 1587f9b056b0SJohn McCall ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags) 1588f9b056b0SJohn McCall : ByrefHelpers(alignment), Flags(flags) {} 1589f9b056b0SJohn McCall 15907c623641SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 15917c623641SJohn McCall llvm::Value *srcField) { 1592f9b056b0SJohn McCall destField = CGF.Builder.CreateBitCast(destField, CGF.VoidPtrTy); 1593f9b056b0SJohn McCall 1594f9b056b0SJohn McCall srcField = CGF.Builder.CreateBitCast(srcField, CGF.VoidPtrPtrTy); 1595f9b056b0SJohn McCall llvm::Value *srcValue = CGF.Builder.CreateLoad(srcField); 1596f9b056b0SJohn McCall 1597f9b056b0SJohn McCall unsigned flags = (Flags | BLOCK_BYREF_CALLER).getBitMask(); 1598f9b056b0SJohn McCall 1599f9b056b0SJohn McCall llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); 1600f9b056b0SJohn McCall llvm::Value *fn = CGF.CGM.getBlockObjectAssign(); 1601882987f3SJohn McCall 1602882987f3SJohn McCall llvm::Value *args[] = { destField, srcValue, flagsVal }; 1603882987f3SJohn McCall CGF.EmitNounwindRuntimeCall(fn, args); 1604f9b056b0SJohn McCall } 1605f9b056b0SJohn McCall 1606f9b056b0SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1607f9b056b0SJohn McCall field = CGF.Builder.CreateBitCast(field, CGF.Int8PtrTy->getPointerTo(0)); 1608f9b056b0SJohn McCall llvm::Value *value = CGF.Builder.CreateLoad(field); 1609f9b056b0SJohn McCall 1610f9b056b0SJohn McCall CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER); 1611f9b056b0SJohn McCall } 1612f9b056b0SJohn McCall 1613f9b056b0SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 1614f9b056b0SJohn McCall id.AddInteger(Flags.getBitMask()); 1615f9b056b0SJohn McCall } 1616f9b056b0SJohn McCall }; 1617f9b056b0SJohn McCall 161831168b07SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __weak variable. 161931168b07SJohn McCall class ARCWeakByrefHelpers : public CodeGenModule::ByrefHelpers { 162031168b07SJohn McCall public: 162131168b07SJohn McCall ARCWeakByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {} 162231168b07SJohn McCall 162331168b07SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 162431168b07SJohn McCall llvm::Value *srcField) { 162531168b07SJohn McCall CGF.EmitARCMoveWeak(destField, srcField); 162631168b07SJohn McCall } 162731168b07SJohn McCall 162831168b07SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 162931168b07SJohn McCall CGF.EmitARCDestroyWeak(field); 163031168b07SJohn McCall } 163131168b07SJohn McCall 163231168b07SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 163331168b07SJohn McCall // 0 is distinguishable from all pointers and byref flags 163431168b07SJohn McCall id.AddInteger(0); 163531168b07SJohn McCall } 163631168b07SJohn McCall }; 163731168b07SJohn McCall 163831168b07SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __strong variable 163931168b07SJohn McCall /// that's not of block-pointer type. 164031168b07SJohn McCall class ARCStrongByrefHelpers : public CodeGenModule::ByrefHelpers { 164131168b07SJohn McCall public: 164231168b07SJohn McCall ARCStrongByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {} 164331168b07SJohn McCall 164431168b07SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 164531168b07SJohn McCall llvm::Value *srcField) { 164631168b07SJohn McCall // Do a "move" by copying the value and then zeroing out the old 164731168b07SJohn McCall // variable. 164831168b07SJohn McCall 16493a237aa3SJohn McCall llvm::LoadInst *value = CGF.Builder.CreateLoad(srcField); 16503a237aa3SJohn McCall value->setAlignment(Alignment.getQuantity()); 16513a237aa3SJohn McCall 165231168b07SJohn McCall llvm::Value *null = 165331168b07SJohn McCall llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType())); 16543a237aa3SJohn McCall 1655a82e9265SFariborz Jahanian if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) { 1656cc2ae88eSFariborz Jahanian llvm::StoreInst *store = CGF.Builder.CreateStore(null, destField); 1657cc2ae88eSFariborz Jahanian store->setAlignment(Alignment.getQuantity()); 1658a82e9265SFariborz Jahanian CGF.EmitARCStoreStrongCall(destField, value, /*ignored*/ true); 1659a82e9265SFariborz Jahanian CGF.EmitARCStoreStrongCall(srcField, null, /*ignored*/ true); 1660a82e9265SFariborz Jahanian return; 1661a82e9265SFariborz Jahanian } 16623a237aa3SJohn McCall llvm::StoreInst *store = CGF.Builder.CreateStore(value, destField); 16633a237aa3SJohn McCall store->setAlignment(Alignment.getQuantity()); 16643a237aa3SJohn McCall 16653a237aa3SJohn McCall store = CGF.Builder.CreateStore(null, srcField); 16663a237aa3SJohn McCall store->setAlignment(Alignment.getQuantity()); 166731168b07SJohn McCall } 166831168b07SJohn McCall 166931168b07SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1670cdda29c9SJohn McCall CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime); 167131168b07SJohn McCall } 167231168b07SJohn McCall 167331168b07SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 167431168b07SJohn McCall // 1 is distinguishable from all pointers and byref flags 167531168b07SJohn McCall id.AddInteger(1); 167631168b07SJohn McCall } 167731168b07SJohn McCall }; 167831168b07SJohn McCall 16793a237aa3SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __strong 16803a237aa3SJohn McCall /// variable that's of block-pointer type. 16813a237aa3SJohn McCall class ARCStrongBlockByrefHelpers : public CodeGenModule::ByrefHelpers { 16823a237aa3SJohn McCall public: 16833a237aa3SJohn McCall ARCStrongBlockByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {} 16843a237aa3SJohn McCall 16853a237aa3SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 16863a237aa3SJohn McCall llvm::Value *srcField) { 16873a237aa3SJohn McCall // Do the copy with objc_retainBlock; that's all that 16883a237aa3SJohn McCall // _Block_object_assign would do anyway, and we'd have to pass the 16893a237aa3SJohn McCall // right arguments to make sure it doesn't get no-op'ed. 16903a237aa3SJohn McCall llvm::LoadInst *oldValue = CGF.Builder.CreateLoad(srcField); 16913a237aa3SJohn McCall oldValue->setAlignment(Alignment.getQuantity()); 16923a237aa3SJohn McCall 16933a237aa3SJohn McCall llvm::Value *copy = CGF.EmitARCRetainBlock(oldValue, /*mandatory*/ true); 16943a237aa3SJohn McCall 16953a237aa3SJohn McCall llvm::StoreInst *store = CGF.Builder.CreateStore(copy, destField); 16963a237aa3SJohn McCall store->setAlignment(Alignment.getQuantity()); 16973a237aa3SJohn McCall } 16983a237aa3SJohn McCall 16993a237aa3SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1700cdda29c9SJohn McCall CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime); 17013a237aa3SJohn McCall } 17023a237aa3SJohn McCall 17033a237aa3SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 17043a237aa3SJohn McCall // 2 is distinguishable from all pointers and byref flags 17053a237aa3SJohn McCall id.AddInteger(2); 17063a237aa3SJohn McCall } 17073a237aa3SJohn McCall }; 17083a237aa3SJohn McCall 1709f9b056b0SJohn McCall /// Emits the copy/dispose helpers for a __block variable with a 1710f9b056b0SJohn McCall /// nontrivial copy constructor or destructor. 1711f9b056b0SJohn McCall class CXXByrefHelpers : public CodeGenModule::ByrefHelpers { 1712f9b056b0SJohn McCall QualType VarType; 1713f9b056b0SJohn McCall const Expr *CopyExpr; 1714f9b056b0SJohn McCall 1715f9b056b0SJohn McCall public: 1716f9b056b0SJohn McCall CXXByrefHelpers(CharUnits alignment, QualType type, 1717f9b056b0SJohn McCall const Expr *copyExpr) 1718f9b056b0SJohn McCall : ByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {} 1719f9b056b0SJohn McCall 1720f9b056b0SJohn McCall bool needsCopy() const { return CopyExpr != 0; } 1721f9b056b0SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 1722f9b056b0SJohn McCall llvm::Value *srcField) { 1723f9b056b0SJohn McCall if (!CopyExpr) return; 1724f9b056b0SJohn McCall CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr); 1725f9b056b0SJohn McCall } 1726f9b056b0SJohn McCall 1727f9b056b0SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1728f9b056b0SJohn McCall EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin(); 1729f9b056b0SJohn McCall CGF.PushDestructorCleanup(VarType, field); 1730f9b056b0SJohn McCall CGF.PopCleanupBlocks(cleanupDepth); 1731f9b056b0SJohn McCall } 1732f9b056b0SJohn McCall 1733f9b056b0SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 1734f9b056b0SJohn McCall id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr()); 1735f9b056b0SJohn McCall } 1736f9b056b0SJohn McCall }; 1737f9b056b0SJohn McCall } // end anonymous namespace 1738f9b056b0SJohn McCall 1739f9b056b0SJohn McCall static llvm::Constant * 1740f9b056b0SJohn McCall generateByrefCopyHelper(CodeGenFunction &CGF, 17412192fe50SChris Lattner llvm::StructType &byrefType, 1742f593b10dSJohn McCall unsigned valueFieldIndex, 1743f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &byrefInfo) { 1744f9b056b0SJohn McCall ASTContext &Context = CGF.getContext(); 1745f9b056b0SJohn McCall 1746f9b056b0SJohn McCall QualType R = Context.VoidTy; 1747ee2a5ee5SMike Stump 1748a738c25fSJohn McCall FunctionArgList args; 1749f9b056b0SJohn McCall ImplicitParamDecl dst(0, SourceLocation(), 0, Context.VoidPtrTy); 1750a738c25fSJohn McCall args.push_back(&dst); 1751f89230d9SMike Stump 1752f9b056b0SJohn McCall ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); 1753a738c25fSJohn McCall args.push_back(&src); 1754ee2a5ee5SMike Stump 17554982b82bSReid Kleckner const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeFreeFunctionDeclaration( 17564982b82bSReid Kleckner R, args, FunctionType::ExtInfo(), /*variadic=*/false); 1757ee2a5ee5SMike Stump 1758f9b056b0SJohn McCall CodeGenTypes &Types = CGF.CGM.getTypes(); 1759a729c62bSJohn McCall llvm::FunctionType *LTy = Types.GetFunctionType(FI); 1760ee2a5ee5SMike Stump 1761cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1762cbc2bcafSMike Stump // internal linkage. 1763ee2a5ee5SMike Stump llvm::Function *Fn = 1764ee2a5ee5SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1765f9b056b0SJohn McCall "__Block_byref_object_copy_", &CGF.CGM.getModule()); 1766ee2a5ee5SMike Stump 1767ee2a5ee5SMike Stump IdentifierInfo *II 1768f9b056b0SJohn McCall = &Context.Idents.get("__Block_byref_object_copy_"); 1769ee2a5ee5SMike Stump 1770f9b056b0SJohn McCall FunctionDecl *FD = FunctionDecl::Create(Context, 1771f9b056b0SJohn McCall Context.getTranslationUnitDecl(), 1772dff1930bSAbramo Bagnara SourceLocation(), 177360ed5604SArgyrios Kyrtzidis SourceLocation(), II, R, 0, 17748e7d656aSJohn McCall SC_Static, 17750b1aef2bSEric Christopher false, false); 177631168b07SJohn McCall 1777f9b056b0SJohn McCall CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); 1778f9b056b0SJohn McCall 1779f9b056b0SJohn McCall if (byrefInfo.needsCopy()) { 17802192fe50SChris Lattner llvm::Type *byrefPtrType = byrefType.getPointerTo(0); 1781f89230d9SMike Stump 1782f89230d9SMike Stump // dst->x 1783f9b056b0SJohn McCall llvm::Value *destField = CGF.GetAddrOfLocalVar(&dst); 1784f9b056b0SJohn McCall destField = CGF.Builder.CreateLoad(destField); 1785f9b056b0SJohn McCall destField = CGF.Builder.CreateBitCast(destField, byrefPtrType); 1786f593b10dSJohn McCall destField = CGF.Builder.CreateStructGEP(destField, valueFieldIndex, "x"); 1787f89230d9SMike Stump 1788f89230d9SMike Stump // src->x 1789f9b056b0SJohn McCall llvm::Value *srcField = CGF.GetAddrOfLocalVar(&src); 1790f9b056b0SJohn McCall srcField = CGF.Builder.CreateLoad(srcField); 1791f9b056b0SJohn McCall srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType); 1792f593b10dSJohn McCall srcField = CGF.Builder.CreateStructGEP(srcField, valueFieldIndex, "x"); 179350198098SFariborz Jahanian 1794f9b056b0SJohn McCall byrefInfo.emitCopy(CGF, destField, srcField); 179550198098SFariborz Jahanian } 1796f89230d9SMike Stump 1797f9b056b0SJohn McCall CGF.FinishFunction(); 1798ee2a5ee5SMike Stump 1799f9b056b0SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); 1800ee2a5ee5SMike Stump } 1801ee2a5ee5SMike Stump 1802f9b056b0SJohn McCall /// Build the copy helper for a __block variable. 1803f9b056b0SJohn McCall static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM, 18042192fe50SChris Lattner llvm::StructType &byrefType, 1805f593b10dSJohn McCall unsigned byrefValueIndex, 1806f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &info) { 1807f9b056b0SJohn McCall CodeGenFunction CGF(CGM); 1808f593b10dSJohn McCall return generateByrefCopyHelper(CGF, byrefType, byrefValueIndex, info); 1809f9b056b0SJohn McCall } 1810f9b056b0SJohn McCall 1811f9b056b0SJohn McCall /// Generate code for a __block variable's dispose helper. 1812f9b056b0SJohn McCall static llvm::Constant * 1813f9b056b0SJohn McCall generateByrefDisposeHelper(CodeGenFunction &CGF, 18142192fe50SChris Lattner llvm::StructType &byrefType, 1815f593b10dSJohn McCall unsigned byrefValueIndex, 1816f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &byrefInfo) { 1817f9b056b0SJohn McCall ASTContext &Context = CGF.getContext(); 1818f9b056b0SJohn McCall QualType R = Context.VoidTy; 1819ee2a5ee5SMike Stump 1820a738c25fSJohn McCall FunctionArgList args; 1821f9b056b0SJohn McCall ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); 1822a738c25fSJohn McCall args.push_back(&src); 1823ee2a5ee5SMike Stump 18244982b82bSReid Kleckner const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeFreeFunctionDeclaration( 18254982b82bSReid Kleckner R, args, FunctionType::ExtInfo(), /*variadic=*/false); 1826ee2a5ee5SMike Stump 1827f9b056b0SJohn McCall CodeGenTypes &Types = CGF.CGM.getTypes(); 1828a729c62bSJohn McCall llvm::FunctionType *LTy = Types.GetFunctionType(FI); 1829ee2a5ee5SMike Stump 1830cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1831cbc2bcafSMike Stump // internal linkage. 1832ee2a5ee5SMike Stump llvm::Function *Fn = 1833ee2a5ee5SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 183450198098SFariborz Jahanian "__Block_byref_object_dispose_", 1835f9b056b0SJohn McCall &CGF.CGM.getModule()); 1836ee2a5ee5SMike Stump 1837ee2a5ee5SMike Stump IdentifierInfo *II 1838f9b056b0SJohn McCall = &Context.Idents.get("__Block_byref_object_dispose_"); 1839ee2a5ee5SMike Stump 1840f9b056b0SJohn McCall FunctionDecl *FD = FunctionDecl::Create(Context, 1841f9b056b0SJohn McCall Context.getTranslationUnitDecl(), 1842dff1930bSAbramo Bagnara SourceLocation(), 184360ed5604SArgyrios Kyrtzidis SourceLocation(), II, R, 0, 18448e7d656aSJohn McCall SC_Static, 18450b1aef2bSEric Christopher false, false); 1846f9b056b0SJohn McCall CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); 1847fbe25dd1SMike Stump 1848f9b056b0SJohn McCall if (byrefInfo.needsDispose()) { 1849f9b056b0SJohn McCall llvm::Value *V = CGF.GetAddrOfLocalVar(&src); 1850f9b056b0SJohn McCall V = CGF.Builder.CreateLoad(V); 1851f9b056b0SJohn McCall V = CGF.Builder.CreateBitCast(V, byrefType.getPointerTo(0)); 1852f593b10dSJohn McCall V = CGF.Builder.CreateStructGEP(V, byrefValueIndex, "x"); 1853ad7c5c16SJohn McCall 1854f9b056b0SJohn McCall byrefInfo.emitDispose(CGF, V); 1855f9b056b0SJohn McCall } 1856ad7c5c16SJohn McCall 1857f9b056b0SJohn McCall CGF.FinishFunction(); 1858f9b056b0SJohn McCall 1859f9b056b0SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); 1860f9b056b0SJohn McCall } 1861f9b056b0SJohn McCall 1862f9b056b0SJohn McCall /// Build the dispose helper for a __block variable. 1863f9b056b0SJohn McCall static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM, 18642192fe50SChris Lattner llvm::StructType &byrefType, 1865f593b10dSJohn McCall unsigned byrefValueIndex, 1866f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &info) { 1867f9b056b0SJohn McCall CodeGenFunction CGF(CGM); 1868f593b10dSJohn McCall return generateByrefDisposeHelper(CGF, byrefType, byrefValueIndex, info); 1869f9b056b0SJohn McCall } 1870f9b056b0SJohn McCall 1871f593b10dSJohn McCall /// Lazily build the copy and dispose helpers for a __block variable 1872f593b10dSJohn McCall /// with the given information. 1873f9b056b0SJohn McCall template <class T> static T *buildByrefHelpers(CodeGenModule &CGM, 18742192fe50SChris Lattner llvm::StructType &byrefTy, 1875f593b10dSJohn McCall unsigned byrefValueIndex, 1876f9b056b0SJohn McCall T &byrefInfo) { 1877f9b056b0SJohn McCall // Increase the field's alignment to be at least pointer alignment, 1878f9b056b0SJohn McCall // since the layout of the byref struct will guarantee at least that. 1879f9b056b0SJohn McCall byrefInfo.Alignment = std::max(byrefInfo.Alignment, 1880f9b056b0SJohn McCall CharUnits::fromQuantity(CGM.PointerAlignInBytes)); 1881f9b056b0SJohn McCall 1882f9b056b0SJohn McCall llvm::FoldingSetNodeID id; 1883f9b056b0SJohn McCall byrefInfo.Profile(id); 1884f9b056b0SJohn McCall 1885f9b056b0SJohn McCall void *insertPos; 1886f9b056b0SJohn McCall CodeGenModule::ByrefHelpers *node 1887f9b056b0SJohn McCall = CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos); 1888f9b056b0SJohn McCall if (node) return static_cast<T*>(node); 1889f9b056b0SJohn McCall 1890f593b10dSJohn McCall byrefInfo.CopyHelper = 1891f593b10dSJohn McCall buildByrefCopyHelper(CGM, byrefTy, byrefValueIndex, byrefInfo); 1892f593b10dSJohn McCall byrefInfo.DisposeHelper = 1893f593b10dSJohn McCall buildByrefDisposeHelper(CGM, byrefTy, byrefValueIndex,byrefInfo); 1894f9b056b0SJohn McCall 1895f9b056b0SJohn McCall T *copy = new (CGM.getContext()) T(byrefInfo); 1896f9b056b0SJohn McCall CGM.ByrefHelpersCache.InsertNode(copy, insertPos); 1897f9b056b0SJohn McCall return copy; 1898f9b056b0SJohn McCall } 1899f9b056b0SJohn McCall 1900f593b10dSJohn McCall /// Build the copy and dispose helpers for the given __block variable 1901f593b10dSJohn McCall /// emission. Places the helpers in the global cache. Returns null 1902f593b10dSJohn McCall /// if no helpers are required. 1903f9b056b0SJohn McCall CodeGenModule::ByrefHelpers * 19042192fe50SChris Lattner CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType, 1905f9b056b0SJohn McCall const AutoVarEmission &emission) { 1906f9b056b0SJohn McCall const VarDecl &var = *emission.Variable; 1907f9b056b0SJohn McCall QualType type = var.getType(); 1908f9b056b0SJohn McCall 1909f593b10dSJohn McCall unsigned byrefValueIndex = getByRefValueLLVMField(&var); 1910f593b10dSJohn McCall 1911f9b056b0SJohn McCall if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) { 1912f9b056b0SJohn McCall const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var); 1913f9b056b0SJohn McCall if (!copyExpr && record->hasTrivialDestructor()) return 0; 1914f9b056b0SJohn McCall 1915f9b056b0SJohn McCall CXXByrefHelpers byrefInfo(emission.Alignment, type, copyExpr); 1916f593b10dSJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo); 1917f9b056b0SJohn McCall } 1918f9b056b0SJohn McCall 191931168b07SJohn McCall // Otherwise, if we don't have a retainable type, there's nothing to do. 192031168b07SJohn McCall // that the runtime does extra copies. 192131168b07SJohn McCall if (!type->isObjCRetainableType()) return 0; 192231168b07SJohn McCall 192331168b07SJohn McCall Qualifiers qs = type.getQualifiers(); 192431168b07SJohn McCall 192531168b07SJohn McCall // If we have lifetime, that dominates. 192631168b07SJohn McCall if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) { 1927bbafb8a7SDavid Blaikie assert(getLangOpts().ObjCAutoRefCount); 192831168b07SJohn McCall 192931168b07SJohn McCall switch (lifetime) { 193031168b07SJohn McCall case Qualifiers::OCL_None: llvm_unreachable("impossible"); 193131168b07SJohn McCall 193231168b07SJohn McCall // These are just bits as far as the runtime is concerned. 193331168b07SJohn McCall case Qualifiers::OCL_ExplicitNone: 193431168b07SJohn McCall case Qualifiers::OCL_Autoreleasing: 193531168b07SJohn McCall return 0; 193631168b07SJohn McCall 193731168b07SJohn McCall // Tell the runtime that this is ARC __weak, called by the 193831168b07SJohn McCall // byref routines. 193931168b07SJohn McCall case Qualifiers::OCL_Weak: { 194031168b07SJohn McCall ARCWeakByrefHelpers byrefInfo(emission.Alignment); 1941f593b10dSJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo); 194231168b07SJohn McCall } 194331168b07SJohn McCall 194431168b07SJohn McCall // ARC __strong __block variables need to be retained. 194531168b07SJohn McCall case Qualifiers::OCL_Strong: 19463a237aa3SJohn McCall // Block pointers need to be copied, and there's no direct 19473a237aa3SJohn McCall // transfer possible. 194831168b07SJohn McCall if (type->isBlockPointerType()) { 19493a237aa3SJohn McCall ARCStrongBlockByrefHelpers byrefInfo(emission.Alignment); 1950f593b10dSJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo); 195131168b07SJohn McCall 195231168b07SJohn McCall // Otherwise, we transfer ownership of the retain from the stack 195331168b07SJohn McCall // to the heap. 195431168b07SJohn McCall } else { 195531168b07SJohn McCall ARCStrongByrefHelpers byrefInfo(emission.Alignment); 1956f593b10dSJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo); 195731168b07SJohn McCall } 195831168b07SJohn McCall } 195931168b07SJohn McCall llvm_unreachable("fell out of lifetime switch!"); 196031168b07SJohn McCall } 196131168b07SJohn McCall 1962f9b056b0SJohn McCall BlockFieldFlags flags; 1963f9b056b0SJohn McCall if (type->isBlockPointerType()) { 1964f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_BLOCK; 1965f9b056b0SJohn McCall } else if (CGM.getContext().isObjCNSObjectType(type) || 1966f9b056b0SJohn McCall type->isObjCObjectPointerType()) { 1967f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_OBJECT; 1968ad7c5c16SJohn McCall } else { 1969f9b056b0SJohn McCall return 0; 1970ee2a5ee5SMike Stump } 1971ee2a5ee5SMike Stump 1972f9b056b0SJohn McCall if (type.isObjCGCWeak()) 1973f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_WEAK; 1974ad7c5c16SJohn McCall 1975f9b056b0SJohn McCall ObjectByrefHelpers byrefInfo(emission.Alignment, flags); 1976f593b10dSJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo); 1977ee2a5ee5SMike Stump } 1978ee2a5ee5SMike Stump 197973064870SJohn McCall unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const { 198073064870SJohn McCall assert(ByRefValueInfo.count(VD) && "Did not find value!"); 198173064870SJohn McCall 198273064870SJohn McCall return ByRefValueInfo.find(VD)->second.second; 198373064870SJohn McCall } 198473064870SJohn McCall 198573064870SJohn McCall llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr, 198673064870SJohn McCall const VarDecl *V) { 198773064870SJohn McCall llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding"); 198873064870SJohn McCall Loc = Builder.CreateLoad(Loc); 198973064870SJohn McCall Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V), 199073064870SJohn McCall V->getNameAsString()); 199173064870SJohn McCall return Loc; 199273064870SJohn McCall } 199373064870SJohn McCall 199473064870SJohn McCall /// BuildByRefType - This routine changes a __block variable declared as T x 199573064870SJohn McCall /// into: 199673064870SJohn McCall /// 199773064870SJohn McCall /// struct { 199873064870SJohn McCall /// void *__isa; 199973064870SJohn McCall /// void *__forwarding; 200073064870SJohn McCall /// int32_t __flags; 200173064870SJohn McCall /// int32_t __size; 200273064870SJohn McCall /// void *__copy_helper; // only if needed 200373064870SJohn McCall /// void *__destroy_helper; // only if needed 2004a9d4464bSFariborz Jahanian /// void *__byref_variable_layout;// only if needed 200573064870SJohn McCall /// char padding[X]; // only if needed 200673064870SJohn McCall /// T x; 200773064870SJohn McCall /// } x 200873064870SJohn McCall /// 20092192fe50SChris Lattner llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) { 20102192fe50SChris Lattner std::pair<llvm::Type *, unsigned> &Info = ByRefValueInfo[D]; 201173064870SJohn McCall if (Info.first) 201273064870SJohn McCall return Info.first; 201373064870SJohn McCall 201473064870SJohn McCall QualType Ty = D->getType(); 201573064870SJohn McCall 20160e62c1ccSChris Lattner SmallVector<llvm::Type *, 8> types; 201773064870SJohn McCall 2018a5f58b05SChris Lattner llvm::StructType *ByRefType = 20195ec04a51SChris Lattner llvm::StructType::create(getLLVMContext(), 2020a5f58b05SChris Lattner "struct.__block_byref_" + D->getNameAsString()); 202173064870SJohn McCall 202273064870SJohn McCall // void *__isa; 20239dc0db21SJohn McCall types.push_back(Int8PtrTy); 202473064870SJohn McCall 202573064870SJohn McCall // void *__forwarding; 2026a5f58b05SChris Lattner types.push_back(llvm::PointerType::getUnqual(ByRefType)); 202773064870SJohn McCall 202873064870SJohn McCall // int32_t __flags; 20299dc0db21SJohn McCall types.push_back(Int32Ty); 203073064870SJohn McCall 203173064870SJohn McCall // int32_t __size; 20329dc0db21SJohn McCall types.push_back(Int32Ty); 2033998f0a33SFariborz Jahanian // Note that this must match *exactly* the logic in buildByrefHelpers. 2034998f0a33SFariborz Jahanian bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty, D); 203573064870SJohn McCall if (HasCopyAndDispose) { 203673064870SJohn McCall /// void *__copy_helper; 20379dc0db21SJohn McCall types.push_back(Int8PtrTy); 203873064870SJohn McCall 203973064870SJohn McCall /// void *__destroy_helper; 20409dc0db21SJohn McCall types.push_back(Int8PtrTy); 204173064870SJohn McCall } 2042a9d4464bSFariborz Jahanian bool HasByrefExtendedLayout = false; 2043a9d4464bSFariborz Jahanian Qualifiers::ObjCLifetime Lifetime; 2044a9d4464bSFariborz Jahanian if (getContext().getByrefLifetime(Ty, Lifetime, HasByrefExtendedLayout) && 2045a9d4464bSFariborz Jahanian HasByrefExtendedLayout) 2046a9d4464bSFariborz Jahanian /// void *__byref_variable_layout; 2047a9d4464bSFariborz Jahanian types.push_back(Int8PtrTy); 204873064870SJohn McCall 204973064870SJohn McCall bool Packed = false; 205073064870SJohn McCall CharUnits Align = getContext().getDeclAlign(D); 2051c8e01705SJohn McCall if (Align > 2052c8e01705SJohn McCall getContext().toCharUnitsFromBits(getTarget().getPointerAlign(0))) { 205373064870SJohn McCall // We have to insert padding. 205473064870SJohn McCall 205573064870SJohn McCall // The struct above has 2 32-bit integers. 205673064870SJohn McCall unsigned CurrentOffsetInBytes = 4 * 2; 205773064870SJohn McCall 2058a9d4464bSFariborz Jahanian // And either 2, 3, 4 or 5 pointers. 2059a9d4464bSFariborz Jahanian unsigned noPointers = 2; 2060a9d4464bSFariborz Jahanian if (HasCopyAndDispose) 2061a9d4464bSFariborz Jahanian noPointers += 2; 2062a9d4464bSFariborz Jahanian if (HasByrefExtendedLayout) 2063a9d4464bSFariborz Jahanian noPointers += 1; 2064a9d4464bSFariborz Jahanian 2065a9d4464bSFariborz Jahanian CurrentOffsetInBytes += noPointers * CGM.getDataLayout().getTypeAllocSize(Int8PtrTy); 206673064870SJohn McCall 206773064870SJohn McCall // Align the offset. 206873064870SJohn McCall unsigned AlignedOffsetInBytes = 206973064870SJohn McCall llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity()); 207073064870SJohn McCall 207173064870SJohn McCall unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes; 207273064870SJohn McCall if (NumPaddingBytes > 0) { 2073ece0409aSChris Lattner llvm::Type *Ty = Int8Ty; 207473064870SJohn McCall // FIXME: We need a sema error for alignment larger than the minimum of 20759dc0db21SJohn McCall // the maximal stack alignment and the alignment of malloc on the system. 207673064870SJohn McCall if (NumPaddingBytes > 1) 207773064870SJohn McCall Ty = llvm::ArrayType::get(Ty, NumPaddingBytes); 207873064870SJohn McCall 20799dc0db21SJohn McCall types.push_back(Ty); 208073064870SJohn McCall 208173064870SJohn McCall // We want a packed struct. 208273064870SJohn McCall Packed = true; 208373064870SJohn McCall } 208473064870SJohn McCall } 208573064870SJohn McCall 208673064870SJohn McCall // T x; 20879dc0db21SJohn McCall types.push_back(ConvertTypeForMem(Ty)); 208873064870SJohn McCall 2089a5f58b05SChris Lattner ByRefType->setBody(types, Packed); 209073064870SJohn McCall 2091a5f58b05SChris Lattner Info.first = ByRefType; 209273064870SJohn McCall 20939dc0db21SJohn McCall Info.second = types.size() - 1; 209473064870SJohn McCall 209573064870SJohn McCall return Info.first; 209673064870SJohn McCall } 209773064870SJohn McCall 209873064870SJohn McCall /// Initialize the structural components of a __block variable, i.e. 209973064870SJohn McCall /// everything but the actual object. 210073064870SJohn McCall void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { 2101f9b056b0SJohn McCall // Find the address of the local. 2102f9b056b0SJohn McCall llvm::Value *addr = emission.Address; 210373064870SJohn McCall 2104f9b056b0SJohn McCall // That's an alloca of the byref structure type. 21052192fe50SChris Lattner llvm::StructType *byrefType = cast<llvm::StructType>( 2106f9b056b0SJohn McCall cast<llvm::PointerType>(addr->getType())->getElementType()); 2107f9b056b0SJohn McCall 2108f9b056b0SJohn McCall // Build the byref helpers if necessary. This is null if we don't need any. 2109f9b056b0SJohn McCall CodeGenModule::ByrefHelpers *helpers = 2110f9b056b0SJohn McCall buildByrefHelpers(*byrefType, emission); 211173064870SJohn McCall 211273064870SJohn McCall const VarDecl &D = *emission.Variable; 211373064870SJohn McCall QualType type = D.getType(); 211473064870SJohn McCall 2115a9d4464bSFariborz Jahanian bool HasByrefExtendedLayout; 2116a9d4464bSFariborz Jahanian Qualifiers::ObjCLifetime ByrefLifetime; 2117a9d4464bSFariborz Jahanian bool ByRefHasLifetime = 2118a9d4464bSFariborz Jahanian getContext().getByrefLifetime(type, ByrefLifetime, HasByrefExtendedLayout); 2119a9d4464bSFariborz Jahanian 2120f9b056b0SJohn McCall llvm::Value *V; 212173064870SJohn McCall 212273064870SJohn McCall // Initialize the 'isa', which is just 0 or 1. 212373064870SJohn McCall int isa = 0; 2124f9b056b0SJohn McCall if (type.isObjCGCWeak()) 212573064870SJohn McCall isa = 1; 212673064870SJohn McCall V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa"); 212773064870SJohn McCall Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa")); 212873064870SJohn McCall 212973064870SJohn McCall // Store the address of the variable into its own forwarding pointer. 213073064870SJohn McCall Builder.CreateStore(addr, 213173064870SJohn McCall Builder.CreateStructGEP(addr, 1, "byref.forwarding")); 213273064870SJohn McCall 213373064870SJohn McCall // Blocks ABI: 213473064870SJohn McCall // c) the flags field is set to either 0 if no helper functions are 2135a9d4464bSFariborz Jahanian // needed or BLOCK_BYREF_HAS_COPY_DISPOSE if they are, 213673064870SJohn McCall BlockFlags flags; 2137a9d4464bSFariborz Jahanian if (helpers) flags |= BLOCK_BYREF_HAS_COPY_DISPOSE; 2138a9d4464bSFariborz Jahanian if (ByRefHasLifetime) { 2139a9d4464bSFariborz Jahanian if (HasByrefExtendedLayout) flags |= BLOCK_BYREF_LAYOUT_EXTENDED; 2140a9d4464bSFariborz Jahanian else switch (ByrefLifetime) { 2141a9d4464bSFariborz Jahanian case Qualifiers::OCL_Strong: 2142a9d4464bSFariborz Jahanian flags |= BLOCK_BYREF_LAYOUT_STRONG; 2143a9d4464bSFariborz Jahanian break; 2144a9d4464bSFariborz Jahanian case Qualifiers::OCL_Weak: 2145a9d4464bSFariborz Jahanian flags |= BLOCK_BYREF_LAYOUT_WEAK; 2146a9d4464bSFariborz Jahanian break; 2147a9d4464bSFariborz Jahanian case Qualifiers::OCL_ExplicitNone: 2148a9d4464bSFariborz Jahanian flags |= BLOCK_BYREF_LAYOUT_UNRETAINED; 2149a9d4464bSFariborz Jahanian break; 2150a9d4464bSFariborz Jahanian case Qualifiers::OCL_None: 2151a9d4464bSFariborz Jahanian if (!type->isObjCObjectPointerType() && !type->isBlockPointerType()) 2152a9d4464bSFariborz Jahanian flags |= BLOCK_BYREF_LAYOUT_NON_OBJECT; 2153a9d4464bSFariborz Jahanian break; 2154a9d4464bSFariborz Jahanian default: 2155a9d4464bSFariborz Jahanian break; 2156a9d4464bSFariborz Jahanian } 2157a9d4464bSFariborz Jahanian if (CGM.getLangOpts().ObjCGCBitmapPrint) { 2158a9d4464bSFariborz Jahanian printf("\n Inline flag for BYREF variable layout (%d):", flags.getBitMask()); 2159a9d4464bSFariborz Jahanian if (flags & BLOCK_BYREF_HAS_COPY_DISPOSE) 2160a9d4464bSFariborz Jahanian printf(" BLOCK_BYREF_HAS_COPY_DISPOSE"); 2161a9d4464bSFariborz Jahanian if (flags & BLOCK_BYREF_LAYOUT_MASK) { 2162a9d4464bSFariborz Jahanian BlockFlags ThisFlag(flags.getBitMask() & BLOCK_BYREF_LAYOUT_MASK); 2163a9d4464bSFariborz Jahanian if (ThisFlag == BLOCK_BYREF_LAYOUT_EXTENDED) 2164a9d4464bSFariborz Jahanian printf(" BLOCK_BYREF_LAYOUT_EXTENDED"); 2165a9d4464bSFariborz Jahanian if (ThisFlag == BLOCK_BYREF_LAYOUT_STRONG) 2166a9d4464bSFariborz Jahanian printf(" BLOCK_BYREF_LAYOUT_STRONG"); 2167a9d4464bSFariborz Jahanian if (ThisFlag == BLOCK_BYREF_LAYOUT_WEAK) 2168a9d4464bSFariborz Jahanian printf(" BLOCK_BYREF_LAYOUT_WEAK"); 2169a9d4464bSFariborz Jahanian if (ThisFlag == BLOCK_BYREF_LAYOUT_UNRETAINED) 2170a9d4464bSFariborz Jahanian printf(" BLOCK_BYREF_LAYOUT_UNRETAINED"); 2171a9d4464bSFariborz Jahanian if (ThisFlag == BLOCK_BYREF_LAYOUT_NON_OBJECT) 2172a9d4464bSFariborz Jahanian printf(" BLOCK_BYREF_LAYOUT_NON_OBJECT"); 2173a9d4464bSFariborz Jahanian } 2174a9d4464bSFariborz Jahanian printf("\n"); 2175a9d4464bSFariborz Jahanian } 2176a9d4464bSFariborz Jahanian } 2177a9d4464bSFariborz Jahanian 217873064870SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()), 217973064870SJohn McCall Builder.CreateStructGEP(addr, 2, "byref.flags")); 218073064870SJohn McCall 2181f9b056b0SJohn McCall CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType); 2182f9b056b0SJohn McCall V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity()); 218373064870SJohn McCall Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size")); 218473064870SJohn McCall 2185f9b056b0SJohn McCall if (helpers) { 218673064870SJohn McCall llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4); 2187f9b056b0SJohn McCall Builder.CreateStore(helpers->CopyHelper, copy_helper); 218873064870SJohn McCall 218973064870SJohn McCall llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5); 2190f9b056b0SJohn McCall Builder.CreateStore(helpers->DisposeHelper, destroy_helper); 219173064870SJohn McCall } 2192a9d4464bSFariborz Jahanian if (ByRefHasLifetime && HasByrefExtendedLayout) { 2193a9d4464bSFariborz Jahanian llvm::Constant* ByrefLayoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type); 2194a9d4464bSFariborz Jahanian llvm::Value *ByrefInfoAddr = Builder.CreateStructGEP(addr, helpers ? 6 : 4, 2195a9d4464bSFariborz Jahanian "byref.layout"); 2196a9d4464bSFariborz Jahanian // cast destination to pointer to source type. 2197a9d4464bSFariborz Jahanian llvm::Type *DesTy = ByrefLayoutInfo->getType(); 2198a9d4464bSFariborz Jahanian DesTy = DesTy->getPointerTo(); 2199a9d4464bSFariborz Jahanian llvm::Value *BC = Builder.CreatePointerCast(ByrefInfoAddr, DesTy); 2200a9d4464bSFariborz Jahanian Builder.CreateStore(ByrefLayoutInfo, BC); 2201a9d4464bSFariborz Jahanian } 220273064870SJohn McCall } 220373064870SJohn McCall 2204ad7c5c16SJohn McCall void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) { 2205900546d2SDaniel Dunbar llvm::Value *F = CGM.getBlockObjectDispose(); 2206882987f3SJohn McCall llvm::Value *args[] = { 2207882987f3SJohn McCall Builder.CreateBitCast(V, Int8PtrTy), 2208882987f3SJohn McCall llvm::ConstantInt::get(Int32Ty, flags.getBitMask()) 2209882987f3SJohn McCall }; 2210882987f3SJohn McCall EmitNounwindRuntimeCall(F, args); // FIXME: throwing destructors? 2211626aecc4SMike Stump } 221273064870SJohn McCall 221373064870SJohn McCall namespace { 221473064870SJohn McCall struct CallBlockRelease : EHScopeStack::Cleanup { 221573064870SJohn McCall llvm::Value *Addr; 221673064870SJohn McCall CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {} 221773064870SJohn McCall 221830317fdaSJohn McCall void Emit(CodeGenFunction &CGF, Flags flags) { 221931168b07SJohn McCall // Should we be passing FIELD_IS_WEAK here? 222073064870SJohn McCall CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF); 222173064870SJohn McCall } 222273064870SJohn McCall }; 222373064870SJohn McCall } 222473064870SJohn McCall 222573064870SJohn McCall /// Enter a cleanup to destroy a __block variable. Note that this 222673064870SJohn McCall /// cleanup should be a no-op if the variable hasn't left the stack 222773064870SJohn McCall /// yet; if a cleanup is required for the variable itself, that needs 222873064870SJohn McCall /// to be done externally. 222973064870SJohn McCall void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) { 223073064870SJohn McCall // We don't enter this cleanup if we're in pure-GC mode. 2231bbafb8a7SDavid Blaikie if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) 223273064870SJohn McCall return; 223373064870SJohn McCall 223473064870SJohn McCall EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address); 223573064870SJohn McCall } 22367959fee2SJohn McCall 22377959fee2SJohn McCall /// Adjust the declaration of something from the blocks API. 22387959fee2SJohn McCall static void configureBlocksRuntimeObject(CodeGenModule &CGM, 22397959fee2SJohn McCall llvm::Constant *C) { 2240bbafb8a7SDavid Blaikie if (!CGM.getLangOpts().BlocksRuntimeOptional) return; 22417959fee2SJohn McCall 22427959fee2SJohn McCall llvm::GlobalValue *GV = cast<llvm::GlobalValue>(C->stripPointerCasts()); 22437959fee2SJohn McCall if (GV->isDeclaration() && 22447959fee2SJohn McCall GV->getLinkage() == llvm::GlobalValue::ExternalLinkage) 22457959fee2SJohn McCall GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 22467959fee2SJohn McCall } 22477959fee2SJohn McCall 22487959fee2SJohn McCall llvm::Constant *CodeGenModule::getBlockObjectDispose() { 22497959fee2SJohn McCall if (BlockObjectDispose) 22507959fee2SJohn McCall return BlockObjectDispose; 22517959fee2SJohn McCall 22527959fee2SJohn McCall llvm::Type *args[] = { Int8PtrTy, Int32Ty }; 22537959fee2SJohn McCall llvm::FunctionType *fty 22547959fee2SJohn McCall = llvm::FunctionType::get(VoidTy, args, false); 22557959fee2SJohn McCall BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose"); 22567959fee2SJohn McCall configureBlocksRuntimeObject(*this, BlockObjectDispose); 22577959fee2SJohn McCall return BlockObjectDispose; 22587959fee2SJohn McCall } 22597959fee2SJohn McCall 22607959fee2SJohn McCall llvm::Constant *CodeGenModule::getBlockObjectAssign() { 22617959fee2SJohn McCall if (BlockObjectAssign) 22627959fee2SJohn McCall return BlockObjectAssign; 22637959fee2SJohn McCall 22647959fee2SJohn McCall llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty }; 22657959fee2SJohn McCall llvm::FunctionType *fty 22667959fee2SJohn McCall = llvm::FunctionType::get(VoidTy, args, false); 22677959fee2SJohn McCall BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign"); 22687959fee2SJohn McCall configureBlocksRuntimeObject(*this, BlockObjectAssign); 22697959fee2SJohn McCall return BlockObjectAssign; 22707959fee2SJohn McCall } 22717959fee2SJohn McCall 22727959fee2SJohn McCall llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() { 22737959fee2SJohn McCall if (NSConcreteGlobalBlock) 22747959fee2SJohn McCall return NSConcreteGlobalBlock; 22757959fee2SJohn McCall 22767959fee2SJohn McCall NSConcreteGlobalBlock = GetOrCreateLLVMGlobal("_NSConcreteGlobalBlock", 22777959fee2SJohn McCall Int8PtrTy->getPointerTo(), 0); 22787959fee2SJohn McCall configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock); 22797959fee2SJohn McCall return NSConcreteGlobalBlock; 22807959fee2SJohn McCall } 22817959fee2SJohn McCall 22827959fee2SJohn McCall llvm::Constant *CodeGenModule::getNSConcreteStackBlock() { 22837959fee2SJohn McCall if (NSConcreteStackBlock) 22847959fee2SJohn McCall return NSConcreteStackBlock; 22857959fee2SJohn McCall 22867959fee2SJohn McCall NSConcreteStackBlock = GetOrCreateLLVMGlobal("_NSConcreteStackBlock", 22877959fee2SJohn McCall Int8PtrTy->getPointerTo(), 0); 22887959fee2SJohn McCall configureBlocksRuntimeObject(*this, NSConcreteStackBlock); 22897959fee2SJohn McCall return NSConcreteStackBlock; 22907959fee2SJohn McCall } 2291