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. 95351762cdSJohn McCall if (C.getLangOptions().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, 218351762cdSJohn McCall const VarDecl *var) { 219351762cdSJohn McCall QualType type = var->getType(); 220351762cdSJohn McCall 221351762cdSJohn McCall // We can only do this if the variable is const. 222351762cdSJohn McCall if (!type.isConstQualified()) return 0; 223351762cdSJohn McCall 224b0a3ecb4SJohn McCall // Furthermore, in C++ we have to worry about mutable fields: 225b0a3ecb4SJohn McCall // C++ [dcl.type.cv]p4: 226b0a3ecb4SJohn McCall // Except that any class member declared mutable can be 227b0a3ecb4SJohn McCall // modified, any attempt to modify a const object during its 228b0a3ecb4SJohn McCall // lifetime results in undefined behavior. 229b0a3ecb4SJohn McCall if (CGM.getLangOptions().CPlusPlus && !isSafeForCXXConstantCapture(type)) 230351762cdSJohn McCall return 0; 231351762cdSJohn McCall 232351762cdSJohn McCall // If the variable doesn't have any initializer (shouldn't this be 233351762cdSJohn McCall // invalid?), it's not clear what we should do. Maybe capture as 234351762cdSJohn McCall // zero? 235351762cdSJohn McCall const Expr *init = var->getInit(); 236351762cdSJohn McCall if (!init) return 0; 237351762cdSJohn McCall 238351762cdSJohn McCall return CGM.EmitConstantExpr(init, var->getType()); 239351762cdSJohn McCall } 240351762cdSJohn McCall 241351762cdSJohn McCall /// Get the low bit of a nonzero character count. This is the 242351762cdSJohn McCall /// alignment of the nth byte if the 0th byte is universally aligned. 243351762cdSJohn McCall static CharUnits getLowBit(CharUnits v) { 244351762cdSJohn McCall return CharUnits::fromQuantity(v.getQuantity() & (~v.getQuantity() + 1)); 245351762cdSJohn McCall } 246351762cdSJohn McCall 247351762cdSJohn McCall static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info, 2480e62c1ccSChris Lattner SmallVectorImpl<llvm::Type*> &elementTypes) { 249351762cdSJohn McCall ASTContext &C = CGM.getContext(); 250351762cdSJohn McCall 251351762cdSJohn McCall // The header is basically a 'struct { void *; int; int; void *; void *; }'. 252351762cdSJohn McCall CharUnits ptrSize, ptrAlign, intSize, intAlign; 253351762cdSJohn McCall llvm::tie(ptrSize, ptrAlign) = C.getTypeInfoInChars(C.VoidPtrTy); 254351762cdSJohn McCall llvm::tie(intSize, intAlign) = C.getTypeInfoInChars(C.IntTy); 255351762cdSJohn McCall 256351762cdSJohn McCall // Are there crazy embedded platforms where this isn't true? 257351762cdSJohn McCall assert(intSize <= ptrSize && "layout assumptions horribly violated"); 258351762cdSJohn McCall 259351762cdSJohn McCall CharUnits headerSize = ptrSize; 260351762cdSJohn McCall if (2 * intSize < ptrAlign) headerSize += ptrSize; 261351762cdSJohn McCall else headerSize += 2 * intSize; 262351762cdSJohn McCall headerSize += 2 * ptrSize; 263351762cdSJohn McCall 264351762cdSJohn McCall info.BlockAlign = ptrAlign; 265351762cdSJohn McCall info.BlockSize = headerSize; 266351762cdSJohn McCall 267351762cdSJohn McCall assert(elementTypes.empty()); 2687c57be3eSJay Foad llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy); 2697c57be3eSJay Foad llvm::Type *intTy = CGM.getTypes().ConvertType(C.IntTy); 270351762cdSJohn McCall elementTypes.push_back(i8p); 271351762cdSJohn McCall elementTypes.push_back(intTy); 272351762cdSJohn McCall elementTypes.push_back(intTy); 273351762cdSJohn McCall elementTypes.push_back(i8p); 274351762cdSJohn McCall elementTypes.push_back(CGM.getBlockDescriptorType()); 275351762cdSJohn McCall 276351762cdSJohn McCall assert(elementTypes.size() == BlockHeaderSize); 277351762cdSJohn McCall } 278351762cdSJohn McCall 279351762cdSJohn McCall /// Compute the layout of the given block. Attempts to lay the block 280351762cdSJohn McCall /// out with minimal space requirements. 281351762cdSJohn McCall static void computeBlockInfo(CodeGenModule &CGM, CGBlockInfo &info) { 282351762cdSJohn McCall ASTContext &C = CGM.getContext(); 283351762cdSJohn McCall const BlockDecl *block = info.getBlockDecl(); 284351762cdSJohn McCall 2850e62c1ccSChris Lattner SmallVector<llvm::Type*, 8> elementTypes; 286351762cdSJohn McCall initializeForBlockHeader(CGM, info, elementTypes); 287351762cdSJohn McCall 288351762cdSJohn McCall if (!block->hasCaptures()) { 289351762cdSJohn McCall info.StructureType = 290351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 291351762cdSJohn McCall info.CanBeGlobal = true; 292351762cdSJohn McCall return; 293351762cdSJohn McCall } 294351762cdSJohn McCall 295351762cdSJohn McCall // Collect the layout chunks. 2960e62c1ccSChris Lattner SmallVector<BlockLayoutChunk, 16> layout; 297351762cdSJohn McCall layout.reserve(block->capturesCXXThis() + 298351762cdSJohn McCall (block->capture_end() - block->capture_begin())); 299351762cdSJohn McCall 300351762cdSJohn McCall CharUnits maxFieldAlign; 301351762cdSJohn McCall 302351762cdSJohn McCall // First, 'this'. 303351762cdSJohn McCall if (block->capturesCXXThis()) { 304351762cdSJohn McCall const DeclContext *DC = block->getDeclContext(); 305351762cdSJohn McCall for (; isa<BlockDecl>(DC); DC = cast<BlockDecl>(DC)->getDeclContext()) 306351762cdSJohn McCall ; 307938f40b5SRichard Smith QualType thisType; 308938f40b5SRichard Smith if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) 309938f40b5SRichard Smith thisType = C.getPointerType(C.getRecordType(RD)); 310938f40b5SRichard Smith else 311938f40b5SRichard Smith thisType = cast<CXXMethodDecl>(DC)->getThisType(C); 312351762cdSJohn McCall 3137c57be3eSJay Foad llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType); 314351762cdSJohn McCall std::pair<CharUnits,CharUnits> tinfo 315351762cdSJohn McCall = CGM.getContext().getTypeInfoInChars(thisType); 316351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, tinfo.second); 317351762cdSJohn McCall 318351762cdSJohn McCall layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, 0, llvmType)); 319351762cdSJohn McCall } 320351762cdSJohn McCall 321351762cdSJohn McCall // Next, all the block captures. 322351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 323351762cdSJohn McCall ce = block->capture_end(); ci != ce; ++ci) { 324351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 325351762cdSJohn McCall 326351762cdSJohn McCall if (ci->isByRef()) { 327351762cdSJohn McCall // We have to copy/dispose of the __block reference. 328351762cdSJohn McCall info.NeedsCopyDispose = true; 329351762cdSJohn McCall 330351762cdSJohn McCall // Just use void* instead of a pointer to the byref type. 331351762cdSJohn McCall QualType byRefPtrTy = C.VoidPtrTy; 332351762cdSJohn McCall 3337c57be3eSJay Foad llvm::Type *llvmType = CGM.getTypes().ConvertType(byRefPtrTy); 334351762cdSJohn McCall std::pair<CharUnits,CharUnits> tinfo 335351762cdSJohn McCall = CGM.getContext().getTypeInfoInChars(byRefPtrTy); 336351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, tinfo.second); 337351762cdSJohn McCall 338351762cdSJohn McCall layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, 339351762cdSJohn McCall &*ci, llvmType)); 340351762cdSJohn McCall continue; 341351762cdSJohn McCall } 342351762cdSJohn McCall 343351762cdSJohn McCall // Otherwise, build a layout chunk with the size and alignment of 344351762cdSJohn McCall // the declaration. 345351762cdSJohn McCall if (llvm::Constant *constant = tryCaptureAsConstant(CGM, variable)) { 346351762cdSJohn McCall info.Captures[variable] = CGBlockInfo::Capture::makeConstant(constant); 347351762cdSJohn McCall continue; 348351762cdSJohn McCall } 349351762cdSJohn McCall 35031168b07SJohn McCall // If we have a lifetime qualifier, honor it for capture purposes. 35131168b07SJohn McCall // That includes *not* copying it if it's __unsafe_unretained. 35231168b07SJohn McCall if (Qualifiers::ObjCLifetime lifetime 35331168b07SJohn McCall = variable->getType().getObjCLifetime()) { 35431168b07SJohn McCall switch (lifetime) { 35531168b07SJohn McCall case Qualifiers::OCL_None: llvm_unreachable("impossible"); 35631168b07SJohn McCall case Qualifiers::OCL_ExplicitNone: 35731168b07SJohn McCall case Qualifiers::OCL_Autoreleasing: 35831168b07SJohn McCall break; 359351762cdSJohn McCall 36031168b07SJohn McCall case Qualifiers::OCL_Strong: 36131168b07SJohn McCall case Qualifiers::OCL_Weak: 36231168b07SJohn McCall info.NeedsCopyDispose = true; 36331168b07SJohn McCall } 36431168b07SJohn McCall 36531168b07SJohn McCall // Block pointers require copy/dispose. So do Objective-C pointers. 36631168b07SJohn McCall } else if (variable->getType()->isObjCRetainableType()) { 367351762cdSJohn McCall info.NeedsCopyDispose = true; 368351762cdSJohn McCall 369351762cdSJohn McCall // So do types that require non-trivial copy construction. 370351762cdSJohn McCall } else if (ci->hasCopyExpr()) { 371351762cdSJohn McCall info.NeedsCopyDispose = true; 372351762cdSJohn McCall info.HasCXXObject = true; 373351762cdSJohn McCall 374351762cdSJohn McCall // And so do types with destructors. 375351762cdSJohn McCall } else if (CGM.getLangOptions().CPlusPlus) { 376351762cdSJohn McCall if (const CXXRecordDecl *record = 377351762cdSJohn McCall variable->getType()->getAsCXXRecordDecl()) { 378351762cdSJohn McCall if (!record->hasTrivialDestructor()) { 379351762cdSJohn McCall info.HasCXXObject = true; 380351762cdSJohn McCall info.NeedsCopyDispose = true; 381351762cdSJohn McCall } 382351762cdSJohn McCall } 383351762cdSJohn McCall } 384351762cdSJohn McCall 38510317eaaSFariborz Jahanian QualType VT = variable->getType(); 386f0cda639SFariborz Jahanian CharUnits size = C.getTypeSizeInChars(VT); 38710317eaaSFariborz Jahanian CharUnits align = C.getDeclAlign(variable); 388f0cda639SFariborz Jahanian 389351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, align); 390351762cdSJohn McCall 3917c57be3eSJay Foad llvm::Type *llvmType = 392f0cda639SFariborz Jahanian CGM.getTypes().ConvertTypeForMem(VT); 393351762cdSJohn McCall 394351762cdSJohn McCall layout.push_back(BlockLayoutChunk(align, size, &*ci, llvmType)); 395351762cdSJohn McCall } 396351762cdSJohn McCall 397351762cdSJohn McCall // If that was everything, we're done here. 398351762cdSJohn McCall if (layout.empty()) { 399351762cdSJohn McCall info.StructureType = 400351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 401351762cdSJohn McCall info.CanBeGlobal = true; 402351762cdSJohn McCall return; 403351762cdSJohn McCall } 404351762cdSJohn McCall 405351762cdSJohn McCall // Sort the layout by alignment. We have to use a stable sort here 406351762cdSJohn McCall // to get reproducible results. There should probably be an 407351762cdSJohn McCall // llvm::array_pod_stable_sort. 408351762cdSJohn McCall std::stable_sort(layout.begin(), layout.end()); 409351762cdSJohn McCall 410351762cdSJohn McCall CharUnits &blockSize = info.BlockSize; 411351762cdSJohn McCall info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign); 412351762cdSJohn McCall 413351762cdSJohn McCall // Assuming that the first byte in the header is maximally aligned, 414351762cdSJohn McCall // get the alignment of the first byte following the header. 415351762cdSJohn McCall CharUnits endAlign = getLowBit(blockSize); 416351762cdSJohn McCall 417351762cdSJohn McCall // If the end of the header isn't satisfactorily aligned for the 418351762cdSJohn McCall // maximum thing, look for things that are okay with the header-end 419351762cdSJohn McCall // alignment, and keep appending them until we get something that's 420351762cdSJohn McCall // aligned right. This algorithm is only guaranteed optimal if 421351762cdSJohn McCall // that condition is satisfied at some point; otherwise we can get 422351762cdSJohn McCall // things like: 423351762cdSJohn McCall // header // next byte has alignment 4 424351762cdSJohn McCall // something_with_size_5; // next byte has alignment 1 425351762cdSJohn McCall // something_with_alignment_8; 426351762cdSJohn McCall // which has 7 bytes of padding, as opposed to the naive solution 427351762cdSJohn McCall // which might have less (?). 428351762cdSJohn McCall if (endAlign < maxFieldAlign) { 4290e62c1ccSChris Lattner SmallVectorImpl<BlockLayoutChunk>::iterator 430351762cdSJohn McCall li = layout.begin() + 1, le = layout.end(); 431351762cdSJohn McCall 432351762cdSJohn McCall // Look for something that the header end is already 433351762cdSJohn McCall // satisfactorily aligned for. 434351762cdSJohn McCall for (; li != le && endAlign < li->Alignment; ++li) 435351762cdSJohn McCall ; 436351762cdSJohn McCall 437351762cdSJohn McCall // If we found something that's naturally aligned for the end of 438351762cdSJohn McCall // the header, keep adding things... 439351762cdSJohn McCall if (li != le) { 4400e62c1ccSChris Lattner SmallVectorImpl<BlockLayoutChunk>::iterator first = li; 441351762cdSJohn McCall for (; li != le; ++li) { 442351762cdSJohn McCall assert(endAlign >= li->Alignment); 443351762cdSJohn McCall 444351762cdSJohn McCall li->setIndex(info, elementTypes.size()); 445351762cdSJohn McCall elementTypes.push_back(li->Type); 446351762cdSJohn McCall blockSize += li->Size; 447351762cdSJohn McCall endAlign = getLowBit(blockSize); 448351762cdSJohn McCall 449351762cdSJohn McCall // ...until we get to the alignment of the maximum field. 450351762cdSJohn McCall if (endAlign >= maxFieldAlign) 451351762cdSJohn McCall break; 452351762cdSJohn McCall } 453351762cdSJohn McCall 454351762cdSJohn McCall // Don't re-append everything we just appended. 455351762cdSJohn McCall layout.erase(first, li); 456351762cdSJohn McCall } 457351762cdSJohn McCall } 458351762cdSJohn McCall 459351762cdSJohn McCall // At this point, we just have to add padding if the end align still 460351762cdSJohn McCall // isn't aligned right. 461351762cdSJohn McCall if (endAlign < maxFieldAlign) { 462351762cdSJohn McCall CharUnits padding = maxFieldAlign - endAlign; 463351762cdSJohn McCall 464e3dc1707SJohn McCall elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty, 465e3dc1707SJohn McCall padding.getQuantity())); 466351762cdSJohn McCall blockSize += padding; 467351762cdSJohn McCall 468351762cdSJohn McCall endAlign = getLowBit(blockSize); 469351762cdSJohn McCall assert(endAlign >= maxFieldAlign); 470351762cdSJohn McCall } 471351762cdSJohn McCall 472351762cdSJohn McCall // Slam everything else on now. This works because they have 473351762cdSJohn McCall // strictly decreasing alignment and we expect that size is always a 474351762cdSJohn McCall // multiple of alignment. 4750e62c1ccSChris Lattner for (SmallVectorImpl<BlockLayoutChunk>::iterator 476351762cdSJohn McCall li = layout.begin(), le = layout.end(); li != le; ++li) { 477351762cdSJohn McCall assert(endAlign >= li->Alignment); 478351762cdSJohn McCall li->setIndex(info, elementTypes.size()); 479351762cdSJohn McCall elementTypes.push_back(li->Type); 480351762cdSJohn McCall blockSize += li->Size; 481351762cdSJohn McCall endAlign = getLowBit(blockSize); 482351762cdSJohn McCall } 483351762cdSJohn McCall 484351762cdSJohn McCall info.StructureType = 485351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 486351762cdSJohn McCall } 487351762cdSJohn McCall 48808ef4660SJohn McCall /// Enter the scope of a block. This should be run at the entrance to 48908ef4660SJohn McCall /// a full-expression so that the block's cleanups are pushed at the 49008ef4660SJohn McCall /// right place in the stack. 49108ef4660SJohn McCall static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) { 49208ef4660SJohn McCall // Allocate the block info and place it at the head of the list. 49308ef4660SJohn McCall CGBlockInfo &blockInfo = 49408ef4660SJohn McCall *new CGBlockInfo(block, CGF.CurFn->getName()); 49508ef4660SJohn McCall blockInfo.NextBlockInfo = CGF.FirstBlockInfo; 49608ef4660SJohn McCall CGF.FirstBlockInfo = &blockInfo; 49708ef4660SJohn McCall 49808ef4660SJohn McCall // Compute information about the layout, etc., of this block, 49908ef4660SJohn McCall // pushing cleanups as necessary. 50008ef4660SJohn McCall computeBlockInfo(CGF.CGM, blockInfo); 50108ef4660SJohn McCall 50208ef4660SJohn McCall // Nothing else to do if it can be global. 50308ef4660SJohn McCall if (blockInfo.CanBeGlobal) return; 50408ef4660SJohn McCall 50508ef4660SJohn McCall // Make the allocation for the block. 50608ef4660SJohn McCall blockInfo.Address = 50708ef4660SJohn McCall CGF.CreateTempAlloca(blockInfo.StructureType, "block"); 50808ef4660SJohn McCall blockInfo.Address->setAlignment(blockInfo.BlockAlign.getQuantity()); 50908ef4660SJohn McCall 51008ef4660SJohn McCall // If there are cleanups to emit, enter them (but inactive). 51108ef4660SJohn McCall if (!blockInfo.NeedsCopyDispose) return; 51208ef4660SJohn McCall 51308ef4660SJohn McCall // Walk through the captures (in order) and find the ones not 51408ef4660SJohn McCall // captured by constant. 51508ef4660SJohn McCall for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 51608ef4660SJohn McCall ce = block->capture_end(); ci != ce; ++ci) { 51708ef4660SJohn McCall // Ignore __block captures; there's nothing special in the 51808ef4660SJohn McCall // on-stack block that we need to do for them. 51908ef4660SJohn McCall if (ci->isByRef()) continue; 52008ef4660SJohn McCall 52108ef4660SJohn McCall // Ignore variables that are constant-captured. 52208ef4660SJohn McCall const VarDecl *variable = ci->getVariable(); 52308ef4660SJohn McCall CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 52408ef4660SJohn McCall if (capture.isConstant()) continue; 52508ef4660SJohn McCall 52608ef4660SJohn McCall // Ignore objects that aren't destructed. 52708ef4660SJohn McCall QualType::DestructionKind dtorKind = 52808ef4660SJohn McCall variable->getType().isDestructedType(); 52908ef4660SJohn McCall if (dtorKind == QualType::DK_none) continue; 53008ef4660SJohn McCall 53108ef4660SJohn McCall CodeGenFunction::Destroyer *destroyer; 53208ef4660SJohn McCall 53308ef4660SJohn McCall // Block captures count as local values and have imprecise semantics. 53408ef4660SJohn McCall // They also can't be arrays, so need to worry about that. 53508ef4660SJohn McCall if (dtorKind == QualType::DK_objc_strong_lifetime) { 53608ef4660SJohn McCall destroyer = &CodeGenFunction::destroyARCStrongImprecise; 53708ef4660SJohn McCall } else { 53808ef4660SJohn McCall destroyer = &CGF.getDestroyer(dtorKind); 53908ef4660SJohn McCall } 54008ef4660SJohn McCall 54108ef4660SJohn McCall // GEP down to the address. 54208ef4660SJohn McCall llvm::Value *addr = CGF.Builder.CreateStructGEP(blockInfo.Address, 54308ef4660SJohn McCall capture.getIndex()); 54408ef4660SJohn McCall 545f4beacd0SJohn McCall // We can use that GEP as the dominating IP. 546f4beacd0SJohn McCall if (!blockInfo.DominatingIP) 547f4beacd0SJohn McCall blockInfo.DominatingIP = cast<llvm::Instruction>(addr); 548f4beacd0SJohn McCall 54908ef4660SJohn McCall CleanupKind cleanupKind = InactiveNormalCleanup; 55008ef4660SJohn McCall bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind); 55108ef4660SJohn McCall if (useArrayEHCleanup) 55208ef4660SJohn McCall cleanupKind = InactiveNormalAndEHCleanup; 55308ef4660SJohn McCall 55408ef4660SJohn McCall CGF.pushDestroy(cleanupKind, addr, variable->getType(), 55508ef4660SJohn McCall *destroyer, useArrayEHCleanup); 55608ef4660SJohn McCall 55708ef4660SJohn McCall // Remember where that cleanup was. 55808ef4660SJohn McCall capture.setCleanup(CGF.EHStack.stable_begin()); 55908ef4660SJohn McCall } 56008ef4660SJohn McCall } 56108ef4660SJohn McCall 56208ef4660SJohn McCall /// Enter a full-expression with a non-trivial number of objects to 56308ef4660SJohn McCall /// clean up. This is in this file because, at the moment, the only 56408ef4660SJohn McCall /// kind of cleanup object is a BlockDecl*. 56508ef4660SJohn McCall void CodeGenFunction::enterNonTrivialFullExpression(const ExprWithCleanups *E) { 56608ef4660SJohn McCall assert(E->getNumObjects() != 0); 56708ef4660SJohn McCall ArrayRef<ExprWithCleanups::CleanupObject> cleanups = E->getObjects(); 56808ef4660SJohn McCall for (ArrayRef<ExprWithCleanups::CleanupObject>::iterator 56908ef4660SJohn McCall i = cleanups.begin(), e = cleanups.end(); i != e; ++i) { 57008ef4660SJohn McCall enterBlockScope(*this, *i); 57108ef4660SJohn McCall } 57208ef4660SJohn McCall } 57308ef4660SJohn McCall 57408ef4660SJohn McCall /// Find the layout for the given block in a linked list and remove it. 57508ef4660SJohn McCall static CGBlockInfo *findAndRemoveBlockInfo(CGBlockInfo **head, 57608ef4660SJohn McCall const BlockDecl *block) { 57708ef4660SJohn McCall while (true) { 57808ef4660SJohn McCall assert(head && *head); 57908ef4660SJohn McCall CGBlockInfo *cur = *head; 58008ef4660SJohn McCall 58108ef4660SJohn McCall // If this is the block we're looking for, splice it out of the list. 58208ef4660SJohn McCall if (cur->getBlockDecl() == block) { 58308ef4660SJohn McCall *head = cur->NextBlockInfo; 58408ef4660SJohn McCall return cur; 58508ef4660SJohn McCall } 58608ef4660SJohn McCall 58708ef4660SJohn McCall head = &cur->NextBlockInfo; 58808ef4660SJohn McCall } 58908ef4660SJohn McCall } 59008ef4660SJohn McCall 59108ef4660SJohn McCall /// Destroy a chain of block layouts. 59208ef4660SJohn McCall void CodeGenFunction::destroyBlockInfos(CGBlockInfo *head) { 59308ef4660SJohn McCall assert(head && "destroying an empty chain"); 59408ef4660SJohn McCall do { 59508ef4660SJohn McCall CGBlockInfo *cur = head; 59608ef4660SJohn McCall head = cur->NextBlockInfo; 59708ef4660SJohn McCall delete cur; 59808ef4660SJohn McCall } while (head != 0); 59908ef4660SJohn McCall } 60008ef4660SJohn McCall 601351762cdSJohn McCall /// Emit a block literal expression in the current function. 602351762cdSJohn McCall llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { 60308ef4660SJohn McCall // If the block has no captures, we won't have a pre-computed 60408ef4660SJohn McCall // layout for it. 60508ef4660SJohn McCall if (!blockExpr->getBlockDecl()->hasCaptures()) { 60608ef4660SJohn McCall CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName()); 607351762cdSJohn McCall computeBlockInfo(CGM, blockInfo); 60808ef4660SJohn McCall blockInfo.BlockExpression = blockExpr; 60908ef4660SJohn McCall return EmitBlockLiteral(blockInfo); 61008ef4660SJohn McCall } 611351762cdSJohn McCall 61208ef4660SJohn McCall // Find the block info for this block and take ownership of it. 61308ef4660SJohn McCall llvm::OwningPtr<CGBlockInfo> blockInfo; 61408ef4660SJohn McCall blockInfo.reset(findAndRemoveBlockInfo(&FirstBlockInfo, 61508ef4660SJohn McCall blockExpr->getBlockDecl())); 61608ef4660SJohn McCall 61708ef4660SJohn McCall blockInfo->BlockExpression = blockExpr; 61808ef4660SJohn McCall return EmitBlockLiteral(*blockInfo); 61908ef4660SJohn McCall } 62008ef4660SJohn McCall 62108ef4660SJohn McCall llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { 62208ef4660SJohn McCall // Using the computed layout, generate the actual block function. 623351762cdSJohn McCall llvm::Constant *blockFn 624351762cdSJohn McCall = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, blockInfo, 625351762cdSJohn McCall CurFuncDecl, LocalDeclMap); 626e3dc1707SJohn McCall blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); 627351762cdSJohn McCall 628351762cdSJohn McCall // If there is nothing to capture, we can emit this as a global block. 629351762cdSJohn McCall if (blockInfo.CanBeGlobal) 630351762cdSJohn McCall return buildGlobalBlock(CGM, blockInfo, blockFn); 631351762cdSJohn McCall 632351762cdSJohn McCall // Otherwise, we have to emit this as a local block. 633351762cdSJohn McCall 634351762cdSJohn McCall llvm::Constant *isa = CGM.getNSConcreteStackBlock(); 635e3dc1707SJohn McCall isa = llvm::ConstantExpr::getBitCast(isa, VoidPtrTy); 636351762cdSJohn McCall 637351762cdSJohn McCall // Build the block descriptor. 638351762cdSJohn McCall llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo); 639351762cdSJohn McCall 64008ef4660SJohn McCall llvm::AllocaInst *blockAddr = blockInfo.Address; 64108ef4660SJohn McCall assert(blockAddr && "block has no address!"); 642351762cdSJohn McCall 643351762cdSJohn McCall // Compute the initial on-stack block flags. 644ad7c5c16SJohn McCall BlockFlags flags = BLOCK_HAS_SIGNATURE; 645351762cdSJohn McCall if (blockInfo.NeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE; 646351762cdSJohn McCall if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ; 64785915250SJohn McCall if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; 648351762cdSJohn McCall 649351762cdSJohn McCall // Initialize the block literal. 650351762cdSJohn McCall Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa")); 65108ef4660SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()), 652351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, 1, "block.flags")); 65308ef4660SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(IntTy, 0), 654351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, 2, "block.reserved")); 655351762cdSJohn McCall Builder.CreateStore(blockFn, Builder.CreateStructGEP(blockAddr, 3, 656351762cdSJohn McCall "block.invoke")); 657351762cdSJohn McCall Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockAddr, 4, 658351762cdSJohn McCall "block.descriptor")); 659351762cdSJohn McCall 660351762cdSJohn McCall // Finally, capture all the values into the block. 661351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 662351762cdSJohn McCall 663351762cdSJohn McCall // First, 'this'. 664351762cdSJohn McCall if (blockDecl->capturesCXXThis()) { 665351762cdSJohn McCall llvm::Value *addr = Builder.CreateStructGEP(blockAddr, 666351762cdSJohn McCall blockInfo.CXXThisIndex, 667351762cdSJohn McCall "block.captured-this.addr"); 668351762cdSJohn McCall Builder.CreateStore(LoadCXXThis(), addr); 669351762cdSJohn McCall } 670351762cdSJohn McCall 671351762cdSJohn McCall // Next, captured variables. 672351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 673351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 674351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 675351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 676351762cdSJohn McCall 677351762cdSJohn McCall // Ignore constant captures. 678351762cdSJohn McCall if (capture.isConstant()) continue; 679351762cdSJohn McCall 680351762cdSJohn McCall QualType type = variable->getType(); 681351762cdSJohn McCall 682351762cdSJohn McCall // This will be a [[type]]*, except that a byref entry will just be 683351762cdSJohn McCall // an i8**. 684351762cdSJohn McCall llvm::Value *blockField = 685351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, capture.getIndex(), 686351762cdSJohn McCall "block.captured"); 687351762cdSJohn McCall 688351762cdSJohn McCall // Compute the address of the thing we're going to move into the 689351762cdSJohn McCall // block literal. 690351762cdSJohn McCall llvm::Value *src; 691351762cdSJohn McCall if (ci->isNested()) { 692351762cdSJohn McCall // We need to use the capture from the enclosing block. 693351762cdSJohn McCall const CGBlockInfo::Capture &enclosingCapture = 694351762cdSJohn McCall BlockInfo->getCapture(variable); 695351762cdSJohn McCall 696351762cdSJohn McCall // This is a [[type]]*, except that a byref entry wil just be an i8**. 697351762cdSJohn McCall src = Builder.CreateStructGEP(LoadBlockStruct(), 698351762cdSJohn McCall enclosingCapture.getIndex(), 699351762cdSJohn McCall "block.capture.addr"); 700351762cdSJohn McCall } else { 701351762cdSJohn McCall // This is a [[type]]*. 702351762cdSJohn McCall src = LocalDeclMap[variable]; 703351762cdSJohn McCall } 704351762cdSJohn McCall 705351762cdSJohn McCall // For byrefs, we just write the pointer to the byref struct into 706351762cdSJohn McCall // the block field. There's no need to chase the forwarding 707351762cdSJohn McCall // pointer at this point, since we're building something that will 708351762cdSJohn McCall // live a shorter life than the stack byref anyway. 709351762cdSJohn McCall if (ci->isByRef()) { 710e3dc1707SJohn McCall // Get a void* that points to the byref struct. 711351762cdSJohn McCall if (ci->isNested()) 712351762cdSJohn McCall src = Builder.CreateLoad(src, "byref.capture"); 713351762cdSJohn McCall else 714e3dc1707SJohn McCall src = Builder.CreateBitCast(src, VoidPtrTy); 715351762cdSJohn McCall 716e3dc1707SJohn McCall // Write that void* into the capture field. 717351762cdSJohn McCall Builder.CreateStore(src, blockField); 718351762cdSJohn McCall 719351762cdSJohn McCall // If we have a copy constructor, evaluate that into the block field. 720351762cdSJohn McCall } else if (const Expr *copyExpr = ci->getCopyExpr()) { 721351762cdSJohn McCall EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr); 722351762cdSJohn McCall 723351762cdSJohn McCall // If it's a reference variable, copy the reference into the block field. 72410317eaaSFariborz Jahanian } else if (type->isReferenceType()) { 725351762cdSJohn McCall Builder.CreateStore(Builder.CreateLoad(src, "ref.val"), blockField); 726351762cdSJohn McCall 727351762cdSJohn McCall // Otherwise, fake up a POD copy into the block field. 728351762cdSJohn McCall } else { 72931168b07SJohn McCall // Fake up a new variable so that EmitScalarInit doesn't think 73031168b07SJohn McCall // we're referring to the variable in its own initializer. 73131168b07SJohn McCall ImplicitParamDecl blockFieldPseudoVar(/*DC*/ 0, SourceLocation(), 73210317eaaSFariborz Jahanian /*name*/ 0, type); 73331168b07SJohn McCall 73493be3f75SJohn McCall // We use one of these or the other depending on whether the 73593be3f75SJohn McCall // reference is nested. 73610317eaaSFariborz Jahanian DeclRefExpr notNested(const_cast<VarDecl*>(variable), type, VK_LValue, 737351762cdSJohn McCall SourceLocation()); 73810317eaaSFariborz Jahanian BlockDeclRefExpr nested(const_cast<VarDecl*>(variable), type, 73993be3f75SJohn McCall VK_LValue, SourceLocation(), /*byref*/ false); 74093be3f75SJohn McCall 74193be3f75SJohn McCall Expr *declRef = 74293be3f75SJohn McCall (ci->isNested() ? static_cast<Expr*>(&nested) : ¬Nested); 74393be3f75SJohn McCall 74410317eaaSFariborz Jahanian ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue, 74593be3f75SJohn McCall declRef, VK_RValue); 7461553b190SJohn McCall EmitExprAsInit(&l2r, &blockFieldPseudoVar, 74710317eaaSFariborz Jahanian MakeAddrLValue(blockField, type, 748*a0544d6fSEli Friedman getContext().getDeclAlign(variable)), 7495c8f6c47SJohn McCall /*captured by init*/ false); 750351762cdSJohn McCall } 751351762cdSJohn McCall 75208ef4660SJohn McCall // Activate the cleanup if layout pushed one. 75331168b07SJohn McCall if (!ci->isByRef()) { 75408ef4660SJohn McCall EHScopeStack::stable_iterator cleanup = capture.getCleanup(); 75508ef4660SJohn McCall if (cleanup.isValid()) 756f4beacd0SJohn McCall ActivateCleanupBlock(cleanup, blockInfo.DominatingIP); 75731168b07SJohn McCall } 758351762cdSJohn McCall } 759351762cdSJohn McCall 760351762cdSJohn McCall // Cast to the converted block-pointer type, which happens (somewhat 761351762cdSJohn McCall // unfortunately) to be a pointer to function type. 762351762cdSJohn McCall llvm::Value *result = 763351762cdSJohn McCall Builder.CreateBitCast(blockAddr, 764351762cdSJohn McCall ConvertType(blockInfo.getBlockExpr()->getType())); 7653882ace2SJohn McCall 766351762cdSJohn McCall return result; 767b750d928SMike Stump } 76885284bacSMike Stump 76985284bacSMike Stump 770a5f58b05SChris Lattner llvm::Type *CodeGenModule::getBlockDescriptorType() { 771650c932dSMike Stump if (BlockDescriptorType) 772650c932dSMike Stump return BlockDescriptorType; 7732437cbfaSAnders Carlsson 774a5f58b05SChris Lattner llvm::Type *UnsignedLongTy = 775650c932dSMike Stump getTypes().ConvertType(getContext().UnsignedLongTy); 7762437cbfaSAnders Carlsson 7772437cbfaSAnders Carlsson // struct __block_descriptor { 7782437cbfaSAnders Carlsson // unsigned long reserved; 7792437cbfaSAnders Carlsson // unsigned long block_size; 780fc83aa04SBlaine Garst // 781fc83aa04SBlaine Garst // // later, the following will be added 782fc83aa04SBlaine Garst // 783fc83aa04SBlaine Garst // struct { 784fc83aa04SBlaine Garst // void (*copyHelper)(); 785fc83aa04SBlaine Garst // void (*copyHelper)(); 786fc83aa04SBlaine Garst // } helpers; // !!! optional 787fc83aa04SBlaine Garst // 788fc83aa04SBlaine Garst // const char *signature; // the block signature 789fc83aa04SBlaine Garst // const char *layout; // reserved 7902437cbfaSAnders Carlsson // }; 791845511feSChris Lattner BlockDescriptorType = 7925ec04a51SChris Lattner llvm::StructType::create("struct.__block_descriptor", 793a5f58b05SChris Lattner UnsignedLongTy, UnsignedLongTy, NULL); 7942437cbfaSAnders Carlsson 795351762cdSJohn McCall // Now form a pointer to that. 796351762cdSJohn McCall BlockDescriptorType = llvm::PointerType::getUnqual(BlockDescriptorType); 797650c932dSMike Stump return BlockDescriptorType; 7982437cbfaSAnders Carlsson } 7992437cbfaSAnders Carlsson 800a5f58b05SChris Lattner llvm::Type *CodeGenModule::getGenericBlockLiteralType() { 801005c9a62SMike Stump if (GenericBlockLiteralType) 802005c9a62SMike Stump return GenericBlockLiteralType; 8032437cbfaSAnders Carlsson 804a5f58b05SChris Lattner llvm::Type *BlockDescPtrTy = getBlockDescriptorType(); 8052437cbfaSAnders Carlsson 8062437cbfaSAnders Carlsson // struct __block_literal_generic { 8075d2534adSMike Stump // void *__isa; 8085d2534adSMike Stump // int __flags; 8095d2534adSMike Stump // int __reserved; 8105d2534adSMike Stump // void (*__invoke)(void *); 8115d2534adSMike Stump // struct __block_descriptor *__descriptor; 8122437cbfaSAnders Carlsson // }; 813a5f58b05SChris Lattner GenericBlockLiteralType = 8145ec04a51SChris Lattner llvm::StructType::create("struct.__block_literal_generic", 8155ec04a51SChris Lattner VoidPtrTy, IntTy, IntTy, VoidPtrTy, 8165ec04a51SChris Lattner BlockDescPtrTy, NULL); 8172437cbfaSAnders Carlsson 818005c9a62SMike Stump return GenericBlockLiteralType; 8192437cbfaSAnders Carlsson } 8202437cbfaSAnders Carlsson 8215d2534adSMike Stump 822bfb3671bSAnders Carlsson RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E, 823bfb3671bSAnders Carlsson ReturnValueSlot ReturnValue) { 8242437cbfaSAnders Carlsson const BlockPointerType *BPT = 825c23c7e6aSTed Kremenek E->getCallee()->getType()->getAs<BlockPointerType>(); 8262437cbfaSAnders Carlsson 8272437cbfaSAnders Carlsson llvm::Value *Callee = EmitScalarExpr(E->getCallee()); 8282437cbfaSAnders Carlsson 8292437cbfaSAnders Carlsson // Get a pointer to the generic block literal. 8302192fe50SChris Lattner llvm::Type *BlockLiteralTy = 8319793f0e4SOwen Anderson llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType()); 8322437cbfaSAnders Carlsson 8332437cbfaSAnders Carlsson // Bitcast the callee to a block literal. 8342437cbfaSAnders Carlsson llvm::Value *BlockLiteral = 8352437cbfaSAnders Carlsson Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal"); 8362437cbfaSAnders Carlsson 8372437cbfaSAnders Carlsson // Get the function pointer from the literal. 83876399eb2SBenjamin Kramer llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3); 8392437cbfaSAnders Carlsson 84076399eb2SBenjamin Kramer BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy); 8412437cbfaSAnders Carlsson 8422437cbfaSAnders Carlsson // Add the block literal. 8432437cbfaSAnders Carlsson CallArgList Args; 8449dc0db21SJohn McCall Args.add(RValue::get(BlockLiteral), getContext().VoidPtrTy); 8452437cbfaSAnders Carlsson 846479e6fc7SAnders Carlsson QualType FnType = BPT->getPointeeType(); 847479e6fc7SAnders Carlsson 8482437cbfaSAnders Carlsson // And the rest of the arguments. 8499dd450bbSJohn McCall EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), 850479e6fc7SAnders Carlsson E->arg_begin(), E->arg_end()); 8512437cbfaSAnders Carlsson 8525f50c651SAnders Carlsson // Load the function. 85376399eb2SBenjamin Kramer llvm::Value *Func = Builder.CreateLoad(FuncPtr); 8545f50c651SAnders Carlsson 85585915250SJohn McCall const FunctionType *FuncTy = FnType->castAs<FunctionType>(); 856f481ccafSEli Friedman const CGFunctionInfo &FnInfo = CGM.getTypes().getFunctionInfo(Args, FuncTy); 8575f50c651SAnders Carlsson 8585f50c651SAnders Carlsson // Cast the function pointer to the right type. 8592192fe50SChris Lattner llvm::Type *BlockFTy = 860a60cbcdfSAnders Carlsson CGM.getTypes().GetFunctionType(FnInfo, false); 8615f50c651SAnders Carlsson 8622192fe50SChris Lattner llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); 8635f50c651SAnders Carlsson Func = Builder.CreateBitCast(Func, BlockFTyPtr); 8645f50c651SAnders Carlsson 8652437cbfaSAnders Carlsson // And call the block. 866bfb3671bSAnders Carlsson return EmitCall(FnInfo, Func, ReturnValue, Args); 8672437cbfaSAnders Carlsson } 8686a60fa24SAnders Carlsson 869351762cdSJohn McCall llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable, 870351762cdSJohn McCall bool isByRef) { 871351762cdSJohn McCall assert(BlockInfo && "evaluating block ref without block information?"); 872351762cdSJohn McCall const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable); 87387fe5d56SJohn McCall 874351762cdSJohn McCall // Handle constant captures. 875351762cdSJohn McCall if (capture.isConstant()) return LocalDeclMap[variable]; 87687fe5d56SJohn McCall 877351762cdSJohn McCall llvm::Value *addr = 878351762cdSJohn McCall Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(), 879351762cdSJohn McCall "block.capture.addr"); 880351762cdSJohn McCall 881351762cdSJohn McCall if (isByRef) { 882351762cdSJohn McCall // addr should be a void** right now. Load, then cast the result 883351762cdSJohn McCall // to byref*. 884351762cdSJohn McCall 885351762cdSJohn McCall addr = Builder.CreateLoad(addr); 8862192fe50SChris Lattner llvm::PointerType *byrefPointerType 887351762cdSJohn McCall = llvm::PointerType::get(BuildByRefType(variable), 0); 888351762cdSJohn McCall addr = Builder.CreateBitCast(addr, byrefPointerType, 889351762cdSJohn McCall "byref.addr"); 890351762cdSJohn McCall 891351762cdSJohn McCall // Follow the forwarding pointer. 892351762cdSJohn McCall addr = Builder.CreateStructGEP(addr, 1, "byref.forwarding"); 893351762cdSJohn McCall addr = Builder.CreateLoad(addr, "byref.addr.forwarded"); 894351762cdSJohn McCall 895351762cdSJohn McCall // Cast back to byref* and GEP over to the actual object. 896351762cdSJohn McCall addr = Builder.CreateBitCast(addr, byrefPointerType); 897351762cdSJohn McCall addr = Builder.CreateStructGEP(addr, getByRefValueLLVMField(variable), 898351762cdSJohn McCall variable->getNameAsString()); 89987fe5d56SJohn McCall } 90087fe5d56SJohn McCall 90110317eaaSFariborz Jahanian if (variable->getType()->isReferenceType()) 902351762cdSJohn McCall addr = Builder.CreateLoad(addr, "ref.tmp"); 9030168f4b2SAnders Carlsson 904351762cdSJohn McCall return addr; 90597d01d50SMike Stump } 90697d01d50SMike Stump 9072d5a2878SMike Stump llvm::Constant * 908ad7c5c16SJohn McCall CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr, 909351762cdSJohn McCall const char *name) { 91008ef4660SJohn McCall CGBlockInfo blockInfo(blockExpr->getBlockDecl(), name); 91108ef4660SJohn McCall blockInfo.BlockExpression = blockExpr; 9126a60fa24SAnders Carlsson 913351762cdSJohn McCall // Compute information about the layout, etc., of this block. 914ad7c5c16SJohn McCall computeBlockInfo(*this, blockInfo); 9156a60fa24SAnders Carlsson 916351762cdSJohn McCall // Using that metadata, generate the actual block function. 917351762cdSJohn McCall llvm::Constant *blockFn; 918351762cdSJohn McCall { 9195469f29aSMike Stump llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap; 920ad7c5c16SJohn McCall blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(), 921351762cdSJohn McCall blockInfo, 922351762cdSJohn McCall 0, LocalDeclMap); 923351762cdSJohn McCall } 924e3dc1707SJohn McCall blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); 9256a60fa24SAnders Carlsson 926ad7c5c16SJohn McCall return buildGlobalBlock(*this, blockInfo, blockFn); 9276a60fa24SAnders Carlsson } 9286a60fa24SAnders Carlsson 929351762cdSJohn McCall static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, 930351762cdSJohn McCall const CGBlockInfo &blockInfo, 931351762cdSJohn McCall llvm::Constant *blockFn) { 932351762cdSJohn McCall assert(blockInfo.CanBeGlobal); 933351762cdSJohn McCall 934351762cdSJohn McCall // Generate the constants for the block literal initializer. 935351762cdSJohn McCall llvm::Constant *fields[BlockHeaderSize]; 936351762cdSJohn McCall 937351762cdSJohn McCall // isa 938351762cdSJohn McCall fields[0] = CGM.getNSConcreteGlobalBlock(); 939351762cdSJohn McCall 940351762cdSJohn McCall // __flags 94185915250SJohn McCall BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE; 94285915250SJohn McCall if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; 94385915250SJohn McCall 944e3dc1707SJohn McCall fields[1] = llvm::ConstantInt::get(CGM.IntTy, flags.getBitMask()); 945351762cdSJohn McCall 946351762cdSJohn McCall // Reserved 947e3dc1707SJohn McCall fields[2] = llvm::Constant::getNullValue(CGM.IntTy); 948351762cdSJohn McCall 949351762cdSJohn McCall // Function 950351762cdSJohn McCall fields[3] = blockFn; 951351762cdSJohn McCall 952351762cdSJohn McCall // Descriptor 953351762cdSJohn McCall fields[4] = buildBlockDescriptor(CGM, blockInfo); 954351762cdSJohn McCall 955e64d7ba1SChris Lattner llvm::Constant *init = llvm::ConstantStruct::getAnon(fields); 956351762cdSJohn McCall 957351762cdSJohn McCall llvm::GlobalVariable *literal = 958351762cdSJohn McCall new llvm::GlobalVariable(CGM.getModule(), 959351762cdSJohn McCall init->getType(), 960351762cdSJohn McCall /*constant*/ true, 961351762cdSJohn McCall llvm::GlobalVariable::InternalLinkage, 962351762cdSJohn McCall init, 963351762cdSJohn McCall "__block_literal_global"); 964351762cdSJohn McCall literal->setAlignment(blockInfo.BlockAlign.getQuantity()); 965351762cdSJohn McCall 966351762cdSJohn McCall // Return a constant of the appropriately-casted type. 9672192fe50SChris Lattner llvm::Type *requiredType = 968351762cdSJohn McCall CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType()); 969351762cdSJohn McCall return llvm::ConstantExpr::getBitCast(literal, requiredType); 970cb2fbcb0SMike Stump } 971cb2fbcb0SMike Stump 9724446dcf0SMike Stump llvm::Function * 973351762cdSJohn McCall CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, 974351762cdSJohn McCall const CGBlockInfo &blockInfo, 975351762cdSJohn McCall const Decl *outerFnDecl, 976351762cdSJohn McCall const DeclMapTy &ldm) { 977351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 9789074ed8cSDevang Patel 9796e40c615SDevang Patel // Check if we should generate debug info for this block function. 9806e40c615SDevang Patel if (CGM.getModuleDebugInfo()) 9816e40c615SDevang Patel DebugInfo = CGM.getModuleDebugInfo(); 9826e40c615SDevang Patel 983351762cdSJohn McCall BlockInfo = &blockInfo; 9849074ed8cSDevang Patel 9855469f29aSMike Stump // Arrange for local static and local extern declarations to appear 986351762cdSJohn McCall // to be local to this function as well, in case they're directly 987351762cdSJohn McCall // referenced in a block. 988351762cdSJohn McCall for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) { 989351762cdSJohn McCall const VarDecl *var = dyn_cast<VarDecl>(i->first); 990351762cdSJohn McCall if (var && !var->hasLocalStorage()) 991351762cdSJohn McCall LocalDeclMap[var] = i->second; 9925469f29aSMike Stump } 9935469f29aSMike Stump 994351762cdSJohn McCall // Begin building the function declaration. 99509a9b6e3SEli Friedman 996351762cdSJohn McCall // Build the argument list. 997351762cdSJohn McCall FunctionArgList args; 9986a60fa24SAnders Carlsson 999351762cdSJohn McCall // The first argument is the block pointer. Just take it as a void* 1000351762cdSJohn McCall // and cast it later. 1001351762cdSJohn McCall QualType selfTy = getContext().VoidPtrTy; 10027fe9cc1dSMike Stump IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); 1003d015328fSMike Stump 1004147d021bSJohn McCall ImplicitParamDecl selfDecl(const_cast<BlockDecl*>(blockDecl), 1005351762cdSJohn McCall SourceLocation(), II, selfTy); 1006a738c25fSJohn McCall args.push_back(&selfDecl); 10077fe9cc1dSMike Stump 1008351762cdSJohn McCall // Now add the rest of the parameters. 1009351762cdSJohn McCall for (BlockDecl::param_const_iterator i = blockDecl->param_begin(), 1010351762cdSJohn McCall e = blockDecl->param_end(); i != e; ++i) 1011a738c25fSJohn McCall args.push_back(*i); 1012afa3c0a8SFariborz Jahanian 1013351762cdSJohn McCall // Create the function declaration. 1014351762cdSJohn McCall const FunctionProtoType *fnType = 1015351762cdSJohn McCall cast<FunctionProtoType>(blockInfo.getBlockExpr()->getFunctionType()); 1016351762cdSJohn McCall const CGFunctionInfo &fnInfo = 1017351762cdSJohn McCall CGM.getTypes().getFunctionInfo(fnType->getResultType(), args, 1018351762cdSJohn McCall fnType->getExtInfo()); 101985915250SJohn McCall if (CGM.ReturnTypeUsesSRet(fnInfo)) 102085915250SJohn McCall blockInfo.UsesStret = true; 102185915250SJohn McCall 10222192fe50SChris Lattner llvm::FunctionType *fnLLVMType = 1023351762cdSJohn McCall CGM.getTypes().GetFunctionType(fnInfo, fnType->isVariadic()); 102487fe5d56SJohn McCall 1025351762cdSJohn McCall MangleBuffer name; 1026351762cdSJohn McCall CGM.getBlockMangledName(GD, name, blockDecl); 1027351762cdSJohn McCall llvm::Function *fn = 1028351762cdSJohn McCall llvm::Function::Create(fnLLVMType, llvm::GlobalValue::InternalLinkage, 1029351762cdSJohn McCall name.getString(), &CGM.getModule()); 1030351762cdSJohn McCall CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo); 10316a60fa24SAnders Carlsson 1032351762cdSJohn McCall // Begin generating the function. 1033a738c25fSJohn McCall StartFunction(blockDecl, fnType->getResultType(), fn, fnInfo, args, 10345f070a51SDevang Patel blockInfo.getBlockExpr()->getBody()->getLocStart()); 1035351762cdSJohn McCall CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl 10366a60fa24SAnders Carlsson 1037147d021bSJohn McCall // Okay. Undo some of what StartFunction did. 1038147d021bSJohn McCall 1039147d021bSJohn McCall // Pull the 'self' reference out of the local decl map. 1040147d021bSJohn McCall llvm::Value *blockAddr = LocalDeclMap[&selfDecl]; 1041147d021bSJohn McCall LocalDeclMap.erase(&selfDecl); 1042351762cdSJohn McCall BlockPointer = Builder.CreateBitCast(blockAddr, 1043351762cdSJohn McCall blockInfo.StructureType->getPointerTo(), 1044351762cdSJohn McCall "block"); 1045017460abSMike Stump 104687fe5d56SJohn McCall // If we have a C++ 'this' reference, go ahead and force it into 104787fe5d56SJohn McCall // existence now. 1048351762cdSJohn McCall if (blockDecl->capturesCXXThis()) { 1049351762cdSJohn McCall llvm::Value *addr = Builder.CreateStructGEP(BlockPointer, 1050351762cdSJohn McCall blockInfo.CXXThisIndex, 1051351762cdSJohn McCall "block.captured-this"); 1052351762cdSJohn McCall CXXThisValue = Builder.CreateLoad(addr, "this"); 105387fe5d56SJohn McCall } 105487fe5d56SJohn McCall 1055351762cdSJohn McCall // LoadObjCSelf() expects there to be an entry for 'self' in LocalDeclMap; 1056351762cdSJohn McCall // appease it. 1057351762cdSJohn McCall if (const ObjCMethodDecl *method 1058351762cdSJohn McCall = dyn_cast_or_null<ObjCMethodDecl>(CurFuncDecl)) { 1059351762cdSJohn McCall const VarDecl *self = method->getSelfDecl(); 1060351762cdSJohn McCall 1061351762cdSJohn McCall // There might not be a capture for 'self', but if there is... 1062351762cdSJohn McCall if (blockInfo.Captures.count(self)) { 1063351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(self); 1064351762cdSJohn McCall llvm::Value *selfAddr = Builder.CreateStructGEP(BlockPointer, 1065351762cdSJohn McCall capture.getIndex(), 1066351762cdSJohn McCall "block.captured-self"); 1067351762cdSJohn McCall LocalDeclMap[self] = selfAddr; 1068351762cdSJohn McCall } 1069351762cdSJohn McCall } 1070351762cdSJohn McCall 1071351762cdSJohn McCall // Also force all the constant captures. 1072351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1073351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1074351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1075351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1076351762cdSJohn McCall if (!capture.isConstant()) continue; 1077351762cdSJohn McCall 1078351762cdSJohn McCall unsigned align = getContext().getDeclAlign(variable).getQuantity(); 1079351762cdSJohn McCall 1080351762cdSJohn McCall llvm::AllocaInst *alloca = 1081351762cdSJohn McCall CreateMemTemp(variable->getType(), "block.captured-const"); 1082351762cdSJohn McCall alloca->setAlignment(align); 1083351762cdSJohn McCall 1084351762cdSJohn McCall Builder.CreateStore(capture.getConstant(), alloca, align); 1085351762cdSJohn McCall 1086351762cdSJohn McCall LocalDeclMap[variable] = alloca; 10879d42f0f1SJohn McCall } 10889d42f0f1SJohn McCall 1089017460abSMike Stump // Save a spot to insert the debug information for all the BlockDeclRefDecls. 1090017460abSMike Stump llvm::BasicBlock *entry = Builder.GetInsertBlock(); 1091017460abSMike Stump llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint(); 1092017460abSMike Stump --entry_ptr; 1093017460abSMike Stump 1094351762cdSJohn McCall EmitStmt(blockDecl->getBody()); 1095017460abSMike Stump 10967d69911aSMike Stump // Remember where we were... 10977d69911aSMike Stump llvm::BasicBlock *resume = Builder.GetInsertBlock(); 1098017460abSMike Stump 10997d69911aSMike Stump // Go back to the entry. 1100017460abSMike Stump ++entry_ptr; 1101017460abSMike Stump Builder.SetInsertPoint(entry, entry_ptr); 1102017460abSMike Stump 11032e722b91SMike Stump // Emit debug information for all the BlockDeclRefDecls. 110487fe5d56SJohn McCall // FIXME: also for 'this' 1105351762cdSJohn McCall if (CGDebugInfo *DI = getDebugInfo()) { 1106351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1107351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1108351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 11097cdf9486SEric Christopher DI->EmitLocation(Builder, variable->getLocation()); 1110351762cdSJohn McCall 1111351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1112351762cdSJohn McCall if (capture.isConstant()) { 1113351762cdSJohn McCall DI->EmitDeclareOfAutoVariable(variable, LocalDeclMap[variable], 1114351762cdSJohn McCall Builder); 1115351762cdSJohn McCall continue; 1116351762cdSJohn McCall } 1117351762cdSJohn McCall 1118147d021bSJohn McCall DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer, 1119351762cdSJohn McCall Builder, blockInfo); 11202e722b91SMike Stump } 11212e722b91SMike Stump } 1122351762cdSJohn McCall 11237d69911aSMike Stump // And resume where we left off. 11247d69911aSMike Stump if (resume == 0) 11257d69911aSMike Stump Builder.ClearInsertionPoint(); 11267d69911aSMike Stump else 11277d69911aSMike Stump Builder.SetInsertPoint(resume); 11282e722b91SMike Stump 1129351762cdSJohn McCall FinishFunction(cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc()); 11306a60fa24SAnders Carlsson 1131351762cdSJohn McCall return fn; 11326a60fa24SAnders Carlsson } 11331db7d04bSMike Stump 1134351762cdSJohn McCall /* 1135351762cdSJohn McCall notes.push_back(HelperInfo()); 1136351762cdSJohn McCall HelperInfo ¬e = notes.back(); 1137351762cdSJohn McCall note.index = capture.getIndex(); 1138351762cdSJohn McCall note.RequiresCopying = (ci->hasCopyExpr() || BlockRequiresCopying(type)); 1139351762cdSJohn McCall note.cxxbar_import = ci->getCopyExpr(); 11401db7d04bSMike Stump 1141351762cdSJohn McCall if (ci->isByRef()) { 1142351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_BYREF; 1143351762cdSJohn McCall if (type.isObjCGCWeak()) 1144351762cdSJohn McCall note.flag |= BLOCK_FIELD_IS_WEAK; 1145351762cdSJohn McCall } else if (type->isBlockPointerType()) { 1146351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_BLOCK; 1147351762cdSJohn McCall } else { 1148351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_OBJECT; 11491db7d04bSMike Stump } 1150351762cdSJohn McCall */ 11511db7d04bSMike Stump 115297d01d50SMike Stump 11530c743277SMike Stump 1154351762cdSJohn McCall llvm::Constant * 1155ad7c5c16SJohn McCall CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { 1156351762cdSJohn McCall ASTContext &C = getContext(); 1157351762cdSJohn McCall 1158351762cdSJohn McCall FunctionArgList args; 1159a738c25fSJohn McCall ImplicitParamDecl dstDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1160a738c25fSJohn McCall args.push_back(&dstDecl); 1161a738c25fSJohn McCall ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1162a738c25fSJohn McCall args.push_back(&srcDecl); 11630c743277SMike Stump 11640c743277SMike Stump const CGFunctionInfo &FI = 1165351762cdSJohn McCall CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo()); 11660c743277SMike Stump 1167351762cdSJohn McCall // FIXME: it would be nice if these were mergeable with things with 1168351762cdSJohn McCall // identical semantics. 11692192fe50SChris Lattner llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false); 11700c743277SMike Stump 11710c743277SMike Stump llvm::Function *Fn = 11720c743277SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1173d6b28fc6SBenjamin Kramer "__copy_helper_block_", &CGM.getModule()); 11740c743277SMike Stump 11750c743277SMike Stump IdentifierInfo *II 11760c743277SMike Stump = &CGM.getContext().Idents.get("__copy_helper_block_"); 11770c743277SMike Stump 11782a7c2194SDevang Patel // Check if we should generate debug info for this block helper function. 11792a7c2194SDevang Patel if (CGM.getModuleDebugInfo()) 11802a7c2194SDevang Patel DebugInfo = CGM.getModuleDebugInfo(); 11812a7c2194SDevang Patel 1182351762cdSJohn McCall FunctionDecl *FD = FunctionDecl::Create(C, 1183351762cdSJohn McCall C.getTranslationUnitDecl(), 1184dff1930bSAbramo Bagnara SourceLocation(), 1185351762cdSJohn McCall SourceLocation(), II, C.VoidTy, 0, 11868e7d656aSJohn McCall SC_Static, 11878e7d656aSJohn McCall SC_None, 1188c4df4076SDouglas Gregor false, 11890c743277SMike Stump true); 1190a738c25fSJohn McCall StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); 1191aeb0ffd5SMike Stump 11922192fe50SChris Lattner llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); 119367645930SMike Stump 1194a738c25fSJohn McCall llvm::Value *src = GetAddrOfLocalVar(&srcDecl); 1195ad7c5c16SJohn McCall src = Builder.CreateLoad(src); 1196ad7c5c16SJohn McCall src = Builder.CreateBitCast(src, structPtrTy, "block.source"); 119767645930SMike Stump 1198a738c25fSJohn McCall llvm::Value *dst = GetAddrOfLocalVar(&dstDecl); 1199ad7c5c16SJohn McCall dst = Builder.CreateLoad(dst); 1200ad7c5c16SJohn McCall dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest"); 1201aeb0ffd5SMike Stump 1202351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1203aeb0ffd5SMike Stump 1204351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1205351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1206351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1207351762cdSJohn McCall QualType type = variable->getType(); 1208aeb0ffd5SMike Stump 1209351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1210351762cdSJohn McCall if (capture.isConstant()) continue; 1211351762cdSJohn McCall 1212351762cdSJohn McCall const Expr *copyExpr = ci->getCopyExpr(); 121331168b07SJohn McCall BlockFieldFlags flags; 121431168b07SJohn McCall 121531168b07SJohn McCall bool isARCWeakCapture = false; 1216351762cdSJohn McCall 1217351762cdSJohn McCall if (copyExpr) { 1218351762cdSJohn McCall assert(!ci->isByRef()); 1219351762cdSJohn McCall // don't bother computing flags 122031168b07SJohn McCall 1221351762cdSJohn McCall } else if (ci->isByRef()) { 1222351762cdSJohn McCall flags = BLOCK_FIELD_IS_BYREF; 122331168b07SJohn McCall if (type.isObjCGCWeak()) 122431168b07SJohn McCall flags |= BLOCK_FIELD_IS_WEAK; 1225351762cdSJohn McCall 122631168b07SJohn McCall } else if (type->isObjCRetainableType()) { 122731168b07SJohn McCall flags = BLOCK_FIELD_IS_OBJECT; 122831168b07SJohn McCall if (type->isBlockPointerType()) 122931168b07SJohn McCall flags = BLOCK_FIELD_IS_BLOCK; 123031168b07SJohn McCall 123131168b07SJohn McCall // Special rules for ARC captures: 123231168b07SJohn McCall if (getLangOptions().ObjCAutoRefCount) { 123331168b07SJohn McCall Qualifiers qs = type.getQualifiers(); 123431168b07SJohn McCall 123531168b07SJohn McCall // Don't generate special copy logic for a captured object 123631168b07SJohn McCall // unless it's __strong or __weak. 123731168b07SJohn McCall if (!qs.hasStrongOrWeakObjCLifetime()) 123831168b07SJohn McCall continue; 123931168b07SJohn McCall 124031168b07SJohn McCall // Support __weak direct captures. 124131168b07SJohn McCall if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) 124231168b07SJohn McCall isARCWeakCapture = true; 124331168b07SJohn McCall } 124431168b07SJohn McCall } else { 124531168b07SJohn McCall continue; 124631168b07SJohn McCall } 1247351762cdSJohn McCall 1248351762cdSJohn McCall unsigned index = capture.getIndex(); 1249ad7c5c16SJohn McCall llvm::Value *srcField = Builder.CreateStructGEP(src, index); 1250ad7c5c16SJohn McCall llvm::Value *dstField = Builder.CreateStructGEP(dst, index); 1251351762cdSJohn McCall 1252351762cdSJohn McCall // If there's an explicit copy expression, we do that. 1253351762cdSJohn McCall if (copyExpr) { 1254ad7c5c16SJohn McCall EmitSynthesizedCXXCopyCtor(dstField, srcField, copyExpr); 125531168b07SJohn McCall } else if (isARCWeakCapture) { 125631168b07SJohn McCall EmitARCCopyWeak(dstField, srcField); 1257351762cdSJohn McCall } else { 1258351762cdSJohn McCall llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); 1259e3dc1707SJohn McCall srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy); 1260e3dc1707SJohn McCall llvm::Value *dstAddr = Builder.CreateBitCast(dstField, VoidPtrTy); 1261351762cdSJohn McCall Builder.CreateCall3(CGM.getBlockObjectAssign(), dstAddr, srcValue, 126231168b07SJohn McCall llvm::ConstantInt::get(Int32Ty, flags.getBitMask())); 126367645930SMike Stump } 1264e988bdacSFariborz Jahanian } 1265aeb0ffd5SMike Stump 1266ad7c5c16SJohn McCall FinishFunction(); 12670c743277SMike Stump 1268e3dc1707SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); 126997d01d50SMike Stump } 127097d01d50SMike Stump 1271351762cdSJohn McCall llvm::Constant * 1272ad7c5c16SJohn McCall CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { 1273351762cdSJohn McCall ASTContext &C = getContext(); 12740c743277SMike Stump 1275351762cdSJohn McCall FunctionArgList args; 1276a738c25fSJohn McCall ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1277a738c25fSJohn McCall args.push_back(&srcDecl); 12780c743277SMike Stump 12790c743277SMike Stump const CGFunctionInfo &FI = 1280351762cdSJohn McCall CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo()); 12810c743277SMike Stump 1282cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1283cbc2bcafSMike Stump // internal linkage. 12842192fe50SChris Lattner llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false); 12850c743277SMike Stump 12860c743277SMike Stump llvm::Function *Fn = 12870c743277SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1288d6b28fc6SBenjamin Kramer "__destroy_helper_block_", &CGM.getModule()); 12890c743277SMike Stump 12902a7c2194SDevang Patel // Check if we should generate debug info for this block destroy function. 12912a7c2194SDevang Patel if (CGM.getModuleDebugInfo()) 12922a7c2194SDevang Patel DebugInfo = CGM.getModuleDebugInfo(); 12932a7c2194SDevang Patel 12940c743277SMike Stump IdentifierInfo *II 12950c743277SMike Stump = &CGM.getContext().Idents.get("__destroy_helper_block_"); 12960c743277SMike Stump 1297351762cdSJohn McCall FunctionDecl *FD = FunctionDecl::Create(C, C.getTranslationUnitDecl(), 1298dff1930bSAbramo Bagnara SourceLocation(), 1299351762cdSJohn McCall SourceLocation(), II, C.VoidTy, 0, 13008e7d656aSJohn McCall SC_Static, 13018e7d656aSJohn McCall SC_None, 1302c4df4076SDouglas Gregor false, true); 1303a738c25fSJohn McCall StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); 13046f7d9f87SMike Stump 13052192fe50SChris Lattner llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); 130667645930SMike Stump 1307a738c25fSJohn McCall llvm::Value *src = GetAddrOfLocalVar(&srcDecl); 1308ad7c5c16SJohn McCall src = Builder.CreateLoad(src); 1309ad7c5c16SJohn McCall src = Builder.CreateBitCast(src, structPtrTy, "block"); 13106f7d9f87SMike Stump 1311351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1312351762cdSJohn McCall 1313ad7c5c16SJohn McCall CodeGenFunction::RunCleanupsScope cleanups(*this); 1314351762cdSJohn McCall 1315351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1316351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1317351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1318351762cdSJohn McCall QualType type = variable->getType(); 1319351762cdSJohn McCall 1320351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1321351762cdSJohn McCall if (capture.isConstant()) continue; 1322351762cdSJohn McCall 1323ad7c5c16SJohn McCall BlockFieldFlags flags; 1324351762cdSJohn McCall const CXXDestructorDecl *dtor = 0; 1325351762cdSJohn McCall 132631168b07SJohn McCall bool isARCWeakCapture = false; 132731168b07SJohn McCall 1328351762cdSJohn McCall if (ci->isByRef()) { 1329351762cdSJohn McCall flags = BLOCK_FIELD_IS_BYREF; 133031168b07SJohn McCall if (type.isObjCGCWeak()) 133131168b07SJohn McCall flags |= BLOCK_FIELD_IS_WEAK; 133231168b07SJohn McCall } else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) { 133331168b07SJohn McCall if (record->hasTrivialDestructor()) 133431168b07SJohn McCall continue; 1335351762cdSJohn McCall dtor = record->getDestructor(); 133631168b07SJohn McCall } else if (type->isObjCRetainableType()) { 133731168b07SJohn McCall flags = BLOCK_FIELD_IS_OBJECT; 133831168b07SJohn McCall if (type->isBlockPointerType()) 133931168b07SJohn McCall flags = BLOCK_FIELD_IS_BLOCK; 1340351762cdSJohn McCall 134131168b07SJohn McCall // Special rules for ARC captures. 134231168b07SJohn McCall if (getLangOptions().ObjCAutoRefCount) { 134331168b07SJohn McCall Qualifiers qs = type.getQualifiers(); 134431168b07SJohn McCall 134531168b07SJohn McCall // Don't generate special dispose logic for a captured object 134631168b07SJohn McCall // unless it's __strong or __weak. 134731168b07SJohn McCall if (!qs.hasStrongOrWeakObjCLifetime()) 134831168b07SJohn McCall continue; 134931168b07SJohn McCall 135031168b07SJohn McCall // Support __weak direct captures. 135131168b07SJohn McCall if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) 135231168b07SJohn McCall isARCWeakCapture = true; 135331168b07SJohn McCall } 135431168b07SJohn McCall } else { 135531168b07SJohn McCall continue; 135631168b07SJohn McCall } 1357351762cdSJohn McCall 1358351762cdSJohn McCall unsigned index = capture.getIndex(); 1359ad7c5c16SJohn McCall llvm::Value *srcField = Builder.CreateStructGEP(src, index); 1360351762cdSJohn McCall 1361351762cdSJohn McCall // If there's an explicit copy expression, we do that. 1362351762cdSJohn McCall if (dtor) { 1363ad7c5c16SJohn McCall PushDestructorCleanup(dtor, srcField); 1364351762cdSJohn McCall 136531168b07SJohn McCall // If this is a __weak capture, emit the release directly. 136631168b07SJohn McCall } else if (isARCWeakCapture) { 136731168b07SJohn McCall EmitARCDestroyWeak(srcField); 136831168b07SJohn McCall 1369351762cdSJohn McCall // Otherwise we call _Block_object_dispose. It wouldn't be too 1370351762cdSJohn McCall // hard to just emit this as a cleanup if we wanted to make sure 1371351762cdSJohn McCall // that things were done in reverse. 1372351762cdSJohn McCall } else { 1373351762cdSJohn McCall llvm::Value *value = Builder.CreateLoad(srcField); 1374e3dc1707SJohn McCall value = Builder.CreateBitCast(value, VoidPtrTy); 1375351762cdSJohn McCall BuildBlockRelease(value, flags); 13766f7d9f87SMike Stump } 13776f7d9f87SMike Stump } 1378351762cdSJohn McCall 1379351762cdSJohn McCall cleanups.ForceCleanup(); 13806f7d9f87SMike Stump 1381ad7c5c16SJohn McCall FinishFunction(); 13820c743277SMike Stump 1383e3dc1707SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); 13840c743277SMike Stump } 13850c743277SMike Stump 1386f9b056b0SJohn McCall namespace { 1387f9b056b0SJohn McCall 1388f9b056b0SJohn McCall /// Emits the copy/dispose helper functions for a __block object of id type. 1389f9b056b0SJohn McCall class ObjectByrefHelpers : public CodeGenModule::ByrefHelpers { 1390f9b056b0SJohn McCall BlockFieldFlags Flags; 1391f9b056b0SJohn McCall 1392f9b056b0SJohn McCall public: 1393f9b056b0SJohn McCall ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags) 1394f9b056b0SJohn McCall : ByrefHelpers(alignment), Flags(flags) {} 1395f9b056b0SJohn McCall 13967c623641SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 13977c623641SJohn McCall llvm::Value *srcField) { 1398f9b056b0SJohn McCall destField = CGF.Builder.CreateBitCast(destField, CGF.VoidPtrTy); 1399f9b056b0SJohn McCall 1400f9b056b0SJohn McCall srcField = CGF.Builder.CreateBitCast(srcField, CGF.VoidPtrPtrTy); 1401f9b056b0SJohn McCall llvm::Value *srcValue = CGF.Builder.CreateLoad(srcField); 1402f9b056b0SJohn McCall 1403f9b056b0SJohn McCall unsigned flags = (Flags | BLOCK_BYREF_CALLER).getBitMask(); 1404f9b056b0SJohn McCall 1405f9b056b0SJohn McCall llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); 1406f9b056b0SJohn McCall llvm::Value *fn = CGF.CGM.getBlockObjectAssign(); 1407f9b056b0SJohn McCall CGF.Builder.CreateCall3(fn, destField, srcValue, flagsVal); 1408f9b056b0SJohn McCall } 1409f9b056b0SJohn McCall 1410f9b056b0SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1411f9b056b0SJohn McCall field = CGF.Builder.CreateBitCast(field, CGF.Int8PtrTy->getPointerTo(0)); 1412f9b056b0SJohn McCall llvm::Value *value = CGF.Builder.CreateLoad(field); 1413f9b056b0SJohn McCall 1414f9b056b0SJohn McCall CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER); 1415f9b056b0SJohn McCall } 1416f9b056b0SJohn McCall 1417f9b056b0SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 1418f9b056b0SJohn McCall id.AddInteger(Flags.getBitMask()); 1419f9b056b0SJohn McCall } 1420f9b056b0SJohn McCall }; 1421f9b056b0SJohn McCall 142231168b07SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __weak variable. 142331168b07SJohn McCall class ARCWeakByrefHelpers : public CodeGenModule::ByrefHelpers { 142431168b07SJohn McCall public: 142531168b07SJohn McCall ARCWeakByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {} 142631168b07SJohn McCall 142731168b07SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 142831168b07SJohn McCall llvm::Value *srcField) { 142931168b07SJohn McCall CGF.EmitARCMoveWeak(destField, srcField); 143031168b07SJohn McCall } 143131168b07SJohn McCall 143231168b07SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 143331168b07SJohn McCall CGF.EmitARCDestroyWeak(field); 143431168b07SJohn McCall } 143531168b07SJohn McCall 143631168b07SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 143731168b07SJohn McCall // 0 is distinguishable from all pointers and byref flags 143831168b07SJohn McCall id.AddInteger(0); 143931168b07SJohn McCall } 144031168b07SJohn McCall }; 144131168b07SJohn McCall 144231168b07SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __strong variable 144331168b07SJohn McCall /// that's not of block-pointer type. 144431168b07SJohn McCall class ARCStrongByrefHelpers : public CodeGenModule::ByrefHelpers { 144531168b07SJohn McCall public: 144631168b07SJohn McCall ARCStrongByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {} 144731168b07SJohn McCall 144831168b07SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 144931168b07SJohn McCall llvm::Value *srcField) { 145031168b07SJohn McCall // Do a "move" by copying the value and then zeroing out the old 145131168b07SJohn McCall // variable. 145231168b07SJohn McCall 14533a237aa3SJohn McCall llvm::LoadInst *value = CGF.Builder.CreateLoad(srcField); 14543a237aa3SJohn McCall value->setAlignment(Alignment.getQuantity()); 14553a237aa3SJohn McCall 145631168b07SJohn McCall llvm::Value *null = 145731168b07SJohn McCall llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType())); 14583a237aa3SJohn McCall 14593a237aa3SJohn McCall llvm::StoreInst *store = CGF.Builder.CreateStore(value, destField); 14603a237aa3SJohn McCall store->setAlignment(Alignment.getQuantity()); 14613a237aa3SJohn McCall 14623a237aa3SJohn McCall store = CGF.Builder.CreateStore(null, srcField); 14633a237aa3SJohn McCall store->setAlignment(Alignment.getQuantity()); 146431168b07SJohn McCall } 146531168b07SJohn McCall 146631168b07SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 14673a237aa3SJohn McCall llvm::LoadInst *value = CGF.Builder.CreateLoad(field); 14683a237aa3SJohn McCall value->setAlignment(Alignment.getQuantity()); 14693a237aa3SJohn McCall 147031168b07SJohn McCall CGF.EmitARCRelease(value, /*precise*/ false); 147131168b07SJohn McCall } 147231168b07SJohn McCall 147331168b07SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 147431168b07SJohn McCall // 1 is distinguishable from all pointers and byref flags 147531168b07SJohn McCall id.AddInteger(1); 147631168b07SJohn McCall } 147731168b07SJohn McCall }; 147831168b07SJohn McCall 14793a237aa3SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __strong 14803a237aa3SJohn McCall /// variable that's of block-pointer type. 14813a237aa3SJohn McCall class ARCStrongBlockByrefHelpers : public CodeGenModule::ByrefHelpers { 14823a237aa3SJohn McCall public: 14833a237aa3SJohn McCall ARCStrongBlockByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {} 14843a237aa3SJohn McCall 14853a237aa3SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 14863a237aa3SJohn McCall llvm::Value *srcField) { 14873a237aa3SJohn McCall // Do the copy with objc_retainBlock; that's all that 14883a237aa3SJohn McCall // _Block_object_assign would do anyway, and we'd have to pass the 14893a237aa3SJohn McCall // right arguments to make sure it doesn't get no-op'ed. 14903a237aa3SJohn McCall llvm::LoadInst *oldValue = CGF.Builder.CreateLoad(srcField); 14913a237aa3SJohn McCall oldValue->setAlignment(Alignment.getQuantity()); 14923a237aa3SJohn McCall 14933a237aa3SJohn McCall llvm::Value *copy = CGF.EmitARCRetainBlock(oldValue, /*mandatory*/ true); 14943a237aa3SJohn McCall 14953a237aa3SJohn McCall llvm::StoreInst *store = CGF.Builder.CreateStore(copy, destField); 14963a237aa3SJohn McCall store->setAlignment(Alignment.getQuantity()); 14973a237aa3SJohn McCall } 14983a237aa3SJohn McCall 14993a237aa3SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 15003a237aa3SJohn McCall llvm::LoadInst *value = CGF.Builder.CreateLoad(field); 15013a237aa3SJohn McCall value->setAlignment(Alignment.getQuantity()); 15023a237aa3SJohn McCall 15033a237aa3SJohn McCall CGF.EmitARCRelease(value, /*precise*/ false); 15043a237aa3SJohn McCall } 15053a237aa3SJohn McCall 15063a237aa3SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 15073a237aa3SJohn McCall // 2 is distinguishable from all pointers and byref flags 15083a237aa3SJohn McCall id.AddInteger(2); 15093a237aa3SJohn McCall } 15103a237aa3SJohn McCall }; 15113a237aa3SJohn McCall 1512f9b056b0SJohn McCall /// Emits the copy/dispose helpers for a __block variable with a 1513f9b056b0SJohn McCall /// nontrivial copy constructor or destructor. 1514f9b056b0SJohn McCall class CXXByrefHelpers : public CodeGenModule::ByrefHelpers { 1515f9b056b0SJohn McCall QualType VarType; 1516f9b056b0SJohn McCall const Expr *CopyExpr; 1517f9b056b0SJohn McCall 1518f9b056b0SJohn McCall public: 1519f9b056b0SJohn McCall CXXByrefHelpers(CharUnits alignment, QualType type, 1520f9b056b0SJohn McCall const Expr *copyExpr) 1521f9b056b0SJohn McCall : ByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {} 1522f9b056b0SJohn McCall 1523f9b056b0SJohn McCall bool needsCopy() const { return CopyExpr != 0; } 1524f9b056b0SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 1525f9b056b0SJohn McCall llvm::Value *srcField) { 1526f9b056b0SJohn McCall if (!CopyExpr) return; 1527f9b056b0SJohn McCall CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr); 1528f9b056b0SJohn McCall } 1529f9b056b0SJohn McCall 1530f9b056b0SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1531f9b056b0SJohn McCall EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin(); 1532f9b056b0SJohn McCall CGF.PushDestructorCleanup(VarType, field); 1533f9b056b0SJohn McCall CGF.PopCleanupBlocks(cleanupDepth); 1534f9b056b0SJohn McCall } 1535f9b056b0SJohn McCall 1536f9b056b0SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 1537f9b056b0SJohn McCall id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr()); 1538f9b056b0SJohn McCall } 1539f9b056b0SJohn McCall }; 1540f9b056b0SJohn McCall } // end anonymous namespace 1541f9b056b0SJohn McCall 1542f9b056b0SJohn McCall static llvm::Constant * 1543f9b056b0SJohn McCall generateByrefCopyHelper(CodeGenFunction &CGF, 15442192fe50SChris Lattner llvm::StructType &byrefType, 1545f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &byrefInfo) { 1546f9b056b0SJohn McCall ASTContext &Context = CGF.getContext(); 1547f9b056b0SJohn McCall 1548f9b056b0SJohn McCall QualType R = Context.VoidTy; 1549ee2a5ee5SMike Stump 1550a738c25fSJohn McCall FunctionArgList args; 1551f9b056b0SJohn McCall ImplicitParamDecl dst(0, SourceLocation(), 0, Context.VoidPtrTy); 1552a738c25fSJohn McCall args.push_back(&dst); 1553f89230d9SMike Stump 1554f9b056b0SJohn McCall ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); 1555a738c25fSJohn McCall args.push_back(&src); 1556ee2a5ee5SMike Stump 1557ee2a5ee5SMike Stump const CGFunctionInfo &FI = 1558f9b056b0SJohn McCall CGF.CGM.getTypes().getFunctionInfo(R, args, FunctionType::ExtInfo()); 1559ee2a5ee5SMike Stump 1560f9b056b0SJohn McCall CodeGenTypes &Types = CGF.CGM.getTypes(); 15612192fe50SChris Lattner llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); 1562ee2a5ee5SMike Stump 1563cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1564cbc2bcafSMike Stump // internal linkage. 1565ee2a5ee5SMike Stump llvm::Function *Fn = 1566ee2a5ee5SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1567f9b056b0SJohn McCall "__Block_byref_object_copy_", &CGF.CGM.getModule()); 1568ee2a5ee5SMike Stump 1569ee2a5ee5SMike Stump IdentifierInfo *II 1570f9b056b0SJohn McCall = &Context.Idents.get("__Block_byref_object_copy_"); 1571ee2a5ee5SMike Stump 1572f9b056b0SJohn McCall FunctionDecl *FD = FunctionDecl::Create(Context, 1573f9b056b0SJohn McCall Context.getTranslationUnitDecl(), 1574dff1930bSAbramo Bagnara SourceLocation(), 157560ed5604SArgyrios Kyrtzidis SourceLocation(), II, R, 0, 15768e7d656aSJohn McCall SC_Static, 15778e7d656aSJohn McCall SC_None, 1578c4df4076SDouglas Gregor false, true); 157931168b07SJohn McCall 1580f9b056b0SJohn McCall CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); 1581f9b056b0SJohn McCall 1582f9b056b0SJohn McCall if (byrefInfo.needsCopy()) { 15832192fe50SChris Lattner llvm::Type *byrefPtrType = byrefType.getPointerTo(0); 1584f89230d9SMike Stump 1585f89230d9SMike Stump // dst->x 1586f9b056b0SJohn McCall llvm::Value *destField = CGF.GetAddrOfLocalVar(&dst); 1587f9b056b0SJohn McCall destField = CGF.Builder.CreateLoad(destField); 1588f9b056b0SJohn McCall destField = CGF.Builder.CreateBitCast(destField, byrefPtrType); 1589f9b056b0SJohn McCall destField = CGF.Builder.CreateStructGEP(destField, 6, "x"); 1590f89230d9SMike Stump 1591f89230d9SMike Stump // src->x 1592f9b056b0SJohn McCall llvm::Value *srcField = CGF.GetAddrOfLocalVar(&src); 1593f9b056b0SJohn McCall srcField = CGF.Builder.CreateLoad(srcField); 1594f9b056b0SJohn McCall srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType); 1595f9b056b0SJohn McCall srcField = CGF.Builder.CreateStructGEP(srcField, 6, "x"); 159650198098SFariborz Jahanian 1597f9b056b0SJohn McCall byrefInfo.emitCopy(CGF, destField, srcField); 159850198098SFariborz Jahanian } 1599f89230d9SMike Stump 1600f9b056b0SJohn McCall CGF.FinishFunction(); 1601ee2a5ee5SMike Stump 1602f9b056b0SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); 1603ee2a5ee5SMike Stump } 1604ee2a5ee5SMike Stump 1605f9b056b0SJohn McCall /// Build the copy helper for a __block variable. 1606f9b056b0SJohn McCall static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM, 16072192fe50SChris Lattner llvm::StructType &byrefType, 1608f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &info) { 1609f9b056b0SJohn McCall CodeGenFunction CGF(CGM); 1610f9b056b0SJohn McCall return generateByrefCopyHelper(CGF, byrefType, info); 1611f9b056b0SJohn McCall } 1612f9b056b0SJohn McCall 1613f9b056b0SJohn McCall /// Generate code for a __block variable's dispose helper. 1614f9b056b0SJohn McCall static llvm::Constant * 1615f9b056b0SJohn McCall generateByrefDisposeHelper(CodeGenFunction &CGF, 16162192fe50SChris Lattner llvm::StructType &byrefType, 1617f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &byrefInfo) { 1618f9b056b0SJohn McCall ASTContext &Context = CGF.getContext(); 1619f9b056b0SJohn McCall QualType R = Context.VoidTy; 1620ee2a5ee5SMike Stump 1621a738c25fSJohn McCall FunctionArgList args; 1622f9b056b0SJohn McCall ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); 1623a738c25fSJohn McCall args.push_back(&src); 1624ee2a5ee5SMike Stump 1625ee2a5ee5SMike Stump const CGFunctionInfo &FI = 1626f9b056b0SJohn McCall CGF.CGM.getTypes().getFunctionInfo(R, args, FunctionType::ExtInfo()); 1627ee2a5ee5SMike Stump 1628f9b056b0SJohn McCall CodeGenTypes &Types = CGF.CGM.getTypes(); 16292192fe50SChris Lattner llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); 1630ee2a5ee5SMike Stump 1631cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1632cbc2bcafSMike Stump // internal linkage. 1633ee2a5ee5SMike Stump llvm::Function *Fn = 1634ee2a5ee5SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 163550198098SFariborz Jahanian "__Block_byref_object_dispose_", 1636f9b056b0SJohn McCall &CGF.CGM.getModule()); 1637ee2a5ee5SMike Stump 1638ee2a5ee5SMike Stump IdentifierInfo *II 1639f9b056b0SJohn McCall = &Context.Idents.get("__Block_byref_object_dispose_"); 1640ee2a5ee5SMike Stump 1641f9b056b0SJohn McCall FunctionDecl *FD = FunctionDecl::Create(Context, 1642f9b056b0SJohn McCall Context.getTranslationUnitDecl(), 1643dff1930bSAbramo Bagnara SourceLocation(), 164460ed5604SArgyrios Kyrtzidis SourceLocation(), II, R, 0, 16458e7d656aSJohn McCall SC_Static, 16468e7d656aSJohn McCall SC_None, 1647c4df4076SDouglas Gregor false, true); 1648f9b056b0SJohn McCall CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); 1649fbe25dd1SMike Stump 1650f9b056b0SJohn McCall if (byrefInfo.needsDispose()) { 1651f9b056b0SJohn McCall llvm::Value *V = CGF.GetAddrOfLocalVar(&src); 1652f9b056b0SJohn McCall V = CGF.Builder.CreateLoad(V); 1653f9b056b0SJohn McCall V = CGF.Builder.CreateBitCast(V, byrefType.getPointerTo(0)); 1654f9b056b0SJohn McCall V = CGF.Builder.CreateStructGEP(V, 6, "x"); 1655ad7c5c16SJohn McCall 1656f9b056b0SJohn McCall byrefInfo.emitDispose(CGF, V); 1657f9b056b0SJohn McCall } 1658ad7c5c16SJohn McCall 1659f9b056b0SJohn McCall CGF.FinishFunction(); 1660f9b056b0SJohn McCall 1661f9b056b0SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); 1662f9b056b0SJohn McCall } 1663f9b056b0SJohn McCall 1664f9b056b0SJohn McCall /// Build the dispose helper for a __block variable. 1665f9b056b0SJohn McCall static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM, 16662192fe50SChris Lattner llvm::StructType &byrefType, 1667f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &info) { 1668f9b056b0SJohn McCall CodeGenFunction CGF(CGM); 1669f9b056b0SJohn McCall return generateByrefDisposeHelper(CGF, byrefType, info); 1670f9b056b0SJohn McCall } 1671f9b056b0SJohn McCall 1672f9b056b0SJohn McCall /// 1673f9b056b0SJohn McCall template <class T> static T *buildByrefHelpers(CodeGenModule &CGM, 16742192fe50SChris Lattner llvm::StructType &byrefTy, 1675f9b056b0SJohn McCall T &byrefInfo) { 1676f9b056b0SJohn McCall // Increase the field's alignment to be at least pointer alignment, 1677f9b056b0SJohn McCall // since the layout of the byref struct will guarantee at least that. 1678f9b056b0SJohn McCall byrefInfo.Alignment = std::max(byrefInfo.Alignment, 1679f9b056b0SJohn McCall CharUnits::fromQuantity(CGM.PointerAlignInBytes)); 1680f9b056b0SJohn McCall 1681f9b056b0SJohn McCall llvm::FoldingSetNodeID id; 1682f9b056b0SJohn McCall byrefInfo.Profile(id); 1683f9b056b0SJohn McCall 1684f9b056b0SJohn McCall void *insertPos; 1685f9b056b0SJohn McCall CodeGenModule::ByrefHelpers *node 1686f9b056b0SJohn McCall = CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos); 1687f9b056b0SJohn McCall if (node) return static_cast<T*>(node); 1688f9b056b0SJohn McCall 1689f9b056b0SJohn McCall byrefInfo.CopyHelper = buildByrefCopyHelper(CGM, byrefTy, byrefInfo); 1690f9b056b0SJohn McCall byrefInfo.DisposeHelper = buildByrefDisposeHelper(CGM, byrefTy, byrefInfo); 1691f9b056b0SJohn McCall 1692f9b056b0SJohn McCall T *copy = new (CGM.getContext()) T(byrefInfo); 1693f9b056b0SJohn McCall CGM.ByrefHelpersCache.InsertNode(copy, insertPos); 1694f9b056b0SJohn McCall return copy; 1695f9b056b0SJohn McCall } 1696f9b056b0SJohn McCall 1697f9b056b0SJohn McCall CodeGenModule::ByrefHelpers * 16982192fe50SChris Lattner CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType, 1699f9b056b0SJohn McCall const AutoVarEmission &emission) { 1700f9b056b0SJohn McCall const VarDecl &var = *emission.Variable; 1701f9b056b0SJohn McCall QualType type = var.getType(); 1702f9b056b0SJohn McCall 1703f9b056b0SJohn McCall if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) { 1704f9b056b0SJohn McCall const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var); 1705f9b056b0SJohn McCall if (!copyExpr && record->hasTrivialDestructor()) return 0; 1706f9b056b0SJohn McCall 1707f9b056b0SJohn McCall CXXByrefHelpers byrefInfo(emission.Alignment, type, copyExpr); 1708f9b056b0SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 1709f9b056b0SJohn McCall } 1710f9b056b0SJohn McCall 171131168b07SJohn McCall // Otherwise, if we don't have a retainable type, there's nothing to do. 171231168b07SJohn McCall // that the runtime does extra copies. 171331168b07SJohn McCall if (!type->isObjCRetainableType()) return 0; 171431168b07SJohn McCall 171531168b07SJohn McCall Qualifiers qs = type.getQualifiers(); 171631168b07SJohn McCall 171731168b07SJohn McCall // If we have lifetime, that dominates. 171831168b07SJohn McCall if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) { 171931168b07SJohn McCall assert(getLangOptions().ObjCAutoRefCount); 172031168b07SJohn McCall 172131168b07SJohn McCall switch (lifetime) { 172231168b07SJohn McCall case Qualifiers::OCL_None: llvm_unreachable("impossible"); 172331168b07SJohn McCall 172431168b07SJohn McCall // These are just bits as far as the runtime is concerned. 172531168b07SJohn McCall case Qualifiers::OCL_ExplicitNone: 172631168b07SJohn McCall case Qualifiers::OCL_Autoreleasing: 172731168b07SJohn McCall return 0; 172831168b07SJohn McCall 172931168b07SJohn McCall // Tell the runtime that this is ARC __weak, called by the 173031168b07SJohn McCall // byref routines. 173131168b07SJohn McCall case Qualifiers::OCL_Weak: { 173231168b07SJohn McCall ARCWeakByrefHelpers byrefInfo(emission.Alignment); 173331168b07SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 173431168b07SJohn McCall } 173531168b07SJohn McCall 173631168b07SJohn McCall // ARC __strong __block variables need to be retained. 173731168b07SJohn McCall case Qualifiers::OCL_Strong: 17383a237aa3SJohn McCall // Block pointers need to be copied, and there's no direct 17393a237aa3SJohn McCall // transfer possible. 174031168b07SJohn McCall if (type->isBlockPointerType()) { 17413a237aa3SJohn McCall ARCStrongBlockByrefHelpers byrefInfo(emission.Alignment); 174231168b07SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 174331168b07SJohn McCall 174431168b07SJohn McCall // Otherwise, we transfer ownership of the retain from the stack 174531168b07SJohn McCall // to the heap. 174631168b07SJohn McCall } else { 174731168b07SJohn McCall ARCStrongByrefHelpers byrefInfo(emission.Alignment); 174831168b07SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 174931168b07SJohn McCall } 175031168b07SJohn McCall } 175131168b07SJohn McCall llvm_unreachable("fell out of lifetime switch!"); 175231168b07SJohn McCall } 175331168b07SJohn McCall 1754f9b056b0SJohn McCall BlockFieldFlags flags; 1755f9b056b0SJohn McCall if (type->isBlockPointerType()) { 1756f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_BLOCK; 1757f9b056b0SJohn McCall } else if (CGM.getContext().isObjCNSObjectType(type) || 1758f9b056b0SJohn McCall type->isObjCObjectPointerType()) { 1759f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_OBJECT; 1760ad7c5c16SJohn McCall } else { 1761f9b056b0SJohn McCall return 0; 1762ee2a5ee5SMike Stump } 1763ee2a5ee5SMike Stump 1764f9b056b0SJohn McCall if (type.isObjCGCWeak()) 1765f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_WEAK; 1766ad7c5c16SJohn McCall 1767f9b056b0SJohn McCall ObjectByrefHelpers byrefInfo(emission.Alignment, flags); 1768f9b056b0SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 1769ee2a5ee5SMike Stump } 1770ee2a5ee5SMike Stump 177173064870SJohn McCall unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const { 177273064870SJohn McCall assert(ByRefValueInfo.count(VD) && "Did not find value!"); 177373064870SJohn McCall 177473064870SJohn McCall return ByRefValueInfo.find(VD)->second.second; 177573064870SJohn McCall } 177673064870SJohn McCall 177773064870SJohn McCall llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr, 177873064870SJohn McCall const VarDecl *V) { 177973064870SJohn McCall llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding"); 178073064870SJohn McCall Loc = Builder.CreateLoad(Loc); 178173064870SJohn McCall Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V), 178273064870SJohn McCall V->getNameAsString()); 178373064870SJohn McCall return Loc; 178473064870SJohn McCall } 178573064870SJohn McCall 178673064870SJohn McCall /// BuildByRefType - This routine changes a __block variable declared as T x 178773064870SJohn McCall /// into: 178873064870SJohn McCall /// 178973064870SJohn McCall /// struct { 179073064870SJohn McCall /// void *__isa; 179173064870SJohn McCall /// void *__forwarding; 179273064870SJohn McCall /// int32_t __flags; 179373064870SJohn McCall /// int32_t __size; 179473064870SJohn McCall /// void *__copy_helper; // only if needed 179573064870SJohn McCall /// void *__destroy_helper; // only if needed 179673064870SJohn McCall /// char padding[X]; // only if needed 179773064870SJohn McCall /// T x; 179873064870SJohn McCall /// } x 179973064870SJohn McCall /// 18002192fe50SChris Lattner llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) { 18012192fe50SChris Lattner std::pair<llvm::Type *, unsigned> &Info = ByRefValueInfo[D]; 180273064870SJohn McCall if (Info.first) 180373064870SJohn McCall return Info.first; 180473064870SJohn McCall 180573064870SJohn McCall QualType Ty = D->getType(); 180673064870SJohn McCall 18070e62c1ccSChris Lattner SmallVector<llvm::Type *, 8> types; 180873064870SJohn McCall 1809a5f58b05SChris Lattner llvm::StructType *ByRefType = 18105ec04a51SChris Lattner llvm::StructType::create(getLLVMContext(), 1811a5f58b05SChris Lattner "struct.__block_byref_" + D->getNameAsString()); 181273064870SJohn McCall 181373064870SJohn McCall // void *__isa; 18149dc0db21SJohn McCall types.push_back(Int8PtrTy); 181573064870SJohn McCall 181673064870SJohn McCall // void *__forwarding; 1817a5f58b05SChris Lattner types.push_back(llvm::PointerType::getUnqual(ByRefType)); 181873064870SJohn McCall 181973064870SJohn McCall // int32_t __flags; 18209dc0db21SJohn McCall types.push_back(Int32Ty); 182173064870SJohn McCall 182273064870SJohn McCall // int32_t __size; 18239dc0db21SJohn McCall types.push_back(Int32Ty); 182473064870SJohn McCall 182573064870SJohn McCall bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty); 182673064870SJohn McCall if (HasCopyAndDispose) { 182773064870SJohn McCall /// void *__copy_helper; 18289dc0db21SJohn McCall types.push_back(Int8PtrTy); 182973064870SJohn McCall 183073064870SJohn McCall /// void *__destroy_helper; 18319dc0db21SJohn McCall types.push_back(Int8PtrTy); 183273064870SJohn McCall } 183373064870SJohn McCall 183473064870SJohn McCall bool Packed = false; 183573064870SJohn McCall CharUnits Align = getContext().getDeclAlign(D); 183673064870SJohn McCall if (Align > getContext().toCharUnitsFromBits(Target.getPointerAlign(0))) { 183773064870SJohn McCall // We have to insert padding. 183873064870SJohn McCall 183973064870SJohn McCall // The struct above has 2 32-bit integers. 184073064870SJohn McCall unsigned CurrentOffsetInBytes = 4 * 2; 184173064870SJohn McCall 184273064870SJohn McCall // And either 2 or 4 pointers. 184373064870SJohn McCall CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) * 184473064870SJohn McCall CGM.getTargetData().getTypeAllocSize(Int8PtrTy); 184573064870SJohn McCall 184673064870SJohn McCall // Align the offset. 184773064870SJohn McCall unsigned AlignedOffsetInBytes = 184873064870SJohn McCall llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity()); 184973064870SJohn McCall 185073064870SJohn McCall unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes; 185173064870SJohn McCall if (NumPaddingBytes > 0) { 1852a5f58b05SChris Lattner llvm::Type *Ty = llvm::Type::getInt8Ty(getLLVMContext()); 185373064870SJohn McCall // FIXME: We need a sema error for alignment larger than the minimum of 18549dc0db21SJohn McCall // the maximal stack alignment and the alignment of malloc on the system. 185573064870SJohn McCall if (NumPaddingBytes > 1) 185673064870SJohn McCall Ty = llvm::ArrayType::get(Ty, NumPaddingBytes); 185773064870SJohn McCall 18589dc0db21SJohn McCall types.push_back(Ty); 185973064870SJohn McCall 186073064870SJohn McCall // We want a packed struct. 186173064870SJohn McCall Packed = true; 186273064870SJohn McCall } 186373064870SJohn McCall } 186473064870SJohn McCall 186573064870SJohn McCall // T x; 18669dc0db21SJohn McCall types.push_back(ConvertTypeForMem(Ty)); 186773064870SJohn McCall 1868a5f58b05SChris Lattner ByRefType->setBody(types, Packed); 186973064870SJohn McCall 1870a5f58b05SChris Lattner Info.first = ByRefType; 187173064870SJohn McCall 18729dc0db21SJohn McCall Info.second = types.size() - 1; 187373064870SJohn McCall 187473064870SJohn McCall return Info.first; 187573064870SJohn McCall } 187673064870SJohn McCall 187773064870SJohn McCall /// Initialize the structural components of a __block variable, i.e. 187873064870SJohn McCall /// everything but the actual object. 187973064870SJohn McCall void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { 1880f9b056b0SJohn McCall // Find the address of the local. 1881f9b056b0SJohn McCall llvm::Value *addr = emission.Address; 188273064870SJohn McCall 1883f9b056b0SJohn McCall // That's an alloca of the byref structure type. 18842192fe50SChris Lattner llvm::StructType *byrefType = cast<llvm::StructType>( 1885f9b056b0SJohn McCall cast<llvm::PointerType>(addr->getType())->getElementType()); 1886f9b056b0SJohn McCall 1887f9b056b0SJohn McCall // Build the byref helpers if necessary. This is null if we don't need any. 1888f9b056b0SJohn McCall CodeGenModule::ByrefHelpers *helpers = 1889f9b056b0SJohn McCall buildByrefHelpers(*byrefType, emission); 189073064870SJohn McCall 189173064870SJohn McCall const VarDecl &D = *emission.Variable; 189273064870SJohn McCall QualType type = D.getType(); 189373064870SJohn McCall 1894f9b056b0SJohn McCall llvm::Value *V; 189573064870SJohn McCall 189673064870SJohn McCall // Initialize the 'isa', which is just 0 or 1. 189773064870SJohn McCall int isa = 0; 1898f9b056b0SJohn McCall if (type.isObjCGCWeak()) 189973064870SJohn McCall isa = 1; 190073064870SJohn McCall V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa"); 190173064870SJohn McCall Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa")); 190273064870SJohn McCall 190373064870SJohn McCall // Store the address of the variable into its own forwarding pointer. 190473064870SJohn McCall Builder.CreateStore(addr, 190573064870SJohn McCall Builder.CreateStructGEP(addr, 1, "byref.forwarding")); 190673064870SJohn McCall 190773064870SJohn McCall // Blocks ABI: 190873064870SJohn McCall // c) the flags field is set to either 0 if no helper functions are 190973064870SJohn McCall // needed or BLOCK_HAS_COPY_DISPOSE if they are, 191073064870SJohn McCall BlockFlags flags; 1911f9b056b0SJohn McCall if (helpers) flags |= BLOCK_HAS_COPY_DISPOSE; 191273064870SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()), 191373064870SJohn McCall Builder.CreateStructGEP(addr, 2, "byref.flags")); 191473064870SJohn McCall 1915f9b056b0SJohn McCall CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType); 1916f9b056b0SJohn McCall V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity()); 191773064870SJohn McCall Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size")); 191873064870SJohn McCall 1919f9b056b0SJohn McCall if (helpers) { 192073064870SJohn McCall llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4); 1921f9b056b0SJohn McCall Builder.CreateStore(helpers->CopyHelper, copy_helper); 192273064870SJohn McCall 192373064870SJohn McCall llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5); 1924f9b056b0SJohn McCall Builder.CreateStore(helpers->DisposeHelper, destroy_helper); 192573064870SJohn McCall } 192673064870SJohn McCall } 192773064870SJohn McCall 1928ad7c5c16SJohn McCall void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) { 1929900546d2SDaniel Dunbar llvm::Value *F = CGM.getBlockObjectDispose(); 1930fbe25dd1SMike Stump llvm::Value *N; 1931ad7c5c16SJohn McCall V = Builder.CreateBitCast(V, Int8PtrTy); 1932ad7c5c16SJohn McCall N = llvm::ConstantInt::get(Int32Ty, flags.getBitMask()); 1933626aecc4SMike Stump Builder.CreateCall2(F, V, N); 1934626aecc4SMike Stump } 193573064870SJohn McCall 193673064870SJohn McCall namespace { 193773064870SJohn McCall struct CallBlockRelease : EHScopeStack::Cleanup { 193873064870SJohn McCall llvm::Value *Addr; 193973064870SJohn McCall CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {} 194073064870SJohn McCall 194130317fdaSJohn McCall void Emit(CodeGenFunction &CGF, Flags flags) { 194231168b07SJohn McCall // Should we be passing FIELD_IS_WEAK here? 194373064870SJohn McCall CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF); 194473064870SJohn McCall } 194573064870SJohn McCall }; 194673064870SJohn McCall } 194773064870SJohn McCall 194873064870SJohn McCall /// Enter a cleanup to destroy a __block variable. Note that this 194973064870SJohn McCall /// cleanup should be a no-op if the variable hasn't left the stack 195073064870SJohn McCall /// yet; if a cleanup is required for the variable itself, that needs 195173064870SJohn McCall /// to be done externally. 195273064870SJohn McCall void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) { 195373064870SJohn McCall // We don't enter this cleanup if we're in pure-GC mode. 195479a91418SDouglas Gregor if (CGM.getLangOptions().getGC() == LangOptions::GCOnly) 195573064870SJohn McCall return; 195673064870SJohn McCall 195773064870SJohn McCall EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address); 195873064870SJohn McCall } 19597959fee2SJohn McCall 19607959fee2SJohn McCall /// Adjust the declaration of something from the blocks API. 19617959fee2SJohn McCall static void configureBlocksRuntimeObject(CodeGenModule &CGM, 19627959fee2SJohn McCall llvm::Constant *C) { 19637959fee2SJohn McCall if (!CGM.getLangOptions().BlocksRuntimeOptional) return; 19647959fee2SJohn McCall 19657959fee2SJohn McCall llvm::GlobalValue *GV = cast<llvm::GlobalValue>(C->stripPointerCasts()); 19667959fee2SJohn McCall if (GV->isDeclaration() && 19677959fee2SJohn McCall GV->getLinkage() == llvm::GlobalValue::ExternalLinkage) 19687959fee2SJohn McCall GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 19697959fee2SJohn McCall } 19707959fee2SJohn McCall 19717959fee2SJohn McCall llvm::Constant *CodeGenModule::getBlockObjectDispose() { 19727959fee2SJohn McCall if (BlockObjectDispose) 19737959fee2SJohn McCall return BlockObjectDispose; 19747959fee2SJohn McCall 19757959fee2SJohn McCall llvm::Type *args[] = { Int8PtrTy, Int32Ty }; 19767959fee2SJohn McCall llvm::FunctionType *fty 19777959fee2SJohn McCall = llvm::FunctionType::get(VoidTy, args, false); 19787959fee2SJohn McCall BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose"); 19797959fee2SJohn McCall configureBlocksRuntimeObject(*this, BlockObjectDispose); 19807959fee2SJohn McCall return BlockObjectDispose; 19817959fee2SJohn McCall } 19827959fee2SJohn McCall 19837959fee2SJohn McCall llvm::Constant *CodeGenModule::getBlockObjectAssign() { 19847959fee2SJohn McCall if (BlockObjectAssign) 19857959fee2SJohn McCall return BlockObjectAssign; 19867959fee2SJohn McCall 19877959fee2SJohn McCall llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty }; 19887959fee2SJohn McCall llvm::FunctionType *fty 19897959fee2SJohn McCall = llvm::FunctionType::get(VoidTy, args, false); 19907959fee2SJohn McCall BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign"); 19917959fee2SJohn McCall configureBlocksRuntimeObject(*this, BlockObjectAssign); 19927959fee2SJohn McCall return BlockObjectAssign; 19937959fee2SJohn McCall } 19947959fee2SJohn McCall 19957959fee2SJohn McCall llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() { 19967959fee2SJohn McCall if (NSConcreteGlobalBlock) 19977959fee2SJohn McCall return NSConcreteGlobalBlock; 19987959fee2SJohn McCall 19997959fee2SJohn McCall NSConcreteGlobalBlock = GetOrCreateLLVMGlobal("_NSConcreteGlobalBlock", 20007959fee2SJohn McCall Int8PtrTy->getPointerTo(), 0); 20017959fee2SJohn McCall configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock); 20027959fee2SJohn McCall return NSConcreteGlobalBlock; 20037959fee2SJohn McCall } 20047959fee2SJohn McCall 20057959fee2SJohn McCall llvm::Constant *CodeGenModule::getNSConcreteStackBlock() { 20067959fee2SJohn McCall if (NSConcreteStackBlock) 20077959fee2SJohn McCall return NSConcreteStackBlock; 20087959fee2SJohn McCall 20097959fee2SJohn McCall NSConcreteStackBlock = GetOrCreateLLVMGlobal("_NSConcreteStackBlock", 20107959fee2SJohn McCall Int8PtrTy->getPointerTo(), 0); 20117959fee2SJohn McCall configureBlocksRuntimeObject(*this, NSConcreteStackBlock); 20127959fee2SJohn McCall return NSConcreteStackBlock; 20137959fee2SJohn McCall } 2014