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 142e722b91SMike Stump #include "CGDebugInfo.h" 152437cbfaSAnders Carlsson #include "CodeGenFunction.h" 16989908fbSFariborz Jahanian #include "CGObjCRuntime.h" 172437cbfaSAnders Carlsson #include "CodeGenModule.h" 18ad7c5c16SJohn McCall #include "CGBlocks.h" 19692c6e37SMike Stump #include "clang/AST/DeclObjC.h" 202437cbfaSAnders Carlsson #include "llvm/Module.h" 219e2e1c90SBenjamin Kramer #include "llvm/ADT/SmallSet.h" 226a60fa24SAnders Carlsson #include "llvm/Target/TargetData.h" 232437cbfaSAnders Carlsson #include <algorithm> 24db714924STorok Edwin 252437cbfaSAnders Carlsson using namespace clang; 262437cbfaSAnders Carlsson using namespace CodeGen; 272437cbfaSAnders Carlsson 2808ef4660SJohn McCall CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name) 2908ef4660SJohn McCall : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), 30f4beacd0SJohn McCall HasCXXObject(false), UsesStret(false), StructureType(0), Block(block), 31f4beacd0SJohn McCall DominatingIP(0) { 329d42f0f1SJohn McCall 3308ef4660SJohn McCall // Skip asm prefix, if any. 'name' is usually taken directly from 3408ef4660SJohn McCall // the mangled name of the enclosing function. 3508ef4660SJohn McCall if (!name.empty() && name[0] == '\01') 3608ef4660SJohn McCall name = name.substr(1); 379d42f0f1SJohn McCall } 389d42f0f1SJohn McCall 39f9b056b0SJohn McCall // Anchor the vtable to this translation unit. 40f9b056b0SJohn McCall CodeGenModule::ByrefHelpers::~ByrefHelpers() {} 41f9b056b0SJohn McCall 42351762cdSJohn McCall /// Build the given block as a global block. 43351762cdSJohn McCall static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, 44351762cdSJohn McCall const CGBlockInfo &blockInfo, 45351762cdSJohn McCall llvm::Constant *blockFn); 469d42f0f1SJohn McCall 47351762cdSJohn McCall /// Build the helper function to copy a block. 48351762cdSJohn McCall static llvm::Constant *buildCopyHelper(CodeGenModule &CGM, 49351762cdSJohn McCall const CGBlockInfo &blockInfo) { 50351762cdSJohn McCall return CodeGenFunction(CGM).GenerateCopyHelperFunction(blockInfo); 51351762cdSJohn McCall } 52351762cdSJohn McCall 53351762cdSJohn McCall /// Build the helper function to dipose of a block. 54351762cdSJohn McCall static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM, 55351762cdSJohn McCall const CGBlockInfo &blockInfo) { 56351762cdSJohn McCall return CodeGenFunction(CGM).GenerateDestroyHelperFunction(blockInfo); 57351762cdSJohn McCall } 58351762cdSJohn McCall 59351762cdSJohn McCall /// Build the block descriptor constant for a block. 60351762cdSJohn McCall static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM, 61351762cdSJohn McCall const CGBlockInfo &blockInfo) { 62351762cdSJohn McCall ASTContext &C = CGM.getContext(); 63351762cdSJohn McCall 642192fe50SChris Lattner llvm::Type *ulong = CGM.getTypes().ConvertType(C.UnsignedLongTy); 652192fe50SChris Lattner llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy); 66351762cdSJohn McCall 670e62c1ccSChris Lattner SmallVector<llvm::Constant*, 6> elements; 6885284bacSMike Stump 6985284bacSMike Stump // reserved 70351762cdSJohn McCall elements.push_back(llvm::ConstantInt::get(ulong, 0)); 7185284bacSMike Stump 7285284bacSMike Stump // Size 732ac40a9fSMike Stump // FIXME: What is the right way to say this doesn't fit? We should give 742ac40a9fSMike Stump // a user diagnostic in that case. Better fix would be to change the 752ac40a9fSMike Stump // API to size_t. 76351762cdSJohn McCall elements.push_back(llvm::ConstantInt::get(ulong, 77351762cdSJohn McCall blockInfo.BlockSize.getQuantity())); 7885284bacSMike Stump 79351762cdSJohn McCall // Optional copy/dispose helpers. 80351762cdSJohn McCall if (blockInfo.NeedsCopyDispose) { 8185284bacSMike Stump // copy_func_helper_decl 82351762cdSJohn McCall elements.push_back(buildCopyHelper(CGM, blockInfo)); 8385284bacSMike Stump 8485284bacSMike Stump // destroy_func_decl 85351762cdSJohn McCall elements.push_back(buildDisposeHelper(CGM, blockInfo)); 8685284bacSMike Stump } 8785284bacSMike Stump 88351762cdSJohn McCall // Signature. Mandatory ObjC-style method descriptor @encode sequence. 89351762cdSJohn McCall std::string typeAtEncoding = 90351762cdSJohn McCall CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr()); 91351762cdSJohn McCall elements.push_back(llvm::ConstantExpr::getBitCast( 92351762cdSJohn McCall CGM.GetAddrOfConstantCString(typeAtEncoding), i8p)); 93fc83aa04SBlaine Garst 94351762cdSJohn McCall // GC layout. 95*bbafb8a7SDavid Blaikie if (C.getLangOpts().ObjC1) 96351762cdSJohn McCall elements.push_back(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo)); 97351762cdSJohn McCall else 98351762cdSJohn McCall elements.push_back(llvm::Constant::getNullValue(i8p)); 99fc83aa04SBlaine Garst 100e64d7ba1SChris Lattner llvm::Constant *init = llvm::ConstantStruct::getAnon(elements); 101c05349e5SFariborz Jahanian 102351762cdSJohn McCall llvm::GlobalVariable *global = 103351762cdSJohn McCall new llvm::GlobalVariable(CGM.getModule(), init->getType(), true, 10485284bacSMike Stump llvm::GlobalValue::InternalLinkage, 105351762cdSJohn McCall init, "__block_descriptor_tmp"); 10685284bacSMike Stump 107351762cdSJohn McCall return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType()); 108ed5e69feSAnders Carlsson } 109ed5e69feSAnders Carlsson 110351762cdSJohn McCall /* 111351762cdSJohn McCall Purely notional variadic template describing the layout of a block. 112ed5e69feSAnders Carlsson 113351762cdSJohn McCall template <class _ResultType, class... _ParamTypes, class... _CaptureTypes> 114351762cdSJohn McCall struct Block_literal { 115351762cdSJohn McCall /// Initialized to one of: 116351762cdSJohn McCall /// extern void *_NSConcreteStackBlock[]; 117351762cdSJohn McCall /// extern void *_NSConcreteGlobalBlock[]; 118351762cdSJohn McCall /// 119351762cdSJohn McCall /// In theory, we could start one off malloc'ed by setting 120351762cdSJohn McCall /// BLOCK_NEEDS_FREE, giving it a refcount of 1, and using 121351762cdSJohn McCall /// this isa: 122351762cdSJohn McCall /// extern void *_NSConcreteMallocBlock[]; 123351762cdSJohn McCall struct objc_class *isa; 12485284bacSMike Stump 125351762cdSJohn McCall /// These are the flags (with corresponding bit number) that the 126351762cdSJohn McCall /// compiler is actually supposed to know about. 127351762cdSJohn McCall /// 25. BLOCK_HAS_COPY_DISPOSE - indicates that the block 128351762cdSJohn McCall /// descriptor provides copy and dispose helper functions 129351762cdSJohn McCall /// 26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured 130351762cdSJohn McCall /// object with a nontrivial destructor or copy constructor 131351762cdSJohn McCall /// 28. BLOCK_IS_GLOBAL - indicates that the block is allocated 132351762cdSJohn McCall /// as global memory 133351762cdSJohn McCall /// 29. BLOCK_USE_STRET - indicates that the block function 134351762cdSJohn McCall /// uses stret, which objc_msgSend needs to know about 135351762cdSJohn McCall /// 30. BLOCK_HAS_SIGNATURE - indicates that the block has an 136351762cdSJohn McCall /// @encoded signature string 137351762cdSJohn McCall /// And we're not supposed to manipulate these: 138351762cdSJohn McCall /// 24. BLOCK_NEEDS_FREE - indicates that the block has been moved 139351762cdSJohn McCall /// to malloc'ed memory 140351762cdSJohn McCall /// 27. BLOCK_IS_GC - indicates that the block has been moved to 141351762cdSJohn McCall /// to GC-allocated memory 142351762cdSJohn McCall /// Additionally, the bottom 16 bits are a reference count which 143351762cdSJohn McCall /// should be zero on the stack. 144351762cdSJohn McCall int flags; 145950a9518SDavid Chisnall 146351762cdSJohn McCall /// Reserved; should be zero-initialized. 147351762cdSJohn McCall int reserved; 148950a9518SDavid Chisnall 149351762cdSJohn McCall /// Function pointer generated from block literal. 150351762cdSJohn McCall _ResultType (*invoke)(Block_literal *, _ParamTypes...); 15185284bacSMike Stump 152351762cdSJohn McCall /// Block description metadata generated from block literal. 153351762cdSJohn McCall struct Block_descriptor *block_descriptor; 1543882ace2SJohn McCall 155351762cdSJohn McCall /// Captured values follow. 156351762cdSJohn McCall _CapturesTypes captures...; 157351762cdSJohn McCall }; 158351762cdSJohn McCall */ 159950a9518SDavid Chisnall 160351762cdSJohn McCall /// The number of fields in a block header. 161351762cdSJohn McCall const unsigned BlockHeaderSize = 5; 1624446dcf0SMike Stump 163351762cdSJohn McCall namespace { 164351762cdSJohn McCall /// A chunk of data that we actually have to capture in the block. 165351762cdSJohn McCall struct BlockLayoutChunk { 166351762cdSJohn McCall CharUnits Alignment; 167351762cdSJohn McCall CharUnits Size; 168351762cdSJohn McCall const BlockDecl::Capture *Capture; // null for 'this' 1697c57be3eSJay Foad llvm::Type *Type; 17085284bacSMike Stump 171351762cdSJohn McCall BlockLayoutChunk(CharUnits align, CharUnits size, 172351762cdSJohn McCall const BlockDecl::Capture *capture, 1737c57be3eSJay Foad llvm::Type *type) 174351762cdSJohn McCall : Alignment(align), Size(size), Capture(capture), Type(type) {} 17585284bacSMike Stump 176351762cdSJohn McCall /// Tell the block info that this chunk has the given field index. 177351762cdSJohn McCall void setIndex(CGBlockInfo &info, unsigned index) { 178351762cdSJohn McCall if (!Capture) 179351762cdSJohn McCall info.CXXThisIndex = index; 180b750d928SMike Stump else 181351762cdSJohn McCall info.Captures[Capture->getVariable()] 182351762cdSJohn McCall = CGBlockInfo::Capture::makeIndex(index); 183b750d928SMike Stump } 184351762cdSJohn McCall }; 185d6ef62f0SMike Stump 186351762cdSJohn McCall /// Order by descending alignment. 187351762cdSJohn McCall bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) { 188351762cdSJohn McCall return left.Alignment > right.Alignment; 189351762cdSJohn McCall } 190b750d928SMike Stump } 191b750d928SMike Stump 192b0a3ecb4SJohn McCall /// Determines if the given type is safe for constant capture in C++. 193b0a3ecb4SJohn McCall static bool isSafeForCXXConstantCapture(QualType type) { 194b0a3ecb4SJohn McCall const RecordType *recordType = 195b0a3ecb4SJohn McCall type->getBaseElementTypeUnsafe()->getAs<RecordType>(); 196b0a3ecb4SJohn McCall 197b0a3ecb4SJohn McCall // Only records can be unsafe. 198b0a3ecb4SJohn McCall if (!recordType) return true; 199b0a3ecb4SJohn McCall 200b0a3ecb4SJohn McCall const CXXRecordDecl *record = cast<CXXRecordDecl>(recordType->getDecl()); 201b0a3ecb4SJohn McCall 202b0a3ecb4SJohn McCall // Maintain semantics for classes with non-trivial dtors or copy ctors. 203b0a3ecb4SJohn McCall if (!record->hasTrivialDestructor()) return false; 204b0a3ecb4SJohn McCall if (!record->hasTrivialCopyConstructor()) return false; 205b0a3ecb4SJohn McCall 206b0a3ecb4SJohn McCall // Otherwise, we just have to make sure there aren't any mutable 207b0a3ecb4SJohn McCall // fields that might have changed since initialization. 20861226d3fSDouglas Gregor return !record->hasMutableFields(); 209b0a3ecb4SJohn McCall } 210b0a3ecb4SJohn McCall 211351762cdSJohn McCall /// It is illegal to modify a const object after initialization. 212351762cdSJohn McCall /// Therefore, if a const object has a constant initializer, we don't 213351762cdSJohn McCall /// actually need to keep storage for it in the block; we'll just 214351762cdSJohn McCall /// rematerialize it at the start of the block function. This is 215351762cdSJohn McCall /// acceptable because we make no promises about address stability of 216351762cdSJohn McCall /// captured variables. 217351762cdSJohn McCall static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM, 218dafff947SRichard Smith CodeGenFunction *CGF, 219351762cdSJohn McCall const VarDecl *var) { 220351762cdSJohn McCall QualType type = var->getType(); 221351762cdSJohn McCall 222351762cdSJohn McCall // We can only do this if the variable is const. 223351762cdSJohn McCall if (!type.isConstQualified()) return 0; 224351762cdSJohn McCall 225b0a3ecb4SJohn McCall // Furthermore, in C++ we have to worry about mutable fields: 226b0a3ecb4SJohn McCall // C++ [dcl.type.cv]p4: 227b0a3ecb4SJohn McCall // Except that any class member declared mutable can be 228b0a3ecb4SJohn McCall // modified, any attempt to modify a const object during its 229b0a3ecb4SJohn McCall // lifetime results in undefined behavior. 230*bbafb8a7SDavid Blaikie if (CGM.getLangOpts().CPlusPlus && !isSafeForCXXConstantCapture(type)) 231351762cdSJohn McCall return 0; 232351762cdSJohn McCall 233351762cdSJohn McCall // If the variable doesn't have any initializer (shouldn't this be 234351762cdSJohn McCall // invalid?), it's not clear what we should do. Maybe capture as 235351762cdSJohn McCall // zero? 236351762cdSJohn McCall const Expr *init = var->getInit(); 237351762cdSJohn McCall if (!init) return 0; 238351762cdSJohn McCall 239dafff947SRichard Smith return CGM.EmitConstantInit(*var, CGF); 240351762cdSJohn McCall } 241351762cdSJohn McCall 242351762cdSJohn McCall /// Get the low bit of a nonzero character count. This is the 243351762cdSJohn McCall /// alignment of the nth byte if the 0th byte is universally aligned. 244351762cdSJohn McCall static CharUnits getLowBit(CharUnits v) { 245351762cdSJohn McCall return CharUnits::fromQuantity(v.getQuantity() & (~v.getQuantity() + 1)); 246351762cdSJohn McCall } 247351762cdSJohn McCall 248351762cdSJohn McCall static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info, 2490e62c1ccSChris Lattner SmallVectorImpl<llvm::Type*> &elementTypes) { 250351762cdSJohn McCall ASTContext &C = CGM.getContext(); 251351762cdSJohn McCall 252351762cdSJohn McCall // The header is basically a 'struct { void *; int; int; void *; void *; }'. 253351762cdSJohn McCall CharUnits ptrSize, ptrAlign, intSize, intAlign; 254351762cdSJohn McCall llvm::tie(ptrSize, ptrAlign) = C.getTypeInfoInChars(C.VoidPtrTy); 255351762cdSJohn McCall llvm::tie(intSize, intAlign) = C.getTypeInfoInChars(C.IntTy); 256351762cdSJohn McCall 257351762cdSJohn McCall // Are there crazy embedded platforms where this isn't true? 258351762cdSJohn McCall assert(intSize <= ptrSize && "layout assumptions horribly violated"); 259351762cdSJohn McCall 260351762cdSJohn McCall CharUnits headerSize = ptrSize; 261351762cdSJohn McCall if (2 * intSize < ptrAlign) headerSize += ptrSize; 262351762cdSJohn McCall else headerSize += 2 * intSize; 263351762cdSJohn McCall headerSize += 2 * ptrSize; 264351762cdSJohn McCall 265351762cdSJohn McCall info.BlockAlign = ptrAlign; 266351762cdSJohn McCall info.BlockSize = headerSize; 267351762cdSJohn McCall 268351762cdSJohn McCall assert(elementTypes.empty()); 2697c57be3eSJay Foad llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy); 2707c57be3eSJay Foad llvm::Type *intTy = CGM.getTypes().ConvertType(C.IntTy); 271351762cdSJohn McCall elementTypes.push_back(i8p); 272351762cdSJohn McCall elementTypes.push_back(intTy); 273351762cdSJohn McCall elementTypes.push_back(intTy); 274351762cdSJohn McCall elementTypes.push_back(i8p); 275351762cdSJohn McCall elementTypes.push_back(CGM.getBlockDescriptorType()); 276351762cdSJohn McCall 277351762cdSJohn McCall assert(elementTypes.size() == BlockHeaderSize); 278351762cdSJohn McCall } 279351762cdSJohn McCall 280351762cdSJohn McCall /// Compute the layout of the given block. Attempts to lay the block 281351762cdSJohn McCall /// out with minimal space requirements. 282dafff947SRichard Smith static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, 283dafff947SRichard Smith CGBlockInfo &info) { 284351762cdSJohn McCall ASTContext &C = CGM.getContext(); 285351762cdSJohn McCall const BlockDecl *block = info.getBlockDecl(); 286351762cdSJohn McCall 2870e62c1ccSChris Lattner SmallVector<llvm::Type*, 8> elementTypes; 288351762cdSJohn McCall initializeForBlockHeader(CGM, info, elementTypes); 289351762cdSJohn McCall 290351762cdSJohn McCall if (!block->hasCaptures()) { 291351762cdSJohn McCall info.StructureType = 292351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 293351762cdSJohn McCall info.CanBeGlobal = true; 294351762cdSJohn McCall return; 295351762cdSJohn McCall } 296351762cdSJohn McCall 297351762cdSJohn McCall // Collect the layout chunks. 2980e62c1ccSChris Lattner SmallVector<BlockLayoutChunk, 16> layout; 299351762cdSJohn McCall layout.reserve(block->capturesCXXThis() + 300351762cdSJohn McCall (block->capture_end() - block->capture_begin())); 301351762cdSJohn McCall 302351762cdSJohn McCall CharUnits maxFieldAlign; 303351762cdSJohn McCall 304351762cdSJohn McCall // First, 'this'. 305351762cdSJohn McCall if (block->capturesCXXThis()) { 306351762cdSJohn McCall const DeclContext *DC = block->getDeclContext(); 307351762cdSJohn McCall for (; isa<BlockDecl>(DC); DC = cast<BlockDecl>(DC)->getDeclContext()) 308351762cdSJohn McCall ; 309938f40b5SRichard Smith QualType thisType; 310938f40b5SRichard Smith if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) 311938f40b5SRichard Smith thisType = C.getPointerType(C.getRecordType(RD)); 312938f40b5SRichard Smith else 313938f40b5SRichard Smith thisType = cast<CXXMethodDecl>(DC)->getThisType(C); 314351762cdSJohn McCall 3157c57be3eSJay Foad llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType); 316351762cdSJohn McCall std::pair<CharUnits,CharUnits> tinfo 317351762cdSJohn McCall = CGM.getContext().getTypeInfoInChars(thisType); 318351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, tinfo.second); 319351762cdSJohn McCall 320351762cdSJohn McCall layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, 0, llvmType)); 321351762cdSJohn McCall } 322351762cdSJohn McCall 323351762cdSJohn McCall // Next, all the block captures. 324351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 325351762cdSJohn McCall ce = block->capture_end(); ci != ce; ++ci) { 326351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 327351762cdSJohn McCall 328351762cdSJohn McCall if (ci->isByRef()) { 329351762cdSJohn McCall // We have to copy/dispose of the __block reference. 330351762cdSJohn McCall info.NeedsCopyDispose = true; 331351762cdSJohn McCall 332351762cdSJohn McCall // Just use void* instead of a pointer to the byref type. 333351762cdSJohn McCall QualType byRefPtrTy = C.VoidPtrTy; 334351762cdSJohn McCall 3357c57be3eSJay Foad llvm::Type *llvmType = CGM.getTypes().ConvertType(byRefPtrTy); 336351762cdSJohn McCall std::pair<CharUnits,CharUnits> tinfo 337351762cdSJohn McCall = CGM.getContext().getTypeInfoInChars(byRefPtrTy); 338351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, tinfo.second); 339351762cdSJohn McCall 340351762cdSJohn McCall layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, 341351762cdSJohn McCall &*ci, llvmType)); 342351762cdSJohn McCall continue; 343351762cdSJohn McCall } 344351762cdSJohn McCall 345351762cdSJohn McCall // Otherwise, build a layout chunk with the size and alignment of 346351762cdSJohn McCall // the declaration. 347dafff947SRichard Smith if (llvm::Constant *constant = tryCaptureAsConstant(CGM, CGF, variable)) { 348351762cdSJohn McCall info.Captures[variable] = CGBlockInfo::Capture::makeConstant(constant); 349351762cdSJohn McCall continue; 350351762cdSJohn McCall } 351351762cdSJohn McCall 35231168b07SJohn McCall // If we have a lifetime qualifier, honor it for capture purposes. 35331168b07SJohn McCall // That includes *not* copying it if it's __unsafe_unretained. 35431168b07SJohn McCall if (Qualifiers::ObjCLifetime lifetime 35531168b07SJohn McCall = variable->getType().getObjCLifetime()) { 35631168b07SJohn McCall switch (lifetime) { 35731168b07SJohn McCall case Qualifiers::OCL_None: llvm_unreachable("impossible"); 35831168b07SJohn McCall case Qualifiers::OCL_ExplicitNone: 35931168b07SJohn McCall case Qualifiers::OCL_Autoreleasing: 36031168b07SJohn McCall break; 361351762cdSJohn McCall 36231168b07SJohn McCall case Qualifiers::OCL_Strong: 36331168b07SJohn McCall case Qualifiers::OCL_Weak: 36431168b07SJohn McCall info.NeedsCopyDispose = true; 36531168b07SJohn McCall } 36631168b07SJohn McCall 36731168b07SJohn McCall // Block pointers require copy/dispose. So do Objective-C pointers. 36831168b07SJohn McCall } else if (variable->getType()->isObjCRetainableType()) { 369351762cdSJohn McCall info.NeedsCopyDispose = true; 370351762cdSJohn McCall 371351762cdSJohn McCall // So do types that require non-trivial copy construction. 372351762cdSJohn McCall } else if (ci->hasCopyExpr()) { 373351762cdSJohn McCall info.NeedsCopyDispose = true; 374351762cdSJohn McCall info.HasCXXObject = true; 375351762cdSJohn McCall 376351762cdSJohn McCall // And so do types with destructors. 377*bbafb8a7SDavid Blaikie } else if (CGM.getLangOpts().CPlusPlus) { 378351762cdSJohn McCall if (const CXXRecordDecl *record = 379351762cdSJohn McCall variable->getType()->getAsCXXRecordDecl()) { 380351762cdSJohn McCall if (!record->hasTrivialDestructor()) { 381351762cdSJohn McCall info.HasCXXObject = true; 382351762cdSJohn McCall info.NeedsCopyDispose = true; 383351762cdSJohn McCall } 384351762cdSJohn McCall } 385351762cdSJohn McCall } 386351762cdSJohn McCall 38710317eaaSFariborz Jahanian QualType VT = variable->getType(); 388f0cda639SFariborz Jahanian CharUnits size = C.getTypeSizeInChars(VT); 38910317eaaSFariborz Jahanian CharUnits align = C.getDeclAlign(variable); 390f0cda639SFariborz Jahanian 391351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, align); 392351762cdSJohn McCall 3937c57be3eSJay Foad llvm::Type *llvmType = 394f0cda639SFariborz Jahanian CGM.getTypes().ConvertTypeForMem(VT); 395351762cdSJohn McCall 396351762cdSJohn McCall layout.push_back(BlockLayoutChunk(align, size, &*ci, llvmType)); 397351762cdSJohn McCall } 398351762cdSJohn McCall 399351762cdSJohn McCall // If that was everything, we're done here. 400351762cdSJohn McCall if (layout.empty()) { 401351762cdSJohn McCall info.StructureType = 402351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 403351762cdSJohn McCall info.CanBeGlobal = true; 404351762cdSJohn McCall return; 405351762cdSJohn McCall } 406351762cdSJohn McCall 407351762cdSJohn McCall // Sort the layout by alignment. We have to use a stable sort here 408351762cdSJohn McCall // to get reproducible results. There should probably be an 409351762cdSJohn McCall // llvm::array_pod_stable_sort. 410351762cdSJohn McCall std::stable_sort(layout.begin(), layout.end()); 411351762cdSJohn McCall 412351762cdSJohn McCall CharUnits &blockSize = info.BlockSize; 413351762cdSJohn McCall info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign); 414351762cdSJohn McCall 415351762cdSJohn McCall // Assuming that the first byte in the header is maximally aligned, 416351762cdSJohn McCall // get the alignment of the first byte following the header. 417351762cdSJohn McCall CharUnits endAlign = getLowBit(blockSize); 418351762cdSJohn McCall 419351762cdSJohn McCall // If the end of the header isn't satisfactorily aligned for the 420351762cdSJohn McCall // maximum thing, look for things that are okay with the header-end 421351762cdSJohn McCall // alignment, and keep appending them until we get something that's 422351762cdSJohn McCall // aligned right. This algorithm is only guaranteed optimal if 423351762cdSJohn McCall // that condition is satisfied at some point; otherwise we can get 424351762cdSJohn McCall // things like: 425351762cdSJohn McCall // header // next byte has alignment 4 426351762cdSJohn McCall // something_with_size_5; // next byte has alignment 1 427351762cdSJohn McCall // something_with_alignment_8; 428351762cdSJohn McCall // which has 7 bytes of padding, as opposed to the naive solution 429351762cdSJohn McCall // which might have less (?). 430351762cdSJohn McCall if (endAlign < maxFieldAlign) { 4310e62c1ccSChris Lattner SmallVectorImpl<BlockLayoutChunk>::iterator 432351762cdSJohn McCall li = layout.begin() + 1, le = layout.end(); 433351762cdSJohn McCall 434351762cdSJohn McCall // Look for something that the header end is already 435351762cdSJohn McCall // satisfactorily aligned for. 436351762cdSJohn McCall for (; li != le && endAlign < li->Alignment; ++li) 437351762cdSJohn McCall ; 438351762cdSJohn McCall 439351762cdSJohn McCall // If we found something that's naturally aligned for the end of 440351762cdSJohn McCall // the header, keep adding things... 441351762cdSJohn McCall if (li != le) { 4420e62c1ccSChris Lattner SmallVectorImpl<BlockLayoutChunk>::iterator first = li; 443351762cdSJohn McCall for (; li != le; ++li) { 444351762cdSJohn McCall assert(endAlign >= li->Alignment); 445351762cdSJohn McCall 446351762cdSJohn McCall li->setIndex(info, elementTypes.size()); 447351762cdSJohn McCall elementTypes.push_back(li->Type); 448351762cdSJohn McCall blockSize += li->Size; 449351762cdSJohn McCall endAlign = getLowBit(blockSize); 450351762cdSJohn McCall 451351762cdSJohn McCall // ...until we get to the alignment of the maximum field. 452351762cdSJohn McCall if (endAlign >= maxFieldAlign) 453351762cdSJohn McCall break; 454351762cdSJohn McCall } 455351762cdSJohn McCall 456351762cdSJohn McCall // Don't re-append everything we just appended. 457351762cdSJohn McCall layout.erase(first, li); 458351762cdSJohn McCall } 459351762cdSJohn McCall } 460351762cdSJohn McCall 461351762cdSJohn McCall // At this point, we just have to add padding if the end align still 462351762cdSJohn McCall // isn't aligned right. 463351762cdSJohn McCall if (endAlign < maxFieldAlign) { 464351762cdSJohn McCall CharUnits padding = maxFieldAlign - endAlign; 465351762cdSJohn McCall 466e3dc1707SJohn McCall elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty, 467e3dc1707SJohn McCall padding.getQuantity())); 468351762cdSJohn McCall blockSize += padding; 469351762cdSJohn McCall 470351762cdSJohn McCall endAlign = getLowBit(blockSize); 471351762cdSJohn McCall assert(endAlign >= maxFieldAlign); 472351762cdSJohn McCall } 473351762cdSJohn McCall 474351762cdSJohn McCall // Slam everything else on now. This works because they have 475351762cdSJohn McCall // strictly decreasing alignment and we expect that size is always a 476351762cdSJohn McCall // multiple of alignment. 4770e62c1ccSChris Lattner for (SmallVectorImpl<BlockLayoutChunk>::iterator 478351762cdSJohn McCall li = layout.begin(), le = layout.end(); li != le; ++li) { 479351762cdSJohn McCall assert(endAlign >= li->Alignment); 480351762cdSJohn McCall li->setIndex(info, elementTypes.size()); 481351762cdSJohn McCall elementTypes.push_back(li->Type); 482351762cdSJohn McCall blockSize += li->Size; 483351762cdSJohn McCall endAlign = getLowBit(blockSize); 484351762cdSJohn McCall } 485351762cdSJohn McCall 486351762cdSJohn McCall info.StructureType = 487351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 488351762cdSJohn McCall } 489351762cdSJohn McCall 49008ef4660SJohn McCall /// Enter the scope of a block. This should be run at the entrance to 49108ef4660SJohn McCall /// a full-expression so that the block's cleanups are pushed at the 49208ef4660SJohn McCall /// right place in the stack. 49308ef4660SJohn McCall static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) { 49408ef4660SJohn McCall // Allocate the block info and place it at the head of the list. 49508ef4660SJohn McCall CGBlockInfo &blockInfo = 49608ef4660SJohn McCall *new CGBlockInfo(block, CGF.CurFn->getName()); 49708ef4660SJohn McCall blockInfo.NextBlockInfo = CGF.FirstBlockInfo; 49808ef4660SJohn McCall CGF.FirstBlockInfo = &blockInfo; 49908ef4660SJohn McCall 50008ef4660SJohn McCall // Compute information about the layout, etc., of this block, 50108ef4660SJohn McCall // pushing cleanups as necessary. 502dafff947SRichard Smith computeBlockInfo(CGF.CGM, &CGF, blockInfo); 50308ef4660SJohn McCall 50408ef4660SJohn McCall // Nothing else to do if it can be global. 50508ef4660SJohn McCall if (blockInfo.CanBeGlobal) return; 50608ef4660SJohn McCall 50708ef4660SJohn McCall // Make the allocation for the block. 50808ef4660SJohn McCall blockInfo.Address = 50908ef4660SJohn McCall CGF.CreateTempAlloca(blockInfo.StructureType, "block"); 51008ef4660SJohn McCall blockInfo.Address->setAlignment(blockInfo.BlockAlign.getQuantity()); 51108ef4660SJohn McCall 51208ef4660SJohn McCall // If there are cleanups to emit, enter them (but inactive). 51308ef4660SJohn McCall if (!blockInfo.NeedsCopyDispose) return; 51408ef4660SJohn McCall 51508ef4660SJohn McCall // Walk through the captures (in order) and find the ones not 51608ef4660SJohn McCall // captured by constant. 51708ef4660SJohn McCall for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 51808ef4660SJohn McCall ce = block->capture_end(); ci != ce; ++ci) { 51908ef4660SJohn McCall // Ignore __block captures; there's nothing special in the 52008ef4660SJohn McCall // on-stack block that we need to do for them. 52108ef4660SJohn McCall if (ci->isByRef()) continue; 52208ef4660SJohn McCall 52308ef4660SJohn McCall // Ignore variables that are constant-captured. 52408ef4660SJohn McCall const VarDecl *variable = ci->getVariable(); 52508ef4660SJohn McCall CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 52608ef4660SJohn McCall if (capture.isConstant()) continue; 52708ef4660SJohn McCall 52808ef4660SJohn McCall // Ignore objects that aren't destructed. 52908ef4660SJohn McCall QualType::DestructionKind dtorKind = 53008ef4660SJohn McCall variable->getType().isDestructedType(); 53108ef4660SJohn McCall if (dtorKind == QualType::DK_none) continue; 53208ef4660SJohn McCall 53308ef4660SJohn McCall CodeGenFunction::Destroyer *destroyer; 53408ef4660SJohn McCall 53508ef4660SJohn McCall // Block captures count as local values and have imprecise semantics. 53608ef4660SJohn McCall // They also can't be arrays, so need to worry about that. 53708ef4660SJohn McCall if (dtorKind == QualType::DK_objc_strong_lifetime) { 5381425b455SPeter Collingbourne destroyer = CodeGenFunction::destroyARCStrongImprecise; 53908ef4660SJohn McCall } else { 5401425b455SPeter Collingbourne destroyer = CGF.getDestroyer(dtorKind); 54108ef4660SJohn McCall } 54208ef4660SJohn McCall 54308ef4660SJohn McCall // GEP down to the address. 54408ef4660SJohn McCall llvm::Value *addr = CGF.Builder.CreateStructGEP(blockInfo.Address, 54508ef4660SJohn McCall capture.getIndex()); 54608ef4660SJohn McCall 547f4beacd0SJohn McCall // We can use that GEP as the dominating IP. 548f4beacd0SJohn McCall if (!blockInfo.DominatingIP) 549f4beacd0SJohn McCall blockInfo.DominatingIP = cast<llvm::Instruction>(addr); 550f4beacd0SJohn McCall 55108ef4660SJohn McCall CleanupKind cleanupKind = InactiveNormalCleanup; 55208ef4660SJohn McCall bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind); 55308ef4660SJohn McCall if (useArrayEHCleanup) 55408ef4660SJohn McCall cleanupKind = InactiveNormalAndEHCleanup; 55508ef4660SJohn McCall 55608ef4660SJohn McCall CGF.pushDestroy(cleanupKind, addr, variable->getType(), 5571425b455SPeter Collingbourne destroyer, useArrayEHCleanup); 55808ef4660SJohn McCall 55908ef4660SJohn McCall // Remember where that cleanup was. 56008ef4660SJohn McCall capture.setCleanup(CGF.EHStack.stable_begin()); 56108ef4660SJohn McCall } 56208ef4660SJohn McCall } 56308ef4660SJohn McCall 56408ef4660SJohn McCall /// Enter a full-expression with a non-trivial number of objects to 56508ef4660SJohn McCall /// clean up. This is in this file because, at the moment, the only 56608ef4660SJohn McCall /// kind of cleanup object is a BlockDecl*. 56708ef4660SJohn McCall void CodeGenFunction::enterNonTrivialFullExpression(const ExprWithCleanups *E) { 56808ef4660SJohn McCall assert(E->getNumObjects() != 0); 56908ef4660SJohn McCall ArrayRef<ExprWithCleanups::CleanupObject> cleanups = E->getObjects(); 57008ef4660SJohn McCall for (ArrayRef<ExprWithCleanups::CleanupObject>::iterator 57108ef4660SJohn McCall i = cleanups.begin(), e = cleanups.end(); i != e; ++i) { 57208ef4660SJohn McCall enterBlockScope(*this, *i); 57308ef4660SJohn McCall } 57408ef4660SJohn McCall } 57508ef4660SJohn McCall 57608ef4660SJohn McCall /// Find the layout for the given block in a linked list and remove it. 57708ef4660SJohn McCall static CGBlockInfo *findAndRemoveBlockInfo(CGBlockInfo **head, 57808ef4660SJohn McCall const BlockDecl *block) { 57908ef4660SJohn McCall while (true) { 58008ef4660SJohn McCall assert(head && *head); 58108ef4660SJohn McCall CGBlockInfo *cur = *head; 58208ef4660SJohn McCall 58308ef4660SJohn McCall // If this is the block we're looking for, splice it out of the list. 58408ef4660SJohn McCall if (cur->getBlockDecl() == block) { 58508ef4660SJohn McCall *head = cur->NextBlockInfo; 58608ef4660SJohn McCall return cur; 58708ef4660SJohn McCall } 58808ef4660SJohn McCall 58908ef4660SJohn McCall head = &cur->NextBlockInfo; 59008ef4660SJohn McCall } 59108ef4660SJohn McCall } 59208ef4660SJohn McCall 59308ef4660SJohn McCall /// Destroy a chain of block layouts. 59408ef4660SJohn McCall void CodeGenFunction::destroyBlockInfos(CGBlockInfo *head) { 59508ef4660SJohn McCall assert(head && "destroying an empty chain"); 59608ef4660SJohn McCall do { 59708ef4660SJohn McCall CGBlockInfo *cur = head; 59808ef4660SJohn McCall head = cur->NextBlockInfo; 59908ef4660SJohn McCall delete cur; 60008ef4660SJohn McCall } while (head != 0); 60108ef4660SJohn McCall } 60208ef4660SJohn McCall 603351762cdSJohn McCall /// Emit a block literal expression in the current function. 604351762cdSJohn McCall llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { 60508ef4660SJohn McCall // If the block has no captures, we won't have a pre-computed 60608ef4660SJohn McCall // layout for it. 60708ef4660SJohn McCall if (!blockExpr->getBlockDecl()->hasCaptures()) { 60808ef4660SJohn McCall CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName()); 609dafff947SRichard Smith computeBlockInfo(CGM, this, blockInfo); 61008ef4660SJohn McCall blockInfo.BlockExpression = blockExpr; 61108ef4660SJohn McCall return EmitBlockLiteral(blockInfo); 61208ef4660SJohn McCall } 613351762cdSJohn McCall 61408ef4660SJohn McCall // Find the block info for this block and take ownership of it. 615e2778999SDylan Noblesmith OwningPtr<CGBlockInfo> blockInfo; 61608ef4660SJohn McCall blockInfo.reset(findAndRemoveBlockInfo(&FirstBlockInfo, 61708ef4660SJohn McCall blockExpr->getBlockDecl())); 61808ef4660SJohn McCall 61908ef4660SJohn McCall blockInfo->BlockExpression = blockExpr; 62008ef4660SJohn McCall return EmitBlockLiteral(*blockInfo); 62108ef4660SJohn McCall } 62208ef4660SJohn McCall 62308ef4660SJohn McCall llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { 62408ef4660SJohn McCall // Using the computed layout, generate the actual block function. 62598b01edcSEli Friedman bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda(); 626351762cdSJohn McCall llvm::Constant *blockFn 627351762cdSJohn McCall = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, blockInfo, 6282495ab08SEli Friedman CurFuncDecl, LocalDeclMap, 62998b01edcSEli Friedman isLambdaConv); 630e3dc1707SJohn McCall blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); 631351762cdSJohn McCall 632351762cdSJohn McCall // If there is nothing to capture, we can emit this as a global block. 633351762cdSJohn McCall if (blockInfo.CanBeGlobal) 634351762cdSJohn McCall return buildGlobalBlock(CGM, blockInfo, blockFn); 635351762cdSJohn McCall 636351762cdSJohn McCall // Otherwise, we have to emit this as a local block. 637351762cdSJohn McCall 638351762cdSJohn McCall llvm::Constant *isa = CGM.getNSConcreteStackBlock(); 639e3dc1707SJohn McCall isa = llvm::ConstantExpr::getBitCast(isa, VoidPtrTy); 640351762cdSJohn McCall 641351762cdSJohn McCall // Build the block descriptor. 642351762cdSJohn McCall llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo); 643351762cdSJohn McCall 64408ef4660SJohn McCall llvm::AllocaInst *blockAddr = blockInfo.Address; 64508ef4660SJohn McCall assert(blockAddr && "block has no address!"); 646351762cdSJohn McCall 647351762cdSJohn McCall // Compute the initial on-stack block flags. 648ad7c5c16SJohn McCall BlockFlags flags = BLOCK_HAS_SIGNATURE; 649351762cdSJohn McCall if (blockInfo.NeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE; 650351762cdSJohn McCall if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ; 65185915250SJohn McCall if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; 652351762cdSJohn McCall 653351762cdSJohn McCall // Initialize the block literal. 654351762cdSJohn McCall Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa")); 65508ef4660SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()), 656351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, 1, "block.flags")); 65708ef4660SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(IntTy, 0), 658351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, 2, "block.reserved")); 659351762cdSJohn McCall Builder.CreateStore(blockFn, Builder.CreateStructGEP(blockAddr, 3, 660351762cdSJohn McCall "block.invoke")); 661351762cdSJohn McCall Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockAddr, 4, 662351762cdSJohn McCall "block.descriptor")); 663351762cdSJohn McCall 664351762cdSJohn McCall // Finally, capture all the values into the block. 665351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 666351762cdSJohn McCall 667351762cdSJohn McCall // First, 'this'. 668351762cdSJohn McCall if (blockDecl->capturesCXXThis()) { 669351762cdSJohn McCall llvm::Value *addr = Builder.CreateStructGEP(blockAddr, 670351762cdSJohn McCall blockInfo.CXXThisIndex, 671351762cdSJohn McCall "block.captured-this.addr"); 672351762cdSJohn McCall Builder.CreateStore(LoadCXXThis(), addr); 673351762cdSJohn McCall } 674351762cdSJohn McCall 675351762cdSJohn McCall // Next, captured variables. 676351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 677351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 678351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 679351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 680351762cdSJohn McCall 681351762cdSJohn McCall // Ignore constant captures. 682351762cdSJohn McCall if (capture.isConstant()) continue; 683351762cdSJohn McCall 684351762cdSJohn McCall QualType type = variable->getType(); 685351762cdSJohn McCall 686351762cdSJohn McCall // This will be a [[type]]*, except that a byref entry will just be 687351762cdSJohn McCall // an i8**. 688351762cdSJohn McCall llvm::Value *blockField = 689351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, capture.getIndex(), 690351762cdSJohn McCall "block.captured"); 691351762cdSJohn McCall 692351762cdSJohn McCall // Compute the address of the thing we're going to move into the 693351762cdSJohn McCall // block literal. 694351762cdSJohn McCall llvm::Value *src; 695351762cdSJohn McCall if (ci->isNested()) { 696351762cdSJohn McCall // We need to use the capture from the enclosing block. 697351762cdSJohn McCall const CGBlockInfo::Capture &enclosingCapture = 698351762cdSJohn McCall BlockInfo->getCapture(variable); 699351762cdSJohn McCall 700351762cdSJohn McCall // This is a [[type]]*, except that a byref entry wil just be an i8**. 701351762cdSJohn McCall src = Builder.CreateStructGEP(LoadBlockStruct(), 702351762cdSJohn McCall enclosingCapture.getIndex(), 703351762cdSJohn McCall "block.capture.addr"); 70498b01edcSEli Friedman } else if (blockDecl->isConversionFromLambda()) { 7052495ab08SEli Friedman // The lambda capture in a lambda's conversion-to-block-pointer is 70698b01edcSEli Friedman // special; we'll simply emit it directly. 70798b01edcSEli Friedman src = 0; 708351762cdSJohn McCall } else { 709351762cdSJohn McCall // This is a [[type]]*. 710351762cdSJohn McCall src = LocalDeclMap[variable]; 711351762cdSJohn McCall } 712351762cdSJohn McCall 713351762cdSJohn McCall // For byrefs, we just write the pointer to the byref struct into 714351762cdSJohn McCall // the block field. There's no need to chase the forwarding 715351762cdSJohn McCall // pointer at this point, since we're building something that will 716351762cdSJohn McCall // live a shorter life than the stack byref anyway. 717351762cdSJohn McCall if (ci->isByRef()) { 718e3dc1707SJohn McCall // Get a void* that points to the byref struct. 719351762cdSJohn McCall if (ci->isNested()) 720351762cdSJohn McCall src = Builder.CreateLoad(src, "byref.capture"); 721351762cdSJohn McCall else 722e3dc1707SJohn McCall src = Builder.CreateBitCast(src, VoidPtrTy); 723351762cdSJohn McCall 724e3dc1707SJohn McCall // Write that void* into the capture field. 725351762cdSJohn McCall Builder.CreateStore(src, blockField); 726351762cdSJohn McCall 727351762cdSJohn McCall // If we have a copy constructor, evaluate that into the block field. 728351762cdSJohn McCall } else if (const Expr *copyExpr = ci->getCopyExpr()) { 72998b01edcSEli Friedman if (blockDecl->isConversionFromLambda()) { 73098b01edcSEli Friedman // If we have a lambda conversion, emit the expression 73198b01edcSEli Friedman // directly into the block instead. 73298b01edcSEli Friedman CharUnits Align = getContext().getTypeAlignInChars(type); 73398b01edcSEli Friedman AggValueSlot Slot = 73498b01edcSEli Friedman AggValueSlot::forAddr(blockField, Align, Qualifiers(), 73598b01edcSEli Friedman AggValueSlot::IsDestructed, 73698b01edcSEli Friedman AggValueSlot::DoesNotNeedGCBarriers, 73798b01edcSEli Friedman AggValueSlot::IsNotAliased); 73898b01edcSEli Friedman EmitAggExpr(copyExpr, Slot); 73998b01edcSEli Friedman } else { 740351762cdSJohn McCall EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr); 74198b01edcSEli Friedman } 742351762cdSJohn McCall 743351762cdSJohn McCall // If it's a reference variable, copy the reference into the block field. 74410317eaaSFariborz Jahanian } else if (type->isReferenceType()) { 745351762cdSJohn McCall Builder.CreateStore(Builder.CreateLoad(src, "ref.val"), blockField); 746351762cdSJohn McCall 747351762cdSJohn McCall // Otherwise, fake up a POD copy into the block field. 748351762cdSJohn McCall } else { 74931168b07SJohn McCall // Fake up a new variable so that EmitScalarInit doesn't think 75031168b07SJohn McCall // we're referring to the variable in its own initializer. 75131168b07SJohn McCall ImplicitParamDecl blockFieldPseudoVar(/*DC*/ 0, SourceLocation(), 75210317eaaSFariborz Jahanian /*name*/ 0, type); 75331168b07SJohn McCall 75493be3f75SJohn McCall // We use one of these or the other depending on whether the 75593be3f75SJohn McCall // reference is nested. 756113bee05SJohn McCall DeclRefExpr declRef(const_cast<VarDecl*>(variable), 757113bee05SJohn McCall /*refersToEnclosing*/ ci->isNested(), type, 758113bee05SJohn McCall VK_LValue, SourceLocation()); 75993be3f75SJohn McCall 76010317eaaSFariborz Jahanian ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue, 761113bee05SJohn McCall &declRef, VK_RValue); 7621553b190SJohn McCall EmitExprAsInit(&l2r, &blockFieldPseudoVar, 76310317eaaSFariborz Jahanian MakeAddrLValue(blockField, type, 764a0544d6fSEli Friedman getContext().getDeclAlign(variable)), 7655c8f6c47SJohn McCall /*captured by init*/ false); 766351762cdSJohn McCall } 767351762cdSJohn McCall 76808ef4660SJohn McCall // Activate the cleanup if layout pushed one. 76931168b07SJohn McCall if (!ci->isByRef()) { 77008ef4660SJohn McCall EHScopeStack::stable_iterator cleanup = capture.getCleanup(); 77108ef4660SJohn McCall if (cleanup.isValid()) 772f4beacd0SJohn McCall ActivateCleanupBlock(cleanup, blockInfo.DominatingIP); 77331168b07SJohn McCall } 774351762cdSJohn McCall } 775351762cdSJohn McCall 776351762cdSJohn McCall // Cast to the converted block-pointer type, which happens (somewhat 777351762cdSJohn McCall // unfortunately) to be a pointer to function type. 778351762cdSJohn McCall llvm::Value *result = 779351762cdSJohn McCall Builder.CreateBitCast(blockAddr, 780351762cdSJohn McCall ConvertType(blockInfo.getBlockExpr()->getType())); 7813882ace2SJohn McCall 782351762cdSJohn McCall return result; 783b750d928SMike Stump } 78485284bacSMike Stump 78585284bacSMike Stump 786a5f58b05SChris Lattner llvm::Type *CodeGenModule::getBlockDescriptorType() { 787650c932dSMike Stump if (BlockDescriptorType) 788650c932dSMike Stump return BlockDescriptorType; 7892437cbfaSAnders Carlsson 790a5f58b05SChris Lattner llvm::Type *UnsignedLongTy = 791650c932dSMike Stump getTypes().ConvertType(getContext().UnsignedLongTy); 7922437cbfaSAnders Carlsson 7932437cbfaSAnders Carlsson // struct __block_descriptor { 7942437cbfaSAnders Carlsson // unsigned long reserved; 7952437cbfaSAnders Carlsson // unsigned long block_size; 796fc83aa04SBlaine Garst // 797fc83aa04SBlaine Garst // // later, the following will be added 798fc83aa04SBlaine Garst // 799fc83aa04SBlaine Garst // struct { 800fc83aa04SBlaine Garst // void (*copyHelper)(); 801fc83aa04SBlaine Garst // void (*copyHelper)(); 802fc83aa04SBlaine Garst // } helpers; // !!! optional 803fc83aa04SBlaine Garst // 804fc83aa04SBlaine Garst // const char *signature; // the block signature 805fc83aa04SBlaine Garst // const char *layout; // reserved 8062437cbfaSAnders Carlsson // }; 807845511feSChris Lattner BlockDescriptorType = 8085ec04a51SChris Lattner llvm::StructType::create("struct.__block_descriptor", 809a5f58b05SChris Lattner UnsignedLongTy, UnsignedLongTy, NULL); 8102437cbfaSAnders Carlsson 811351762cdSJohn McCall // Now form a pointer to that. 812351762cdSJohn McCall BlockDescriptorType = llvm::PointerType::getUnqual(BlockDescriptorType); 813650c932dSMike Stump return BlockDescriptorType; 8142437cbfaSAnders Carlsson } 8152437cbfaSAnders Carlsson 816a5f58b05SChris Lattner llvm::Type *CodeGenModule::getGenericBlockLiteralType() { 817005c9a62SMike Stump if (GenericBlockLiteralType) 818005c9a62SMike Stump return GenericBlockLiteralType; 8192437cbfaSAnders Carlsson 820a5f58b05SChris Lattner llvm::Type *BlockDescPtrTy = getBlockDescriptorType(); 8212437cbfaSAnders Carlsson 8222437cbfaSAnders Carlsson // struct __block_literal_generic { 8235d2534adSMike Stump // void *__isa; 8245d2534adSMike Stump // int __flags; 8255d2534adSMike Stump // int __reserved; 8265d2534adSMike Stump // void (*__invoke)(void *); 8275d2534adSMike Stump // struct __block_descriptor *__descriptor; 8282437cbfaSAnders Carlsson // }; 829a5f58b05SChris Lattner GenericBlockLiteralType = 8305ec04a51SChris Lattner llvm::StructType::create("struct.__block_literal_generic", 8315ec04a51SChris Lattner VoidPtrTy, IntTy, IntTy, VoidPtrTy, 8325ec04a51SChris Lattner BlockDescPtrTy, NULL); 8332437cbfaSAnders Carlsson 834005c9a62SMike Stump return GenericBlockLiteralType; 8352437cbfaSAnders Carlsson } 8362437cbfaSAnders Carlsson 8375d2534adSMike Stump 838bfb3671bSAnders Carlsson RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E, 839bfb3671bSAnders Carlsson ReturnValueSlot ReturnValue) { 8402437cbfaSAnders Carlsson const BlockPointerType *BPT = 841c23c7e6aSTed Kremenek E->getCallee()->getType()->getAs<BlockPointerType>(); 8422437cbfaSAnders Carlsson 8432437cbfaSAnders Carlsson llvm::Value *Callee = EmitScalarExpr(E->getCallee()); 8442437cbfaSAnders Carlsson 8452437cbfaSAnders Carlsson // Get a pointer to the generic block literal. 8462192fe50SChris Lattner llvm::Type *BlockLiteralTy = 8479793f0e4SOwen Anderson llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType()); 8482437cbfaSAnders Carlsson 8492437cbfaSAnders Carlsson // Bitcast the callee to a block literal. 8502437cbfaSAnders Carlsson llvm::Value *BlockLiteral = 8512437cbfaSAnders Carlsson Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal"); 8522437cbfaSAnders Carlsson 8532437cbfaSAnders Carlsson // Get the function pointer from the literal. 85476399eb2SBenjamin Kramer llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3); 8552437cbfaSAnders Carlsson 85676399eb2SBenjamin Kramer BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy); 8572437cbfaSAnders Carlsson 8582437cbfaSAnders Carlsson // Add the block literal. 8592437cbfaSAnders Carlsson CallArgList Args; 8609dc0db21SJohn McCall Args.add(RValue::get(BlockLiteral), getContext().VoidPtrTy); 8612437cbfaSAnders Carlsson 862479e6fc7SAnders Carlsson QualType FnType = BPT->getPointeeType(); 863479e6fc7SAnders Carlsson 8642437cbfaSAnders Carlsson // And the rest of the arguments. 8659dd450bbSJohn McCall EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), 866479e6fc7SAnders Carlsson E->arg_begin(), E->arg_end()); 8672437cbfaSAnders Carlsson 8685f50c651SAnders Carlsson // Load the function. 86976399eb2SBenjamin Kramer llvm::Value *Func = Builder.CreateLoad(FuncPtr); 8705f50c651SAnders Carlsson 87185915250SJohn McCall const FunctionType *FuncTy = FnType->castAs<FunctionType>(); 872a729c62bSJohn McCall const CGFunctionInfo &FnInfo = 873a729c62bSJohn McCall CGM.getTypes().arrangeFunctionCall(Args, FuncTy); 8745f50c651SAnders Carlsson 8755f50c651SAnders Carlsson // Cast the function pointer to the right type. 876a729c62bSJohn McCall llvm::Type *BlockFTy = CGM.getTypes().GetFunctionType(FnInfo); 8775f50c651SAnders Carlsson 8782192fe50SChris Lattner llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); 8795f50c651SAnders Carlsson Func = Builder.CreateBitCast(Func, BlockFTyPtr); 8805f50c651SAnders Carlsson 8812437cbfaSAnders Carlsson // And call the block. 882bfb3671bSAnders Carlsson return EmitCall(FnInfo, Func, ReturnValue, Args); 8832437cbfaSAnders Carlsson } 8846a60fa24SAnders Carlsson 885351762cdSJohn McCall llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable, 886351762cdSJohn McCall bool isByRef) { 887351762cdSJohn McCall assert(BlockInfo && "evaluating block ref without block information?"); 888351762cdSJohn McCall const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable); 88987fe5d56SJohn McCall 890351762cdSJohn McCall // Handle constant captures. 891351762cdSJohn McCall if (capture.isConstant()) return LocalDeclMap[variable]; 89287fe5d56SJohn McCall 893351762cdSJohn McCall llvm::Value *addr = 894351762cdSJohn McCall Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(), 895351762cdSJohn McCall "block.capture.addr"); 896351762cdSJohn McCall 897351762cdSJohn McCall if (isByRef) { 898351762cdSJohn McCall // addr should be a void** right now. Load, then cast the result 899351762cdSJohn McCall // to byref*. 900351762cdSJohn McCall 901351762cdSJohn McCall addr = Builder.CreateLoad(addr); 9022192fe50SChris Lattner llvm::PointerType *byrefPointerType 903351762cdSJohn McCall = llvm::PointerType::get(BuildByRefType(variable), 0); 904351762cdSJohn McCall addr = Builder.CreateBitCast(addr, byrefPointerType, 905351762cdSJohn McCall "byref.addr"); 906351762cdSJohn McCall 907351762cdSJohn McCall // Follow the forwarding pointer. 908351762cdSJohn McCall addr = Builder.CreateStructGEP(addr, 1, "byref.forwarding"); 909351762cdSJohn McCall addr = Builder.CreateLoad(addr, "byref.addr.forwarded"); 910351762cdSJohn McCall 911351762cdSJohn McCall // Cast back to byref* and GEP over to the actual object. 912351762cdSJohn McCall addr = Builder.CreateBitCast(addr, byrefPointerType); 913351762cdSJohn McCall addr = Builder.CreateStructGEP(addr, getByRefValueLLVMField(variable), 914351762cdSJohn McCall variable->getNameAsString()); 91587fe5d56SJohn McCall } 91687fe5d56SJohn McCall 91710317eaaSFariborz Jahanian if (variable->getType()->isReferenceType()) 918351762cdSJohn McCall addr = Builder.CreateLoad(addr, "ref.tmp"); 9190168f4b2SAnders Carlsson 920351762cdSJohn McCall return addr; 92197d01d50SMike Stump } 92297d01d50SMike Stump 9232d5a2878SMike Stump llvm::Constant * 924ad7c5c16SJohn McCall CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr, 925351762cdSJohn McCall const char *name) { 92608ef4660SJohn McCall CGBlockInfo blockInfo(blockExpr->getBlockDecl(), name); 92708ef4660SJohn McCall blockInfo.BlockExpression = blockExpr; 9286a60fa24SAnders Carlsson 929351762cdSJohn McCall // Compute information about the layout, etc., of this block. 930dafff947SRichard Smith computeBlockInfo(*this, 0, blockInfo); 9316a60fa24SAnders Carlsson 932351762cdSJohn McCall // Using that metadata, generate the actual block function. 933351762cdSJohn McCall llvm::Constant *blockFn; 934351762cdSJohn McCall { 9355469f29aSMike Stump llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap; 936ad7c5c16SJohn McCall blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(), 937351762cdSJohn McCall blockInfo, 9382495ab08SEli Friedman 0, LocalDeclMap, 9392495ab08SEli Friedman false); 940351762cdSJohn McCall } 941e3dc1707SJohn McCall blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); 9426a60fa24SAnders Carlsson 943ad7c5c16SJohn McCall return buildGlobalBlock(*this, blockInfo, blockFn); 9446a60fa24SAnders Carlsson } 9456a60fa24SAnders Carlsson 946351762cdSJohn McCall static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, 947351762cdSJohn McCall const CGBlockInfo &blockInfo, 948351762cdSJohn McCall llvm::Constant *blockFn) { 949351762cdSJohn McCall assert(blockInfo.CanBeGlobal); 950351762cdSJohn McCall 951351762cdSJohn McCall // Generate the constants for the block literal initializer. 952351762cdSJohn McCall llvm::Constant *fields[BlockHeaderSize]; 953351762cdSJohn McCall 954351762cdSJohn McCall // isa 955351762cdSJohn McCall fields[0] = CGM.getNSConcreteGlobalBlock(); 956351762cdSJohn McCall 957351762cdSJohn McCall // __flags 95885915250SJohn McCall BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE; 95985915250SJohn McCall if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; 96085915250SJohn McCall 961e3dc1707SJohn McCall fields[1] = llvm::ConstantInt::get(CGM.IntTy, flags.getBitMask()); 962351762cdSJohn McCall 963351762cdSJohn McCall // Reserved 964e3dc1707SJohn McCall fields[2] = llvm::Constant::getNullValue(CGM.IntTy); 965351762cdSJohn McCall 966351762cdSJohn McCall // Function 967351762cdSJohn McCall fields[3] = blockFn; 968351762cdSJohn McCall 969351762cdSJohn McCall // Descriptor 970351762cdSJohn McCall fields[4] = buildBlockDescriptor(CGM, blockInfo); 971351762cdSJohn McCall 972e64d7ba1SChris Lattner llvm::Constant *init = llvm::ConstantStruct::getAnon(fields); 973351762cdSJohn McCall 974351762cdSJohn McCall llvm::GlobalVariable *literal = 975351762cdSJohn McCall new llvm::GlobalVariable(CGM.getModule(), 976351762cdSJohn McCall init->getType(), 977351762cdSJohn McCall /*constant*/ true, 978351762cdSJohn McCall llvm::GlobalVariable::InternalLinkage, 979351762cdSJohn McCall init, 980351762cdSJohn McCall "__block_literal_global"); 981351762cdSJohn McCall literal->setAlignment(blockInfo.BlockAlign.getQuantity()); 982351762cdSJohn McCall 983351762cdSJohn McCall // Return a constant of the appropriately-casted type. 9842192fe50SChris Lattner llvm::Type *requiredType = 985351762cdSJohn McCall CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType()); 986351762cdSJohn McCall return llvm::ConstantExpr::getBitCast(literal, requiredType); 987cb2fbcb0SMike Stump } 988cb2fbcb0SMike Stump 9894446dcf0SMike Stump llvm::Function * 990351762cdSJohn McCall CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, 991351762cdSJohn McCall const CGBlockInfo &blockInfo, 992351762cdSJohn McCall const Decl *outerFnDecl, 9932495ab08SEli Friedman const DeclMapTy &ldm, 9942495ab08SEli Friedman bool IsLambdaConversionToBlock) { 995351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 9969074ed8cSDevang Patel 9976e40c615SDevang Patel // Check if we should generate debug info for this block function. 9986e40c615SDevang Patel if (CGM.getModuleDebugInfo()) 9996e40c615SDevang Patel DebugInfo = CGM.getModuleDebugInfo(); 10006e40c615SDevang Patel 1001351762cdSJohn McCall BlockInfo = &blockInfo; 10029074ed8cSDevang Patel 10035469f29aSMike Stump // Arrange for local static and local extern declarations to appear 1004351762cdSJohn McCall // to be local to this function as well, in case they're directly 1005351762cdSJohn McCall // referenced in a block. 1006351762cdSJohn McCall for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) { 1007351762cdSJohn McCall const VarDecl *var = dyn_cast<VarDecl>(i->first); 1008351762cdSJohn McCall if (var && !var->hasLocalStorage()) 1009351762cdSJohn McCall LocalDeclMap[var] = i->second; 10105469f29aSMike Stump } 10115469f29aSMike Stump 1012351762cdSJohn McCall // Begin building the function declaration. 101309a9b6e3SEli Friedman 1014351762cdSJohn McCall // Build the argument list. 1015351762cdSJohn McCall FunctionArgList args; 10166a60fa24SAnders Carlsson 1017351762cdSJohn McCall // The first argument is the block pointer. Just take it as a void* 1018351762cdSJohn McCall // and cast it later. 1019351762cdSJohn McCall QualType selfTy = getContext().VoidPtrTy; 10207fe9cc1dSMike Stump IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); 1021d015328fSMike Stump 1022147d021bSJohn McCall ImplicitParamDecl selfDecl(const_cast<BlockDecl*>(blockDecl), 1023351762cdSJohn McCall SourceLocation(), II, selfTy); 1024a738c25fSJohn McCall args.push_back(&selfDecl); 10257fe9cc1dSMike Stump 1026351762cdSJohn McCall // Now add the rest of the parameters. 1027351762cdSJohn McCall for (BlockDecl::param_const_iterator i = blockDecl->param_begin(), 1028351762cdSJohn McCall e = blockDecl->param_end(); i != e; ++i) 1029a738c25fSJohn McCall args.push_back(*i); 1030afa3c0a8SFariborz Jahanian 1031351762cdSJohn McCall // Create the function declaration. 1032a729c62bSJohn McCall const FunctionProtoType *fnType = blockInfo.getBlockExpr()->getFunctionType(); 1033351762cdSJohn McCall const CGFunctionInfo &fnInfo = 1034a729c62bSJohn McCall CGM.getTypes().arrangeFunctionDeclaration(fnType->getResultType(), args, 1035a729c62bSJohn McCall fnType->getExtInfo(), 1036a729c62bSJohn McCall fnType->isVariadic()); 103785915250SJohn McCall if (CGM.ReturnTypeUsesSRet(fnInfo)) 103885915250SJohn McCall blockInfo.UsesStret = true; 103985915250SJohn McCall 1040a729c62bSJohn McCall llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo); 104187fe5d56SJohn McCall 1042351762cdSJohn McCall MangleBuffer name; 1043351762cdSJohn McCall CGM.getBlockMangledName(GD, name, blockDecl); 1044351762cdSJohn McCall llvm::Function *fn = 1045351762cdSJohn McCall llvm::Function::Create(fnLLVMType, llvm::GlobalValue::InternalLinkage, 1046351762cdSJohn McCall name.getString(), &CGM.getModule()); 1047351762cdSJohn McCall CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo); 10486a60fa24SAnders Carlsson 1049351762cdSJohn McCall // Begin generating the function. 1050a738c25fSJohn McCall StartFunction(blockDecl, fnType->getResultType(), fn, fnInfo, args, 10515f070a51SDevang Patel blockInfo.getBlockExpr()->getBody()->getLocStart()); 1052351762cdSJohn McCall CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl 10536a60fa24SAnders Carlsson 1054147d021bSJohn McCall // Okay. Undo some of what StartFunction did. 1055147d021bSJohn McCall 1056147d021bSJohn McCall // Pull the 'self' reference out of the local decl map. 1057147d021bSJohn McCall llvm::Value *blockAddr = LocalDeclMap[&selfDecl]; 1058147d021bSJohn McCall LocalDeclMap.erase(&selfDecl); 1059351762cdSJohn McCall BlockPointer = Builder.CreateBitCast(blockAddr, 1060351762cdSJohn McCall blockInfo.StructureType->getPointerTo(), 1061351762cdSJohn McCall "block"); 1062017460abSMike Stump 106387fe5d56SJohn McCall // If we have a C++ 'this' reference, go ahead and force it into 106487fe5d56SJohn McCall // existence now. 1065351762cdSJohn McCall if (blockDecl->capturesCXXThis()) { 1066351762cdSJohn McCall llvm::Value *addr = Builder.CreateStructGEP(BlockPointer, 1067351762cdSJohn McCall blockInfo.CXXThisIndex, 1068351762cdSJohn McCall "block.captured-this"); 1069351762cdSJohn McCall CXXThisValue = Builder.CreateLoad(addr, "this"); 107087fe5d56SJohn McCall } 107187fe5d56SJohn McCall 1072351762cdSJohn McCall // LoadObjCSelf() expects there to be an entry for 'self' in LocalDeclMap; 1073351762cdSJohn McCall // appease it. 1074351762cdSJohn McCall if (const ObjCMethodDecl *method 1075351762cdSJohn McCall = dyn_cast_or_null<ObjCMethodDecl>(CurFuncDecl)) { 1076351762cdSJohn McCall const VarDecl *self = method->getSelfDecl(); 1077351762cdSJohn McCall 1078351762cdSJohn McCall // There might not be a capture for 'self', but if there is... 1079351762cdSJohn McCall if (blockInfo.Captures.count(self)) { 1080351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(self); 1081351762cdSJohn McCall llvm::Value *selfAddr = Builder.CreateStructGEP(BlockPointer, 1082351762cdSJohn McCall capture.getIndex(), 1083351762cdSJohn McCall "block.captured-self"); 1084351762cdSJohn McCall LocalDeclMap[self] = selfAddr; 1085351762cdSJohn McCall } 1086351762cdSJohn McCall } 1087351762cdSJohn McCall 1088351762cdSJohn McCall // Also force all the constant captures. 1089351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1090351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1091351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1092351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1093351762cdSJohn McCall if (!capture.isConstant()) continue; 1094351762cdSJohn McCall 1095351762cdSJohn McCall unsigned align = getContext().getDeclAlign(variable).getQuantity(); 1096351762cdSJohn McCall 1097351762cdSJohn McCall llvm::AllocaInst *alloca = 1098351762cdSJohn McCall CreateMemTemp(variable->getType(), "block.captured-const"); 1099351762cdSJohn McCall alloca->setAlignment(align); 1100351762cdSJohn McCall 1101351762cdSJohn McCall Builder.CreateStore(capture.getConstant(), alloca, align); 1102351762cdSJohn McCall 1103351762cdSJohn McCall LocalDeclMap[variable] = alloca; 11049d42f0f1SJohn McCall } 11059d42f0f1SJohn McCall 1106113bee05SJohn McCall // Save a spot to insert the debug information for all the DeclRefExprs. 1107017460abSMike Stump llvm::BasicBlock *entry = Builder.GetInsertBlock(); 1108017460abSMike Stump llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint(); 1109017460abSMike Stump --entry_ptr; 1110017460abSMike Stump 11112495ab08SEli Friedman if (IsLambdaConversionToBlock) 11122495ab08SEli Friedman EmitLambdaBlockInvokeBody(); 11132495ab08SEli Friedman else 1114351762cdSJohn McCall EmitStmt(blockDecl->getBody()); 1115017460abSMike Stump 11167d69911aSMike Stump // Remember where we were... 11177d69911aSMike Stump llvm::BasicBlock *resume = Builder.GetInsertBlock(); 1118017460abSMike Stump 11197d69911aSMike Stump // Go back to the entry. 1120017460abSMike Stump ++entry_ptr; 1121017460abSMike Stump Builder.SetInsertPoint(entry, entry_ptr); 1122017460abSMike Stump 1123113bee05SJohn McCall // Emit debug information for all the DeclRefExprs. 112487fe5d56SJohn McCall // FIXME: also for 'this' 1125351762cdSJohn McCall if (CGDebugInfo *DI = getDebugInfo()) { 1126351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1127351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1128351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 11297cdf9486SEric Christopher DI->EmitLocation(Builder, variable->getLocation()); 1130351762cdSJohn McCall 1131351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1132351762cdSJohn McCall if (capture.isConstant()) { 1133351762cdSJohn McCall DI->EmitDeclareOfAutoVariable(variable, LocalDeclMap[variable], 1134351762cdSJohn McCall Builder); 1135351762cdSJohn McCall continue; 1136351762cdSJohn McCall } 1137351762cdSJohn McCall 1138147d021bSJohn McCall DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer, 1139351762cdSJohn McCall Builder, blockInfo); 11402e722b91SMike Stump } 11412e722b91SMike Stump } 1142351762cdSJohn McCall 11437d69911aSMike Stump // And resume where we left off. 11447d69911aSMike Stump if (resume == 0) 11457d69911aSMike Stump Builder.ClearInsertionPoint(); 11467d69911aSMike Stump else 11477d69911aSMike Stump Builder.SetInsertPoint(resume); 11482e722b91SMike Stump 1149351762cdSJohn McCall FinishFunction(cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc()); 11506a60fa24SAnders Carlsson 1151351762cdSJohn McCall return fn; 11526a60fa24SAnders Carlsson } 11531db7d04bSMike Stump 1154351762cdSJohn McCall /* 1155351762cdSJohn McCall notes.push_back(HelperInfo()); 1156351762cdSJohn McCall HelperInfo ¬e = notes.back(); 1157351762cdSJohn McCall note.index = capture.getIndex(); 1158351762cdSJohn McCall note.RequiresCopying = (ci->hasCopyExpr() || BlockRequiresCopying(type)); 1159351762cdSJohn McCall note.cxxbar_import = ci->getCopyExpr(); 11601db7d04bSMike Stump 1161351762cdSJohn McCall if (ci->isByRef()) { 1162351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_BYREF; 1163351762cdSJohn McCall if (type.isObjCGCWeak()) 1164351762cdSJohn McCall note.flag |= BLOCK_FIELD_IS_WEAK; 1165351762cdSJohn McCall } else if (type->isBlockPointerType()) { 1166351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_BLOCK; 1167351762cdSJohn McCall } else { 1168351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_OBJECT; 11691db7d04bSMike Stump } 1170351762cdSJohn McCall */ 11711db7d04bSMike Stump 117297d01d50SMike Stump 11730c743277SMike Stump 1174351762cdSJohn McCall llvm::Constant * 1175ad7c5c16SJohn McCall CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { 1176351762cdSJohn McCall ASTContext &C = getContext(); 1177351762cdSJohn McCall 1178351762cdSJohn McCall FunctionArgList args; 1179a738c25fSJohn McCall ImplicitParamDecl dstDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1180a738c25fSJohn McCall args.push_back(&dstDecl); 1181a738c25fSJohn McCall ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1182a738c25fSJohn McCall args.push_back(&srcDecl); 11830c743277SMike Stump 11840c743277SMike Stump const CGFunctionInfo &FI = 1185a729c62bSJohn McCall CGM.getTypes().arrangeFunctionDeclaration(C.VoidTy, args, 1186a729c62bSJohn McCall FunctionType::ExtInfo(), 1187a729c62bSJohn McCall /*variadic*/ false); 11880c743277SMike Stump 1189351762cdSJohn McCall // FIXME: it would be nice if these were mergeable with things with 1190351762cdSJohn McCall // identical semantics. 1191a729c62bSJohn McCall llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); 11920c743277SMike Stump 11930c743277SMike Stump llvm::Function *Fn = 11940c743277SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1195d6b28fc6SBenjamin Kramer "__copy_helper_block_", &CGM.getModule()); 11960c743277SMike Stump 11970c743277SMike Stump IdentifierInfo *II 11980c743277SMike Stump = &CGM.getContext().Idents.get("__copy_helper_block_"); 11990c743277SMike Stump 12002a7c2194SDevang Patel // Check if we should generate debug info for this block helper function. 12012a7c2194SDevang Patel if (CGM.getModuleDebugInfo()) 12022a7c2194SDevang Patel DebugInfo = CGM.getModuleDebugInfo(); 12032a7c2194SDevang Patel 1204351762cdSJohn McCall FunctionDecl *FD = FunctionDecl::Create(C, 1205351762cdSJohn McCall C.getTranslationUnitDecl(), 1206dff1930bSAbramo Bagnara SourceLocation(), 1207351762cdSJohn McCall SourceLocation(), II, C.VoidTy, 0, 12088e7d656aSJohn McCall SC_Static, 12098e7d656aSJohn McCall SC_None, 1210c4df4076SDouglas Gregor false, 12110c743277SMike Stump true); 1212a738c25fSJohn McCall StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); 1213aeb0ffd5SMike Stump 12142192fe50SChris Lattner llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); 121567645930SMike Stump 1216a738c25fSJohn McCall llvm::Value *src = GetAddrOfLocalVar(&srcDecl); 1217ad7c5c16SJohn McCall src = Builder.CreateLoad(src); 1218ad7c5c16SJohn McCall src = Builder.CreateBitCast(src, structPtrTy, "block.source"); 121967645930SMike Stump 1220a738c25fSJohn McCall llvm::Value *dst = GetAddrOfLocalVar(&dstDecl); 1221ad7c5c16SJohn McCall dst = Builder.CreateLoad(dst); 1222ad7c5c16SJohn McCall dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest"); 1223aeb0ffd5SMike Stump 1224351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1225aeb0ffd5SMike Stump 1226351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1227351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1228351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1229351762cdSJohn McCall QualType type = variable->getType(); 1230aeb0ffd5SMike Stump 1231351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1232351762cdSJohn McCall if (capture.isConstant()) continue; 1233351762cdSJohn McCall 1234351762cdSJohn McCall const Expr *copyExpr = ci->getCopyExpr(); 123531168b07SJohn McCall BlockFieldFlags flags; 123631168b07SJohn McCall 123731168b07SJohn McCall bool isARCWeakCapture = false; 1238351762cdSJohn McCall 1239351762cdSJohn McCall if (copyExpr) { 1240351762cdSJohn McCall assert(!ci->isByRef()); 1241351762cdSJohn McCall // don't bother computing flags 124231168b07SJohn McCall 1243351762cdSJohn McCall } else if (ci->isByRef()) { 1244351762cdSJohn McCall flags = BLOCK_FIELD_IS_BYREF; 124531168b07SJohn McCall if (type.isObjCGCWeak()) 124631168b07SJohn McCall flags |= BLOCK_FIELD_IS_WEAK; 1247351762cdSJohn McCall 124831168b07SJohn McCall } else if (type->isObjCRetainableType()) { 124931168b07SJohn McCall flags = BLOCK_FIELD_IS_OBJECT; 125031168b07SJohn McCall if (type->isBlockPointerType()) 125131168b07SJohn McCall flags = BLOCK_FIELD_IS_BLOCK; 125231168b07SJohn McCall 125331168b07SJohn McCall // Special rules for ARC captures: 1254*bbafb8a7SDavid Blaikie if (getLangOpts().ObjCAutoRefCount) { 125531168b07SJohn McCall Qualifiers qs = type.getQualifiers(); 125631168b07SJohn McCall 125731168b07SJohn McCall // Don't generate special copy logic for a captured object 125831168b07SJohn McCall // unless it's __strong or __weak. 125931168b07SJohn McCall if (!qs.hasStrongOrWeakObjCLifetime()) 126031168b07SJohn McCall continue; 126131168b07SJohn McCall 126231168b07SJohn McCall // Support __weak direct captures. 126331168b07SJohn McCall if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) 126431168b07SJohn McCall isARCWeakCapture = true; 126531168b07SJohn McCall } 126631168b07SJohn McCall } else { 126731168b07SJohn McCall continue; 126831168b07SJohn McCall } 1269351762cdSJohn McCall 1270351762cdSJohn McCall unsigned index = capture.getIndex(); 1271ad7c5c16SJohn McCall llvm::Value *srcField = Builder.CreateStructGEP(src, index); 1272ad7c5c16SJohn McCall llvm::Value *dstField = Builder.CreateStructGEP(dst, index); 1273351762cdSJohn McCall 1274351762cdSJohn McCall // If there's an explicit copy expression, we do that. 1275351762cdSJohn McCall if (copyExpr) { 1276ad7c5c16SJohn McCall EmitSynthesizedCXXCopyCtor(dstField, srcField, copyExpr); 127731168b07SJohn McCall } else if (isARCWeakCapture) { 127831168b07SJohn McCall EmitARCCopyWeak(dstField, srcField); 1279351762cdSJohn McCall } else { 1280351762cdSJohn McCall llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); 1281e3dc1707SJohn McCall srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy); 1282e3dc1707SJohn McCall llvm::Value *dstAddr = Builder.CreateBitCast(dstField, VoidPtrTy); 1283351762cdSJohn McCall Builder.CreateCall3(CGM.getBlockObjectAssign(), dstAddr, srcValue, 128431168b07SJohn McCall llvm::ConstantInt::get(Int32Ty, flags.getBitMask())); 128567645930SMike Stump } 1286e988bdacSFariborz Jahanian } 1287aeb0ffd5SMike Stump 1288ad7c5c16SJohn McCall FinishFunction(); 12890c743277SMike Stump 1290e3dc1707SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); 129197d01d50SMike Stump } 129297d01d50SMike Stump 1293351762cdSJohn McCall llvm::Constant * 1294ad7c5c16SJohn McCall CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { 1295351762cdSJohn McCall ASTContext &C = getContext(); 12960c743277SMike Stump 1297351762cdSJohn McCall FunctionArgList args; 1298a738c25fSJohn McCall ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1299a738c25fSJohn McCall args.push_back(&srcDecl); 13000c743277SMike Stump 13010c743277SMike Stump const CGFunctionInfo &FI = 1302a729c62bSJohn McCall CGM.getTypes().arrangeFunctionDeclaration(C.VoidTy, args, 1303a729c62bSJohn McCall FunctionType::ExtInfo(), 1304a729c62bSJohn McCall /*variadic*/ false); 13050c743277SMike Stump 1306cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1307cbc2bcafSMike Stump // internal linkage. 1308a729c62bSJohn McCall llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); 13090c743277SMike Stump 13100c743277SMike Stump llvm::Function *Fn = 13110c743277SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1312d6b28fc6SBenjamin Kramer "__destroy_helper_block_", &CGM.getModule()); 13130c743277SMike Stump 13142a7c2194SDevang Patel // Check if we should generate debug info for this block destroy function. 13152a7c2194SDevang Patel if (CGM.getModuleDebugInfo()) 13162a7c2194SDevang Patel DebugInfo = CGM.getModuleDebugInfo(); 13172a7c2194SDevang Patel 13180c743277SMike Stump IdentifierInfo *II 13190c743277SMike Stump = &CGM.getContext().Idents.get("__destroy_helper_block_"); 13200c743277SMike Stump 1321351762cdSJohn McCall FunctionDecl *FD = FunctionDecl::Create(C, C.getTranslationUnitDecl(), 1322dff1930bSAbramo Bagnara SourceLocation(), 1323351762cdSJohn McCall SourceLocation(), II, C.VoidTy, 0, 13248e7d656aSJohn McCall SC_Static, 13258e7d656aSJohn McCall SC_None, 1326c4df4076SDouglas Gregor false, true); 1327a738c25fSJohn McCall StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); 13286f7d9f87SMike Stump 13292192fe50SChris Lattner llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); 133067645930SMike Stump 1331a738c25fSJohn McCall llvm::Value *src = GetAddrOfLocalVar(&srcDecl); 1332ad7c5c16SJohn McCall src = Builder.CreateLoad(src); 1333ad7c5c16SJohn McCall src = Builder.CreateBitCast(src, structPtrTy, "block"); 13346f7d9f87SMike Stump 1335351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1336351762cdSJohn McCall 1337ad7c5c16SJohn McCall CodeGenFunction::RunCleanupsScope cleanups(*this); 1338351762cdSJohn McCall 1339351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1340351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1341351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1342351762cdSJohn McCall QualType type = variable->getType(); 1343351762cdSJohn McCall 1344351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1345351762cdSJohn McCall if (capture.isConstant()) continue; 1346351762cdSJohn McCall 1347ad7c5c16SJohn McCall BlockFieldFlags flags; 1348351762cdSJohn McCall const CXXDestructorDecl *dtor = 0; 1349351762cdSJohn McCall 135031168b07SJohn McCall bool isARCWeakCapture = false; 135131168b07SJohn McCall 1352351762cdSJohn McCall if (ci->isByRef()) { 1353351762cdSJohn McCall flags = BLOCK_FIELD_IS_BYREF; 135431168b07SJohn McCall if (type.isObjCGCWeak()) 135531168b07SJohn McCall flags |= BLOCK_FIELD_IS_WEAK; 135631168b07SJohn McCall } else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) { 135731168b07SJohn McCall if (record->hasTrivialDestructor()) 135831168b07SJohn McCall continue; 1359351762cdSJohn McCall dtor = record->getDestructor(); 136031168b07SJohn McCall } else if (type->isObjCRetainableType()) { 136131168b07SJohn McCall flags = BLOCK_FIELD_IS_OBJECT; 136231168b07SJohn McCall if (type->isBlockPointerType()) 136331168b07SJohn McCall flags = BLOCK_FIELD_IS_BLOCK; 1364351762cdSJohn McCall 136531168b07SJohn McCall // Special rules for ARC captures. 1366*bbafb8a7SDavid Blaikie if (getLangOpts().ObjCAutoRefCount) { 136731168b07SJohn McCall Qualifiers qs = type.getQualifiers(); 136831168b07SJohn McCall 136931168b07SJohn McCall // Don't generate special dispose logic for a captured object 137031168b07SJohn McCall // unless it's __strong or __weak. 137131168b07SJohn McCall if (!qs.hasStrongOrWeakObjCLifetime()) 137231168b07SJohn McCall continue; 137331168b07SJohn McCall 137431168b07SJohn McCall // Support __weak direct captures. 137531168b07SJohn McCall if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) 137631168b07SJohn McCall isARCWeakCapture = true; 137731168b07SJohn McCall } 137831168b07SJohn McCall } else { 137931168b07SJohn McCall continue; 138031168b07SJohn McCall } 1381351762cdSJohn McCall 1382351762cdSJohn McCall unsigned index = capture.getIndex(); 1383ad7c5c16SJohn McCall llvm::Value *srcField = Builder.CreateStructGEP(src, index); 1384351762cdSJohn McCall 1385351762cdSJohn McCall // If there's an explicit copy expression, we do that. 1386351762cdSJohn McCall if (dtor) { 1387ad7c5c16SJohn McCall PushDestructorCleanup(dtor, srcField); 1388351762cdSJohn McCall 138931168b07SJohn McCall // If this is a __weak capture, emit the release directly. 139031168b07SJohn McCall } else if (isARCWeakCapture) { 139131168b07SJohn McCall EmitARCDestroyWeak(srcField); 139231168b07SJohn McCall 1393351762cdSJohn McCall // Otherwise we call _Block_object_dispose. It wouldn't be too 1394351762cdSJohn McCall // hard to just emit this as a cleanup if we wanted to make sure 1395351762cdSJohn McCall // that things were done in reverse. 1396351762cdSJohn McCall } else { 1397351762cdSJohn McCall llvm::Value *value = Builder.CreateLoad(srcField); 1398e3dc1707SJohn McCall value = Builder.CreateBitCast(value, VoidPtrTy); 1399351762cdSJohn McCall BuildBlockRelease(value, flags); 14006f7d9f87SMike Stump } 14016f7d9f87SMike Stump } 1402351762cdSJohn McCall 1403351762cdSJohn McCall cleanups.ForceCleanup(); 14046f7d9f87SMike Stump 1405ad7c5c16SJohn McCall FinishFunction(); 14060c743277SMike Stump 1407e3dc1707SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); 14080c743277SMike Stump } 14090c743277SMike Stump 1410f9b056b0SJohn McCall namespace { 1411f9b056b0SJohn McCall 1412f9b056b0SJohn McCall /// Emits the copy/dispose helper functions for a __block object of id type. 1413f9b056b0SJohn McCall class ObjectByrefHelpers : public CodeGenModule::ByrefHelpers { 1414f9b056b0SJohn McCall BlockFieldFlags Flags; 1415f9b056b0SJohn McCall 1416f9b056b0SJohn McCall public: 1417f9b056b0SJohn McCall ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags) 1418f9b056b0SJohn McCall : ByrefHelpers(alignment), Flags(flags) {} 1419f9b056b0SJohn McCall 14207c623641SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 14217c623641SJohn McCall llvm::Value *srcField) { 1422f9b056b0SJohn McCall destField = CGF.Builder.CreateBitCast(destField, CGF.VoidPtrTy); 1423f9b056b0SJohn McCall 1424f9b056b0SJohn McCall srcField = CGF.Builder.CreateBitCast(srcField, CGF.VoidPtrPtrTy); 1425f9b056b0SJohn McCall llvm::Value *srcValue = CGF.Builder.CreateLoad(srcField); 1426f9b056b0SJohn McCall 1427f9b056b0SJohn McCall unsigned flags = (Flags | BLOCK_BYREF_CALLER).getBitMask(); 1428f9b056b0SJohn McCall 1429f9b056b0SJohn McCall llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); 1430f9b056b0SJohn McCall llvm::Value *fn = CGF.CGM.getBlockObjectAssign(); 1431f9b056b0SJohn McCall CGF.Builder.CreateCall3(fn, destField, srcValue, flagsVal); 1432f9b056b0SJohn McCall } 1433f9b056b0SJohn McCall 1434f9b056b0SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1435f9b056b0SJohn McCall field = CGF.Builder.CreateBitCast(field, CGF.Int8PtrTy->getPointerTo(0)); 1436f9b056b0SJohn McCall llvm::Value *value = CGF.Builder.CreateLoad(field); 1437f9b056b0SJohn McCall 1438f9b056b0SJohn McCall CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER); 1439f9b056b0SJohn McCall } 1440f9b056b0SJohn McCall 1441f9b056b0SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 1442f9b056b0SJohn McCall id.AddInteger(Flags.getBitMask()); 1443f9b056b0SJohn McCall } 1444f9b056b0SJohn McCall }; 1445f9b056b0SJohn McCall 144631168b07SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __weak variable. 144731168b07SJohn McCall class ARCWeakByrefHelpers : public CodeGenModule::ByrefHelpers { 144831168b07SJohn McCall public: 144931168b07SJohn McCall ARCWeakByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {} 145031168b07SJohn McCall 145131168b07SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 145231168b07SJohn McCall llvm::Value *srcField) { 145331168b07SJohn McCall CGF.EmitARCMoveWeak(destField, srcField); 145431168b07SJohn McCall } 145531168b07SJohn McCall 145631168b07SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 145731168b07SJohn McCall CGF.EmitARCDestroyWeak(field); 145831168b07SJohn McCall } 145931168b07SJohn McCall 146031168b07SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 146131168b07SJohn McCall // 0 is distinguishable from all pointers and byref flags 146231168b07SJohn McCall id.AddInteger(0); 146331168b07SJohn McCall } 146431168b07SJohn McCall }; 146531168b07SJohn McCall 146631168b07SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __strong variable 146731168b07SJohn McCall /// that's not of block-pointer type. 146831168b07SJohn McCall class ARCStrongByrefHelpers : public CodeGenModule::ByrefHelpers { 146931168b07SJohn McCall public: 147031168b07SJohn McCall ARCStrongByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {} 147131168b07SJohn McCall 147231168b07SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 147331168b07SJohn McCall llvm::Value *srcField) { 147431168b07SJohn McCall // Do a "move" by copying the value and then zeroing out the old 147531168b07SJohn McCall // variable. 147631168b07SJohn McCall 14773a237aa3SJohn McCall llvm::LoadInst *value = CGF.Builder.CreateLoad(srcField); 14783a237aa3SJohn McCall value->setAlignment(Alignment.getQuantity()); 14793a237aa3SJohn McCall 148031168b07SJohn McCall llvm::Value *null = 148131168b07SJohn McCall llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType())); 14823a237aa3SJohn McCall 14833a237aa3SJohn McCall llvm::StoreInst *store = CGF.Builder.CreateStore(value, destField); 14843a237aa3SJohn McCall store->setAlignment(Alignment.getQuantity()); 14853a237aa3SJohn McCall 14863a237aa3SJohn McCall store = CGF.Builder.CreateStore(null, srcField); 14873a237aa3SJohn McCall store->setAlignment(Alignment.getQuantity()); 148831168b07SJohn McCall } 148931168b07SJohn McCall 149031168b07SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 14913a237aa3SJohn McCall llvm::LoadInst *value = CGF.Builder.CreateLoad(field); 14923a237aa3SJohn McCall value->setAlignment(Alignment.getQuantity()); 14933a237aa3SJohn McCall 149431168b07SJohn McCall CGF.EmitARCRelease(value, /*precise*/ false); 149531168b07SJohn McCall } 149631168b07SJohn McCall 149731168b07SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 149831168b07SJohn McCall // 1 is distinguishable from all pointers and byref flags 149931168b07SJohn McCall id.AddInteger(1); 150031168b07SJohn McCall } 150131168b07SJohn McCall }; 150231168b07SJohn McCall 15033a237aa3SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __strong 15043a237aa3SJohn McCall /// variable that's of block-pointer type. 15053a237aa3SJohn McCall class ARCStrongBlockByrefHelpers : public CodeGenModule::ByrefHelpers { 15063a237aa3SJohn McCall public: 15073a237aa3SJohn McCall ARCStrongBlockByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {} 15083a237aa3SJohn McCall 15093a237aa3SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 15103a237aa3SJohn McCall llvm::Value *srcField) { 15113a237aa3SJohn McCall // Do the copy with objc_retainBlock; that's all that 15123a237aa3SJohn McCall // _Block_object_assign would do anyway, and we'd have to pass the 15133a237aa3SJohn McCall // right arguments to make sure it doesn't get no-op'ed. 15143a237aa3SJohn McCall llvm::LoadInst *oldValue = CGF.Builder.CreateLoad(srcField); 15153a237aa3SJohn McCall oldValue->setAlignment(Alignment.getQuantity()); 15163a237aa3SJohn McCall 15173a237aa3SJohn McCall llvm::Value *copy = CGF.EmitARCRetainBlock(oldValue, /*mandatory*/ true); 15183a237aa3SJohn McCall 15193a237aa3SJohn McCall llvm::StoreInst *store = CGF.Builder.CreateStore(copy, destField); 15203a237aa3SJohn McCall store->setAlignment(Alignment.getQuantity()); 15213a237aa3SJohn McCall } 15223a237aa3SJohn McCall 15233a237aa3SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 15243a237aa3SJohn McCall llvm::LoadInst *value = CGF.Builder.CreateLoad(field); 15253a237aa3SJohn McCall value->setAlignment(Alignment.getQuantity()); 15263a237aa3SJohn McCall 15273a237aa3SJohn McCall CGF.EmitARCRelease(value, /*precise*/ false); 15283a237aa3SJohn McCall } 15293a237aa3SJohn McCall 15303a237aa3SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 15313a237aa3SJohn McCall // 2 is distinguishable from all pointers and byref flags 15323a237aa3SJohn McCall id.AddInteger(2); 15333a237aa3SJohn McCall } 15343a237aa3SJohn McCall }; 15353a237aa3SJohn McCall 1536f9b056b0SJohn McCall /// Emits the copy/dispose helpers for a __block variable with a 1537f9b056b0SJohn McCall /// nontrivial copy constructor or destructor. 1538f9b056b0SJohn McCall class CXXByrefHelpers : public CodeGenModule::ByrefHelpers { 1539f9b056b0SJohn McCall QualType VarType; 1540f9b056b0SJohn McCall const Expr *CopyExpr; 1541f9b056b0SJohn McCall 1542f9b056b0SJohn McCall public: 1543f9b056b0SJohn McCall CXXByrefHelpers(CharUnits alignment, QualType type, 1544f9b056b0SJohn McCall const Expr *copyExpr) 1545f9b056b0SJohn McCall : ByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {} 1546f9b056b0SJohn McCall 1547f9b056b0SJohn McCall bool needsCopy() const { return CopyExpr != 0; } 1548f9b056b0SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 1549f9b056b0SJohn McCall llvm::Value *srcField) { 1550f9b056b0SJohn McCall if (!CopyExpr) return; 1551f9b056b0SJohn McCall CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr); 1552f9b056b0SJohn McCall } 1553f9b056b0SJohn McCall 1554f9b056b0SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1555f9b056b0SJohn McCall EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin(); 1556f9b056b0SJohn McCall CGF.PushDestructorCleanup(VarType, field); 1557f9b056b0SJohn McCall CGF.PopCleanupBlocks(cleanupDepth); 1558f9b056b0SJohn McCall } 1559f9b056b0SJohn McCall 1560f9b056b0SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 1561f9b056b0SJohn McCall id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr()); 1562f9b056b0SJohn McCall } 1563f9b056b0SJohn McCall }; 1564f9b056b0SJohn McCall } // end anonymous namespace 1565f9b056b0SJohn McCall 1566f9b056b0SJohn McCall static llvm::Constant * 1567f9b056b0SJohn McCall generateByrefCopyHelper(CodeGenFunction &CGF, 15682192fe50SChris Lattner llvm::StructType &byrefType, 1569f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &byrefInfo) { 1570f9b056b0SJohn McCall ASTContext &Context = CGF.getContext(); 1571f9b056b0SJohn McCall 1572f9b056b0SJohn McCall QualType R = Context.VoidTy; 1573ee2a5ee5SMike Stump 1574a738c25fSJohn McCall FunctionArgList args; 1575f9b056b0SJohn McCall ImplicitParamDecl dst(0, SourceLocation(), 0, Context.VoidPtrTy); 1576a738c25fSJohn McCall args.push_back(&dst); 1577f89230d9SMike Stump 1578f9b056b0SJohn McCall ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); 1579a738c25fSJohn McCall args.push_back(&src); 1580ee2a5ee5SMike Stump 1581ee2a5ee5SMike Stump const CGFunctionInfo &FI = 1582a729c62bSJohn McCall CGF.CGM.getTypes().arrangeFunctionDeclaration(R, args, 1583a729c62bSJohn McCall FunctionType::ExtInfo(), 1584a729c62bSJohn McCall /*variadic*/ false); 1585ee2a5ee5SMike Stump 1586f9b056b0SJohn McCall CodeGenTypes &Types = CGF.CGM.getTypes(); 1587a729c62bSJohn McCall llvm::FunctionType *LTy = Types.GetFunctionType(FI); 1588ee2a5ee5SMike Stump 1589cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1590cbc2bcafSMike Stump // internal linkage. 1591ee2a5ee5SMike Stump llvm::Function *Fn = 1592ee2a5ee5SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1593f9b056b0SJohn McCall "__Block_byref_object_copy_", &CGF.CGM.getModule()); 1594ee2a5ee5SMike Stump 1595ee2a5ee5SMike Stump IdentifierInfo *II 1596f9b056b0SJohn McCall = &Context.Idents.get("__Block_byref_object_copy_"); 1597ee2a5ee5SMike Stump 1598f9b056b0SJohn McCall FunctionDecl *FD = FunctionDecl::Create(Context, 1599f9b056b0SJohn McCall Context.getTranslationUnitDecl(), 1600dff1930bSAbramo Bagnara SourceLocation(), 160160ed5604SArgyrios Kyrtzidis SourceLocation(), II, R, 0, 16028e7d656aSJohn McCall SC_Static, 16038e7d656aSJohn McCall SC_None, 1604c4df4076SDouglas Gregor false, true); 160531168b07SJohn McCall 1606f9b056b0SJohn McCall CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); 1607f9b056b0SJohn McCall 1608f9b056b0SJohn McCall if (byrefInfo.needsCopy()) { 16092192fe50SChris Lattner llvm::Type *byrefPtrType = byrefType.getPointerTo(0); 1610f89230d9SMike Stump 1611f89230d9SMike Stump // dst->x 1612f9b056b0SJohn McCall llvm::Value *destField = CGF.GetAddrOfLocalVar(&dst); 1613f9b056b0SJohn McCall destField = CGF.Builder.CreateLoad(destField); 1614f9b056b0SJohn McCall destField = CGF.Builder.CreateBitCast(destField, byrefPtrType); 1615f9b056b0SJohn McCall destField = CGF.Builder.CreateStructGEP(destField, 6, "x"); 1616f89230d9SMike Stump 1617f89230d9SMike Stump // src->x 1618f9b056b0SJohn McCall llvm::Value *srcField = CGF.GetAddrOfLocalVar(&src); 1619f9b056b0SJohn McCall srcField = CGF.Builder.CreateLoad(srcField); 1620f9b056b0SJohn McCall srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType); 1621f9b056b0SJohn McCall srcField = CGF.Builder.CreateStructGEP(srcField, 6, "x"); 162250198098SFariborz Jahanian 1623f9b056b0SJohn McCall byrefInfo.emitCopy(CGF, destField, srcField); 162450198098SFariborz Jahanian } 1625f89230d9SMike Stump 1626f9b056b0SJohn McCall CGF.FinishFunction(); 1627ee2a5ee5SMike Stump 1628f9b056b0SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); 1629ee2a5ee5SMike Stump } 1630ee2a5ee5SMike Stump 1631f9b056b0SJohn McCall /// Build the copy helper for a __block variable. 1632f9b056b0SJohn McCall static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM, 16332192fe50SChris Lattner llvm::StructType &byrefType, 1634f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &info) { 1635f9b056b0SJohn McCall CodeGenFunction CGF(CGM); 1636f9b056b0SJohn McCall return generateByrefCopyHelper(CGF, byrefType, info); 1637f9b056b0SJohn McCall } 1638f9b056b0SJohn McCall 1639f9b056b0SJohn McCall /// Generate code for a __block variable's dispose helper. 1640f9b056b0SJohn McCall static llvm::Constant * 1641f9b056b0SJohn McCall generateByrefDisposeHelper(CodeGenFunction &CGF, 16422192fe50SChris Lattner llvm::StructType &byrefType, 1643f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &byrefInfo) { 1644f9b056b0SJohn McCall ASTContext &Context = CGF.getContext(); 1645f9b056b0SJohn McCall QualType R = Context.VoidTy; 1646ee2a5ee5SMike Stump 1647a738c25fSJohn McCall FunctionArgList args; 1648f9b056b0SJohn McCall ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); 1649a738c25fSJohn McCall args.push_back(&src); 1650ee2a5ee5SMike Stump 1651ee2a5ee5SMike Stump const CGFunctionInfo &FI = 1652a729c62bSJohn McCall CGF.CGM.getTypes().arrangeFunctionDeclaration(R, args, 1653a729c62bSJohn McCall FunctionType::ExtInfo(), 1654a729c62bSJohn McCall /*variadic*/ false); 1655ee2a5ee5SMike Stump 1656f9b056b0SJohn McCall CodeGenTypes &Types = CGF.CGM.getTypes(); 1657a729c62bSJohn McCall llvm::FunctionType *LTy = Types.GetFunctionType(FI); 1658ee2a5ee5SMike Stump 1659cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1660cbc2bcafSMike Stump // internal linkage. 1661ee2a5ee5SMike Stump llvm::Function *Fn = 1662ee2a5ee5SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 166350198098SFariborz Jahanian "__Block_byref_object_dispose_", 1664f9b056b0SJohn McCall &CGF.CGM.getModule()); 1665ee2a5ee5SMike Stump 1666ee2a5ee5SMike Stump IdentifierInfo *II 1667f9b056b0SJohn McCall = &Context.Idents.get("__Block_byref_object_dispose_"); 1668ee2a5ee5SMike Stump 1669f9b056b0SJohn McCall FunctionDecl *FD = FunctionDecl::Create(Context, 1670f9b056b0SJohn McCall Context.getTranslationUnitDecl(), 1671dff1930bSAbramo Bagnara SourceLocation(), 167260ed5604SArgyrios Kyrtzidis SourceLocation(), II, R, 0, 16738e7d656aSJohn McCall SC_Static, 16748e7d656aSJohn McCall SC_None, 1675c4df4076SDouglas Gregor false, true); 1676f9b056b0SJohn McCall CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); 1677fbe25dd1SMike Stump 1678f9b056b0SJohn McCall if (byrefInfo.needsDispose()) { 1679f9b056b0SJohn McCall llvm::Value *V = CGF.GetAddrOfLocalVar(&src); 1680f9b056b0SJohn McCall V = CGF.Builder.CreateLoad(V); 1681f9b056b0SJohn McCall V = CGF.Builder.CreateBitCast(V, byrefType.getPointerTo(0)); 1682f9b056b0SJohn McCall V = CGF.Builder.CreateStructGEP(V, 6, "x"); 1683ad7c5c16SJohn McCall 1684f9b056b0SJohn McCall byrefInfo.emitDispose(CGF, V); 1685f9b056b0SJohn McCall } 1686ad7c5c16SJohn McCall 1687f9b056b0SJohn McCall CGF.FinishFunction(); 1688f9b056b0SJohn McCall 1689f9b056b0SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); 1690f9b056b0SJohn McCall } 1691f9b056b0SJohn McCall 1692f9b056b0SJohn McCall /// Build the dispose helper for a __block variable. 1693f9b056b0SJohn McCall static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM, 16942192fe50SChris Lattner llvm::StructType &byrefType, 1695f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &info) { 1696f9b056b0SJohn McCall CodeGenFunction CGF(CGM); 1697f9b056b0SJohn McCall return generateByrefDisposeHelper(CGF, byrefType, info); 1698f9b056b0SJohn McCall } 1699f9b056b0SJohn McCall 1700f9b056b0SJohn McCall /// 1701f9b056b0SJohn McCall template <class T> static T *buildByrefHelpers(CodeGenModule &CGM, 17022192fe50SChris Lattner llvm::StructType &byrefTy, 1703f9b056b0SJohn McCall T &byrefInfo) { 1704f9b056b0SJohn McCall // Increase the field's alignment to be at least pointer alignment, 1705f9b056b0SJohn McCall // since the layout of the byref struct will guarantee at least that. 1706f9b056b0SJohn McCall byrefInfo.Alignment = std::max(byrefInfo.Alignment, 1707f9b056b0SJohn McCall CharUnits::fromQuantity(CGM.PointerAlignInBytes)); 1708f9b056b0SJohn McCall 1709f9b056b0SJohn McCall llvm::FoldingSetNodeID id; 1710f9b056b0SJohn McCall byrefInfo.Profile(id); 1711f9b056b0SJohn McCall 1712f9b056b0SJohn McCall void *insertPos; 1713f9b056b0SJohn McCall CodeGenModule::ByrefHelpers *node 1714f9b056b0SJohn McCall = CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos); 1715f9b056b0SJohn McCall if (node) return static_cast<T*>(node); 1716f9b056b0SJohn McCall 1717f9b056b0SJohn McCall byrefInfo.CopyHelper = buildByrefCopyHelper(CGM, byrefTy, byrefInfo); 1718f9b056b0SJohn McCall byrefInfo.DisposeHelper = buildByrefDisposeHelper(CGM, byrefTy, byrefInfo); 1719f9b056b0SJohn McCall 1720f9b056b0SJohn McCall T *copy = new (CGM.getContext()) T(byrefInfo); 1721f9b056b0SJohn McCall CGM.ByrefHelpersCache.InsertNode(copy, insertPos); 1722f9b056b0SJohn McCall return copy; 1723f9b056b0SJohn McCall } 1724f9b056b0SJohn McCall 1725f9b056b0SJohn McCall CodeGenModule::ByrefHelpers * 17262192fe50SChris Lattner CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType, 1727f9b056b0SJohn McCall const AutoVarEmission &emission) { 1728f9b056b0SJohn McCall const VarDecl &var = *emission.Variable; 1729f9b056b0SJohn McCall QualType type = var.getType(); 1730f9b056b0SJohn McCall 1731f9b056b0SJohn McCall if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) { 1732f9b056b0SJohn McCall const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var); 1733f9b056b0SJohn McCall if (!copyExpr && record->hasTrivialDestructor()) return 0; 1734f9b056b0SJohn McCall 1735f9b056b0SJohn McCall CXXByrefHelpers byrefInfo(emission.Alignment, type, copyExpr); 1736f9b056b0SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 1737f9b056b0SJohn McCall } 1738f9b056b0SJohn McCall 173931168b07SJohn McCall // Otherwise, if we don't have a retainable type, there's nothing to do. 174031168b07SJohn McCall // that the runtime does extra copies. 174131168b07SJohn McCall if (!type->isObjCRetainableType()) return 0; 174231168b07SJohn McCall 174331168b07SJohn McCall Qualifiers qs = type.getQualifiers(); 174431168b07SJohn McCall 174531168b07SJohn McCall // If we have lifetime, that dominates. 174631168b07SJohn McCall if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) { 1747*bbafb8a7SDavid Blaikie assert(getLangOpts().ObjCAutoRefCount); 174831168b07SJohn McCall 174931168b07SJohn McCall switch (lifetime) { 175031168b07SJohn McCall case Qualifiers::OCL_None: llvm_unreachable("impossible"); 175131168b07SJohn McCall 175231168b07SJohn McCall // These are just bits as far as the runtime is concerned. 175331168b07SJohn McCall case Qualifiers::OCL_ExplicitNone: 175431168b07SJohn McCall case Qualifiers::OCL_Autoreleasing: 175531168b07SJohn McCall return 0; 175631168b07SJohn McCall 175731168b07SJohn McCall // Tell the runtime that this is ARC __weak, called by the 175831168b07SJohn McCall // byref routines. 175931168b07SJohn McCall case Qualifiers::OCL_Weak: { 176031168b07SJohn McCall ARCWeakByrefHelpers byrefInfo(emission.Alignment); 176131168b07SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 176231168b07SJohn McCall } 176331168b07SJohn McCall 176431168b07SJohn McCall // ARC __strong __block variables need to be retained. 176531168b07SJohn McCall case Qualifiers::OCL_Strong: 17663a237aa3SJohn McCall // Block pointers need to be copied, and there's no direct 17673a237aa3SJohn McCall // transfer possible. 176831168b07SJohn McCall if (type->isBlockPointerType()) { 17693a237aa3SJohn McCall ARCStrongBlockByrefHelpers byrefInfo(emission.Alignment); 177031168b07SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 177131168b07SJohn McCall 177231168b07SJohn McCall // Otherwise, we transfer ownership of the retain from the stack 177331168b07SJohn McCall // to the heap. 177431168b07SJohn McCall } else { 177531168b07SJohn McCall ARCStrongByrefHelpers byrefInfo(emission.Alignment); 177631168b07SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 177731168b07SJohn McCall } 177831168b07SJohn McCall } 177931168b07SJohn McCall llvm_unreachable("fell out of lifetime switch!"); 178031168b07SJohn McCall } 178131168b07SJohn McCall 1782f9b056b0SJohn McCall BlockFieldFlags flags; 1783f9b056b0SJohn McCall if (type->isBlockPointerType()) { 1784f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_BLOCK; 1785f9b056b0SJohn McCall } else if (CGM.getContext().isObjCNSObjectType(type) || 1786f9b056b0SJohn McCall type->isObjCObjectPointerType()) { 1787f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_OBJECT; 1788ad7c5c16SJohn McCall } else { 1789f9b056b0SJohn McCall return 0; 1790ee2a5ee5SMike Stump } 1791ee2a5ee5SMike Stump 1792f9b056b0SJohn McCall if (type.isObjCGCWeak()) 1793f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_WEAK; 1794ad7c5c16SJohn McCall 1795f9b056b0SJohn McCall ObjectByrefHelpers byrefInfo(emission.Alignment, flags); 1796f9b056b0SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 1797ee2a5ee5SMike Stump } 1798ee2a5ee5SMike Stump 179973064870SJohn McCall unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const { 180073064870SJohn McCall assert(ByRefValueInfo.count(VD) && "Did not find value!"); 180173064870SJohn McCall 180273064870SJohn McCall return ByRefValueInfo.find(VD)->second.second; 180373064870SJohn McCall } 180473064870SJohn McCall 180573064870SJohn McCall llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr, 180673064870SJohn McCall const VarDecl *V) { 180773064870SJohn McCall llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding"); 180873064870SJohn McCall Loc = Builder.CreateLoad(Loc); 180973064870SJohn McCall Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V), 181073064870SJohn McCall V->getNameAsString()); 181173064870SJohn McCall return Loc; 181273064870SJohn McCall } 181373064870SJohn McCall 181473064870SJohn McCall /// BuildByRefType - This routine changes a __block variable declared as T x 181573064870SJohn McCall /// into: 181673064870SJohn McCall /// 181773064870SJohn McCall /// struct { 181873064870SJohn McCall /// void *__isa; 181973064870SJohn McCall /// void *__forwarding; 182073064870SJohn McCall /// int32_t __flags; 182173064870SJohn McCall /// int32_t __size; 182273064870SJohn McCall /// void *__copy_helper; // only if needed 182373064870SJohn McCall /// void *__destroy_helper; // only if needed 182473064870SJohn McCall /// char padding[X]; // only if needed 182573064870SJohn McCall /// T x; 182673064870SJohn McCall /// } x 182773064870SJohn McCall /// 18282192fe50SChris Lattner llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) { 18292192fe50SChris Lattner std::pair<llvm::Type *, unsigned> &Info = ByRefValueInfo[D]; 183073064870SJohn McCall if (Info.first) 183173064870SJohn McCall return Info.first; 183273064870SJohn McCall 183373064870SJohn McCall QualType Ty = D->getType(); 183473064870SJohn McCall 18350e62c1ccSChris Lattner SmallVector<llvm::Type *, 8> types; 183673064870SJohn McCall 1837a5f58b05SChris Lattner llvm::StructType *ByRefType = 18385ec04a51SChris Lattner llvm::StructType::create(getLLVMContext(), 1839a5f58b05SChris Lattner "struct.__block_byref_" + D->getNameAsString()); 184073064870SJohn McCall 184173064870SJohn McCall // void *__isa; 18429dc0db21SJohn McCall types.push_back(Int8PtrTy); 184373064870SJohn McCall 184473064870SJohn McCall // void *__forwarding; 1845a5f58b05SChris Lattner types.push_back(llvm::PointerType::getUnqual(ByRefType)); 184673064870SJohn McCall 184773064870SJohn McCall // int32_t __flags; 18489dc0db21SJohn McCall types.push_back(Int32Ty); 184973064870SJohn McCall 185073064870SJohn McCall // int32_t __size; 18519dc0db21SJohn McCall types.push_back(Int32Ty); 185273064870SJohn McCall 185373064870SJohn McCall bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty); 185473064870SJohn McCall if (HasCopyAndDispose) { 185573064870SJohn McCall /// void *__copy_helper; 18569dc0db21SJohn McCall types.push_back(Int8PtrTy); 185773064870SJohn McCall 185873064870SJohn McCall /// void *__destroy_helper; 18599dc0db21SJohn McCall types.push_back(Int8PtrTy); 186073064870SJohn McCall } 186173064870SJohn McCall 186273064870SJohn McCall bool Packed = false; 186373064870SJohn McCall CharUnits Align = getContext().getDeclAlign(D); 186473064870SJohn McCall if (Align > getContext().toCharUnitsFromBits(Target.getPointerAlign(0))) { 186573064870SJohn McCall // We have to insert padding. 186673064870SJohn McCall 186773064870SJohn McCall // The struct above has 2 32-bit integers. 186873064870SJohn McCall unsigned CurrentOffsetInBytes = 4 * 2; 186973064870SJohn McCall 187073064870SJohn McCall // And either 2 or 4 pointers. 187173064870SJohn McCall CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) * 187273064870SJohn McCall CGM.getTargetData().getTypeAllocSize(Int8PtrTy); 187373064870SJohn McCall 187473064870SJohn McCall // Align the offset. 187573064870SJohn McCall unsigned AlignedOffsetInBytes = 187673064870SJohn McCall llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity()); 187773064870SJohn McCall 187873064870SJohn McCall unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes; 187973064870SJohn McCall if (NumPaddingBytes > 0) { 1880ece0409aSChris Lattner llvm::Type *Ty = Int8Ty; 188173064870SJohn McCall // FIXME: We need a sema error for alignment larger than the minimum of 18829dc0db21SJohn McCall // the maximal stack alignment and the alignment of malloc on the system. 188373064870SJohn McCall if (NumPaddingBytes > 1) 188473064870SJohn McCall Ty = llvm::ArrayType::get(Ty, NumPaddingBytes); 188573064870SJohn McCall 18869dc0db21SJohn McCall types.push_back(Ty); 188773064870SJohn McCall 188873064870SJohn McCall // We want a packed struct. 188973064870SJohn McCall Packed = true; 189073064870SJohn McCall } 189173064870SJohn McCall } 189273064870SJohn McCall 189373064870SJohn McCall // T x; 18949dc0db21SJohn McCall types.push_back(ConvertTypeForMem(Ty)); 189573064870SJohn McCall 1896a5f58b05SChris Lattner ByRefType->setBody(types, Packed); 189773064870SJohn McCall 1898a5f58b05SChris Lattner Info.first = ByRefType; 189973064870SJohn McCall 19009dc0db21SJohn McCall Info.second = types.size() - 1; 190173064870SJohn McCall 190273064870SJohn McCall return Info.first; 190373064870SJohn McCall } 190473064870SJohn McCall 190573064870SJohn McCall /// Initialize the structural components of a __block variable, i.e. 190673064870SJohn McCall /// everything but the actual object. 190773064870SJohn McCall void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { 1908f9b056b0SJohn McCall // Find the address of the local. 1909f9b056b0SJohn McCall llvm::Value *addr = emission.Address; 191073064870SJohn McCall 1911f9b056b0SJohn McCall // That's an alloca of the byref structure type. 19122192fe50SChris Lattner llvm::StructType *byrefType = cast<llvm::StructType>( 1913f9b056b0SJohn McCall cast<llvm::PointerType>(addr->getType())->getElementType()); 1914f9b056b0SJohn McCall 1915f9b056b0SJohn McCall // Build the byref helpers if necessary. This is null if we don't need any. 1916f9b056b0SJohn McCall CodeGenModule::ByrefHelpers *helpers = 1917f9b056b0SJohn McCall buildByrefHelpers(*byrefType, emission); 191873064870SJohn McCall 191973064870SJohn McCall const VarDecl &D = *emission.Variable; 192073064870SJohn McCall QualType type = D.getType(); 192173064870SJohn McCall 1922f9b056b0SJohn McCall llvm::Value *V; 192373064870SJohn McCall 192473064870SJohn McCall // Initialize the 'isa', which is just 0 or 1. 192573064870SJohn McCall int isa = 0; 1926f9b056b0SJohn McCall if (type.isObjCGCWeak()) 192773064870SJohn McCall isa = 1; 192873064870SJohn McCall V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa"); 192973064870SJohn McCall Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa")); 193073064870SJohn McCall 193173064870SJohn McCall // Store the address of the variable into its own forwarding pointer. 193273064870SJohn McCall Builder.CreateStore(addr, 193373064870SJohn McCall Builder.CreateStructGEP(addr, 1, "byref.forwarding")); 193473064870SJohn McCall 193573064870SJohn McCall // Blocks ABI: 193673064870SJohn McCall // c) the flags field is set to either 0 if no helper functions are 193773064870SJohn McCall // needed or BLOCK_HAS_COPY_DISPOSE if they are, 193873064870SJohn McCall BlockFlags flags; 1939f9b056b0SJohn McCall if (helpers) flags |= BLOCK_HAS_COPY_DISPOSE; 194073064870SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()), 194173064870SJohn McCall Builder.CreateStructGEP(addr, 2, "byref.flags")); 194273064870SJohn McCall 1943f9b056b0SJohn McCall CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType); 1944f9b056b0SJohn McCall V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity()); 194573064870SJohn McCall Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size")); 194673064870SJohn McCall 1947f9b056b0SJohn McCall if (helpers) { 194873064870SJohn McCall llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4); 1949f9b056b0SJohn McCall Builder.CreateStore(helpers->CopyHelper, copy_helper); 195073064870SJohn McCall 195173064870SJohn McCall llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5); 1952f9b056b0SJohn McCall Builder.CreateStore(helpers->DisposeHelper, destroy_helper); 195373064870SJohn McCall } 195473064870SJohn McCall } 195573064870SJohn McCall 1956ad7c5c16SJohn McCall void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) { 1957900546d2SDaniel Dunbar llvm::Value *F = CGM.getBlockObjectDispose(); 1958fbe25dd1SMike Stump llvm::Value *N; 1959ad7c5c16SJohn McCall V = Builder.CreateBitCast(V, Int8PtrTy); 1960ad7c5c16SJohn McCall N = llvm::ConstantInt::get(Int32Ty, flags.getBitMask()); 1961626aecc4SMike Stump Builder.CreateCall2(F, V, N); 1962626aecc4SMike Stump } 196373064870SJohn McCall 196473064870SJohn McCall namespace { 196573064870SJohn McCall struct CallBlockRelease : EHScopeStack::Cleanup { 196673064870SJohn McCall llvm::Value *Addr; 196773064870SJohn McCall CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {} 196873064870SJohn McCall 196930317fdaSJohn McCall void Emit(CodeGenFunction &CGF, Flags flags) { 197031168b07SJohn McCall // Should we be passing FIELD_IS_WEAK here? 197173064870SJohn McCall CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF); 197273064870SJohn McCall } 197373064870SJohn McCall }; 197473064870SJohn McCall } 197573064870SJohn McCall 197673064870SJohn McCall /// Enter a cleanup to destroy a __block variable. Note that this 197773064870SJohn McCall /// cleanup should be a no-op if the variable hasn't left the stack 197873064870SJohn McCall /// yet; if a cleanup is required for the variable itself, that needs 197973064870SJohn McCall /// to be done externally. 198073064870SJohn McCall void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) { 198173064870SJohn McCall // We don't enter this cleanup if we're in pure-GC mode. 1982*bbafb8a7SDavid Blaikie if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) 198373064870SJohn McCall return; 198473064870SJohn McCall 198573064870SJohn McCall EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address); 198673064870SJohn McCall } 19877959fee2SJohn McCall 19887959fee2SJohn McCall /// Adjust the declaration of something from the blocks API. 19897959fee2SJohn McCall static void configureBlocksRuntimeObject(CodeGenModule &CGM, 19907959fee2SJohn McCall llvm::Constant *C) { 1991*bbafb8a7SDavid Blaikie if (!CGM.getLangOpts().BlocksRuntimeOptional) return; 19927959fee2SJohn McCall 19937959fee2SJohn McCall llvm::GlobalValue *GV = cast<llvm::GlobalValue>(C->stripPointerCasts()); 19947959fee2SJohn McCall if (GV->isDeclaration() && 19957959fee2SJohn McCall GV->getLinkage() == llvm::GlobalValue::ExternalLinkage) 19967959fee2SJohn McCall GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 19977959fee2SJohn McCall } 19987959fee2SJohn McCall 19997959fee2SJohn McCall llvm::Constant *CodeGenModule::getBlockObjectDispose() { 20007959fee2SJohn McCall if (BlockObjectDispose) 20017959fee2SJohn McCall return BlockObjectDispose; 20027959fee2SJohn McCall 20037959fee2SJohn McCall llvm::Type *args[] = { Int8PtrTy, Int32Ty }; 20047959fee2SJohn McCall llvm::FunctionType *fty 20057959fee2SJohn McCall = llvm::FunctionType::get(VoidTy, args, false); 20067959fee2SJohn McCall BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose"); 20077959fee2SJohn McCall configureBlocksRuntimeObject(*this, BlockObjectDispose); 20087959fee2SJohn McCall return BlockObjectDispose; 20097959fee2SJohn McCall } 20107959fee2SJohn McCall 20117959fee2SJohn McCall llvm::Constant *CodeGenModule::getBlockObjectAssign() { 20127959fee2SJohn McCall if (BlockObjectAssign) 20137959fee2SJohn McCall return BlockObjectAssign; 20147959fee2SJohn McCall 20157959fee2SJohn McCall llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty }; 20167959fee2SJohn McCall llvm::FunctionType *fty 20177959fee2SJohn McCall = llvm::FunctionType::get(VoidTy, args, false); 20187959fee2SJohn McCall BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign"); 20197959fee2SJohn McCall configureBlocksRuntimeObject(*this, BlockObjectAssign); 20207959fee2SJohn McCall return BlockObjectAssign; 20217959fee2SJohn McCall } 20227959fee2SJohn McCall 20237959fee2SJohn McCall llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() { 20247959fee2SJohn McCall if (NSConcreteGlobalBlock) 20257959fee2SJohn McCall return NSConcreteGlobalBlock; 20267959fee2SJohn McCall 20277959fee2SJohn McCall NSConcreteGlobalBlock = GetOrCreateLLVMGlobal("_NSConcreteGlobalBlock", 20287959fee2SJohn McCall Int8PtrTy->getPointerTo(), 0); 20297959fee2SJohn McCall configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock); 20307959fee2SJohn McCall return NSConcreteGlobalBlock; 20317959fee2SJohn McCall } 20327959fee2SJohn McCall 20337959fee2SJohn McCall llvm::Constant *CodeGenModule::getNSConcreteStackBlock() { 20347959fee2SJohn McCall if (NSConcreteStackBlock) 20357959fee2SJohn McCall return NSConcreteStackBlock; 20367959fee2SJohn McCall 20377959fee2SJohn McCall NSConcreteStackBlock = GetOrCreateLLVMGlobal("_NSConcreteStackBlock", 20387959fee2SJohn McCall Int8PtrTy->getPointerTo(), 0); 20397959fee2SJohn McCall configureBlocksRuntimeObject(*this, NSConcreteStackBlock); 20407959fee2SJohn McCall return NSConcreteStackBlock; 20417959fee2SJohn McCall } 2042