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 28351762cdSJohn McCall CGBlockInfo::CGBlockInfo(const BlockExpr *blockExpr, const char *N) 29351762cdSJohn McCall : Name(N), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), 3085915250SJohn McCall HasCXXObject(false), UsesStret(false), StructureType(0), Block(blockExpr) { 319d42f0f1SJohn McCall 329d42f0f1SJohn McCall // Skip asm prefix, if any. 339d42f0f1SJohn McCall if (Name && Name[0] == '\01') 349d42f0f1SJohn McCall ++Name; 359d42f0f1SJohn McCall } 369d42f0f1SJohn McCall 37f9b056b0SJohn McCall // Anchor the vtable to this translation unit. 38f9b056b0SJohn McCall CodeGenModule::ByrefHelpers::~ByrefHelpers() {} 39f9b056b0SJohn McCall 40351762cdSJohn McCall /// Build the given block as a global block. 41351762cdSJohn McCall static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, 42351762cdSJohn McCall const CGBlockInfo &blockInfo, 43351762cdSJohn McCall llvm::Constant *blockFn); 449d42f0f1SJohn McCall 45351762cdSJohn McCall /// Build the helper function to copy a block. 46351762cdSJohn McCall static llvm::Constant *buildCopyHelper(CodeGenModule &CGM, 47351762cdSJohn McCall const CGBlockInfo &blockInfo) { 48351762cdSJohn McCall return CodeGenFunction(CGM).GenerateCopyHelperFunction(blockInfo); 49351762cdSJohn McCall } 50351762cdSJohn McCall 51351762cdSJohn McCall /// Build the helper function to dipose of a block. 52351762cdSJohn McCall static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM, 53351762cdSJohn McCall const CGBlockInfo &blockInfo) { 54351762cdSJohn McCall return CodeGenFunction(CGM).GenerateDestroyHelperFunction(blockInfo); 55351762cdSJohn McCall } 56351762cdSJohn McCall 57351762cdSJohn McCall /// Build the block descriptor constant for a block. 58351762cdSJohn McCall static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM, 59351762cdSJohn McCall const CGBlockInfo &blockInfo) { 60351762cdSJohn McCall ASTContext &C = CGM.getContext(); 61351762cdSJohn McCall 62351762cdSJohn McCall const llvm::Type *ulong = CGM.getTypes().ConvertType(C.UnsignedLongTy); 63351762cdSJohn McCall const llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy); 64351762cdSJohn McCall 65351762cdSJohn McCall llvm::SmallVector<llvm::Constant*, 6> elements; 6685284bacSMike Stump 6785284bacSMike Stump // reserved 68351762cdSJohn McCall elements.push_back(llvm::ConstantInt::get(ulong, 0)); 6985284bacSMike Stump 7085284bacSMike Stump // Size 712ac40a9fSMike Stump // FIXME: What is the right way to say this doesn't fit? We should give 722ac40a9fSMike Stump // a user diagnostic in that case. Better fix would be to change the 732ac40a9fSMike Stump // API to size_t. 74351762cdSJohn McCall elements.push_back(llvm::ConstantInt::get(ulong, 75351762cdSJohn McCall blockInfo.BlockSize.getQuantity())); 7685284bacSMike Stump 77351762cdSJohn McCall // Optional copy/dispose helpers. 78351762cdSJohn McCall if (blockInfo.NeedsCopyDispose) { 7985284bacSMike Stump // copy_func_helper_decl 80351762cdSJohn McCall elements.push_back(buildCopyHelper(CGM, blockInfo)); 8185284bacSMike Stump 8285284bacSMike Stump // destroy_func_decl 83351762cdSJohn McCall elements.push_back(buildDisposeHelper(CGM, blockInfo)); 8485284bacSMike Stump } 8585284bacSMike Stump 86351762cdSJohn McCall // Signature. Mandatory ObjC-style method descriptor @encode sequence. 87351762cdSJohn McCall std::string typeAtEncoding = 88351762cdSJohn McCall CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr()); 89351762cdSJohn McCall elements.push_back(llvm::ConstantExpr::getBitCast( 90351762cdSJohn McCall CGM.GetAddrOfConstantCString(typeAtEncoding), i8p)); 91fc83aa04SBlaine Garst 92351762cdSJohn McCall // GC layout. 93351762cdSJohn McCall if (C.getLangOptions().ObjC1) 94351762cdSJohn McCall elements.push_back(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo)); 95351762cdSJohn McCall else 96351762cdSJohn McCall elements.push_back(llvm::Constant::getNullValue(i8p)); 97fc83aa04SBlaine Garst 98351762cdSJohn McCall llvm::Constant *init = 99351762cdSJohn McCall llvm::ConstantStruct::get(CGM.getLLVMContext(), elements.data(), 100351762cdSJohn McCall elements.size(), false); 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' 169351762cdSJohn McCall const llvm::Type *Type; 17085284bacSMike Stump 171351762cdSJohn McCall BlockLayoutChunk(CharUnits align, CharUnits size, 172351762cdSJohn McCall const BlockDecl::Capture *capture, 173351762cdSJohn McCall const 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, 2489dc0db21SJohn McCall llvm::SmallVectorImpl<const 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()); 268351762cdSJohn McCall const llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy); 269351762cdSJohn McCall const 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 2859dc0db21SJohn McCall llvm::SmallVector<const 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. 296351762cdSJohn McCall llvm::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 ; 307*938f40b5SRichard Smith QualType thisType; 308*938f40b5SRichard Smith if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) 309*938f40b5SRichard Smith thisType = C.getPointerType(C.getRecordType(RD)); 310*938f40b5SRichard Smith else 311*938f40b5SRichard Smith thisType = cast<CXXMethodDecl>(DC)->getThisType(C); 312351762cdSJohn McCall 313351762cdSJohn McCall const 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 333351762cdSJohn McCall const 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 350351762cdSJohn McCall // Block pointers require copy/dispose. 351351762cdSJohn McCall if (variable->getType()->isBlockPointerType()) { 352351762cdSJohn McCall info.NeedsCopyDispose = true; 353351762cdSJohn McCall 354351762cdSJohn McCall // So do Objective-C pointers. 355351762cdSJohn McCall } else if (variable->getType()->isObjCObjectPointerType() || 356351762cdSJohn McCall C.isObjCNSObjectType(variable->getType())) { 357351762cdSJohn McCall info.NeedsCopyDispose = true; 358351762cdSJohn McCall 359351762cdSJohn McCall // So do types that require non-trivial copy construction. 360351762cdSJohn McCall } else if (ci->hasCopyExpr()) { 361351762cdSJohn McCall info.NeedsCopyDispose = true; 362351762cdSJohn McCall info.HasCXXObject = true; 363351762cdSJohn McCall 364351762cdSJohn McCall // And so do types with destructors. 365351762cdSJohn McCall } else if (CGM.getLangOptions().CPlusPlus) { 366351762cdSJohn McCall if (const CXXRecordDecl *record = 367351762cdSJohn McCall variable->getType()->getAsCXXRecordDecl()) { 368351762cdSJohn McCall if (!record->hasTrivialDestructor()) { 369351762cdSJohn McCall info.HasCXXObject = true; 370351762cdSJohn McCall info.NeedsCopyDispose = true; 371351762cdSJohn McCall } 372351762cdSJohn McCall } 373351762cdSJohn McCall } 374351762cdSJohn McCall 375351762cdSJohn McCall CharUnits size = C.getTypeSizeInChars(variable->getType()); 376351762cdSJohn McCall CharUnits align = C.getDeclAlign(variable); 377351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, align); 378351762cdSJohn McCall 379351762cdSJohn McCall const llvm::Type *llvmType = 380351762cdSJohn McCall CGM.getTypes().ConvertTypeForMem(variable->getType()); 381351762cdSJohn McCall 382351762cdSJohn McCall layout.push_back(BlockLayoutChunk(align, size, &*ci, llvmType)); 383351762cdSJohn McCall } 384351762cdSJohn McCall 385351762cdSJohn McCall // If that was everything, we're done here. 386351762cdSJohn McCall if (layout.empty()) { 387351762cdSJohn McCall info.StructureType = 388351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 389351762cdSJohn McCall info.CanBeGlobal = true; 390351762cdSJohn McCall return; 391351762cdSJohn McCall } 392351762cdSJohn McCall 393351762cdSJohn McCall // Sort the layout by alignment. We have to use a stable sort here 394351762cdSJohn McCall // to get reproducible results. There should probably be an 395351762cdSJohn McCall // llvm::array_pod_stable_sort. 396351762cdSJohn McCall std::stable_sort(layout.begin(), layout.end()); 397351762cdSJohn McCall 398351762cdSJohn McCall CharUnits &blockSize = info.BlockSize; 399351762cdSJohn McCall info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign); 400351762cdSJohn McCall 401351762cdSJohn McCall // Assuming that the first byte in the header is maximally aligned, 402351762cdSJohn McCall // get the alignment of the first byte following the header. 403351762cdSJohn McCall CharUnits endAlign = getLowBit(blockSize); 404351762cdSJohn McCall 405351762cdSJohn McCall // If the end of the header isn't satisfactorily aligned for the 406351762cdSJohn McCall // maximum thing, look for things that are okay with the header-end 407351762cdSJohn McCall // alignment, and keep appending them until we get something that's 408351762cdSJohn McCall // aligned right. This algorithm is only guaranteed optimal if 409351762cdSJohn McCall // that condition is satisfied at some point; otherwise we can get 410351762cdSJohn McCall // things like: 411351762cdSJohn McCall // header // next byte has alignment 4 412351762cdSJohn McCall // something_with_size_5; // next byte has alignment 1 413351762cdSJohn McCall // something_with_alignment_8; 414351762cdSJohn McCall // which has 7 bytes of padding, as opposed to the naive solution 415351762cdSJohn McCall // which might have less (?). 416351762cdSJohn McCall if (endAlign < maxFieldAlign) { 417351762cdSJohn McCall llvm::SmallVectorImpl<BlockLayoutChunk>::iterator 418351762cdSJohn McCall li = layout.begin() + 1, le = layout.end(); 419351762cdSJohn McCall 420351762cdSJohn McCall // Look for something that the header end is already 421351762cdSJohn McCall // satisfactorily aligned for. 422351762cdSJohn McCall for (; li != le && endAlign < li->Alignment; ++li) 423351762cdSJohn McCall ; 424351762cdSJohn McCall 425351762cdSJohn McCall // If we found something that's naturally aligned for the end of 426351762cdSJohn McCall // the header, keep adding things... 427351762cdSJohn McCall if (li != le) { 428351762cdSJohn McCall llvm::SmallVectorImpl<BlockLayoutChunk>::iterator first = li; 429351762cdSJohn McCall for (; li != le; ++li) { 430351762cdSJohn McCall assert(endAlign >= li->Alignment); 431351762cdSJohn McCall 432351762cdSJohn McCall li->setIndex(info, elementTypes.size()); 433351762cdSJohn McCall elementTypes.push_back(li->Type); 434351762cdSJohn McCall blockSize += li->Size; 435351762cdSJohn McCall endAlign = getLowBit(blockSize); 436351762cdSJohn McCall 437351762cdSJohn McCall // ...until we get to the alignment of the maximum field. 438351762cdSJohn McCall if (endAlign >= maxFieldAlign) 439351762cdSJohn McCall break; 440351762cdSJohn McCall } 441351762cdSJohn McCall 442351762cdSJohn McCall // Don't re-append everything we just appended. 443351762cdSJohn McCall layout.erase(first, li); 444351762cdSJohn McCall } 445351762cdSJohn McCall } 446351762cdSJohn McCall 447351762cdSJohn McCall // At this point, we just have to add padding if the end align still 448351762cdSJohn McCall // isn't aligned right. 449351762cdSJohn McCall if (endAlign < maxFieldAlign) { 450351762cdSJohn McCall CharUnits padding = maxFieldAlign - endAlign; 451351762cdSJohn McCall 452e3dc1707SJohn McCall elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty, 453e3dc1707SJohn McCall padding.getQuantity())); 454351762cdSJohn McCall blockSize += padding; 455351762cdSJohn McCall 456351762cdSJohn McCall endAlign = getLowBit(blockSize); 457351762cdSJohn McCall assert(endAlign >= maxFieldAlign); 458351762cdSJohn McCall } 459351762cdSJohn McCall 460351762cdSJohn McCall // Slam everything else on now. This works because they have 461351762cdSJohn McCall // strictly decreasing alignment and we expect that size is always a 462351762cdSJohn McCall // multiple of alignment. 463351762cdSJohn McCall for (llvm::SmallVectorImpl<BlockLayoutChunk>::iterator 464351762cdSJohn McCall li = layout.begin(), le = layout.end(); li != le; ++li) { 465351762cdSJohn McCall assert(endAlign >= li->Alignment); 466351762cdSJohn McCall li->setIndex(info, elementTypes.size()); 467351762cdSJohn McCall elementTypes.push_back(li->Type); 468351762cdSJohn McCall blockSize += li->Size; 469351762cdSJohn McCall endAlign = getLowBit(blockSize); 470351762cdSJohn McCall } 471351762cdSJohn McCall 472351762cdSJohn McCall info.StructureType = 473351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 474351762cdSJohn McCall } 475351762cdSJohn McCall 476351762cdSJohn McCall /// Emit a block literal expression in the current function. 477351762cdSJohn McCall llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { 478351762cdSJohn McCall std::string Name = CurFn->getName(); 479351762cdSJohn McCall CGBlockInfo blockInfo(blockExpr, Name.c_str()); 480351762cdSJohn McCall 481351762cdSJohn McCall // Compute information about the layout, etc., of this block. 482351762cdSJohn McCall computeBlockInfo(CGM, blockInfo); 483351762cdSJohn McCall 484351762cdSJohn McCall // Using that metadata, generate the actual block function. 485351762cdSJohn McCall llvm::Constant *blockFn 486351762cdSJohn McCall = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, blockInfo, 487351762cdSJohn McCall CurFuncDecl, LocalDeclMap); 488e3dc1707SJohn McCall blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); 489351762cdSJohn McCall 490351762cdSJohn McCall // If there is nothing to capture, we can emit this as a global block. 491351762cdSJohn McCall if (blockInfo.CanBeGlobal) 492351762cdSJohn McCall return buildGlobalBlock(CGM, blockInfo, blockFn); 493351762cdSJohn McCall 494351762cdSJohn McCall // Otherwise, we have to emit this as a local block. 495351762cdSJohn McCall 496351762cdSJohn McCall llvm::Constant *isa = CGM.getNSConcreteStackBlock(); 497e3dc1707SJohn McCall isa = llvm::ConstantExpr::getBitCast(isa, VoidPtrTy); 498351762cdSJohn McCall 499351762cdSJohn McCall // Build the block descriptor. 500351762cdSJohn McCall llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo); 501351762cdSJohn McCall 502351762cdSJohn McCall const llvm::Type *intTy = ConvertType(getContext().IntTy); 503351762cdSJohn McCall 504351762cdSJohn McCall llvm::AllocaInst *blockAddr = 505351762cdSJohn McCall CreateTempAlloca(blockInfo.StructureType, "block"); 506351762cdSJohn McCall blockAddr->setAlignment(blockInfo.BlockAlign.getQuantity()); 507351762cdSJohn McCall 508351762cdSJohn McCall // Compute the initial on-stack block flags. 509ad7c5c16SJohn McCall BlockFlags flags = BLOCK_HAS_SIGNATURE; 510351762cdSJohn McCall if (blockInfo.NeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE; 511351762cdSJohn McCall if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ; 51285915250SJohn McCall if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; 513351762cdSJohn McCall 514351762cdSJohn McCall // Initialize the block literal. 515351762cdSJohn McCall Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa")); 516ad7c5c16SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(intTy, flags.getBitMask()), 517351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, 1, "block.flags")); 518351762cdSJohn McCall Builder.CreateStore(llvm::ConstantInt::get(intTy, 0), 519351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, 2, "block.reserved")); 520351762cdSJohn McCall Builder.CreateStore(blockFn, Builder.CreateStructGEP(blockAddr, 3, 521351762cdSJohn McCall "block.invoke")); 522351762cdSJohn McCall Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockAddr, 4, 523351762cdSJohn McCall "block.descriptor")); 524351762cdSJohn McCall 525351762cdSJohn McCall // Finally, capture all the values into the block. 526351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 527351762cdSJohn McCall 528351762cdSJohn McCall // First, 'this'. 529351762cdSJohn McCall if (blockDecl->capturesCXXThis()) { 530351762cdSJohn McCall llvm::Value *addr = Builder.CreateStructGEP(blockAddr, 531351762cdSJohn McCall blockInfo.CXXThisIndex, 532351762cdSJohn McCall "block.captured-this.addr"); 533351762cdSJohn McCall Builder.CreateStore(LoadCXXThis(), addr); 534351762cdSJohn McCall } 535351762cdSJohn McCall 536351762cdSJohn McCall // Next, captured variables. 537351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 538351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 539351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 540351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 541351762cdSJohn McCall 542351762cdSJohn McCall // Ignore constant captures. 543351762cdSJohn McCall if (capture.isConstant()) continue; 544351762cdSJohn McCall 545351762cdSJohn McCall QualType type = variable->getType(); 546351762cdSJohn McCall 547351762cdSJohn McCall // This will be a [[type]]*, except that a byref entry will just be 548351762cdSJohn McCall // an i8**. 549351762cdSJohn McCall llvm::Value *blockField = 550351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, capture.getIndex(), 551351762cdSJohn McCall "block.captured"); 552351762cdSJohn McCall 553351762cdSJohn McCall // Compute the address of the thing we're going to move into the 554351762cdSJohn McCall // block literal. 555351762cdSJohn McCall llvm::Value *src; 556351762cdSJohn McCall if (ci->isNested()) { 557351762cdSJohn McCall // We need to use the capture from the enclosing block. 558351762cdSJohn McCall const CGBlockInfo::Capture &enclosingCapture = 559351762cdSJohn McCall BlockInfo->getCapture(variable); 560351762cdSJohn McCall 561351762cdSJohn McCall // This is a [[type]]*, except that a byref entry wil just be an i8**. 562351762cdSJohn McCall src = Builder.CreateStructGEP(LoadBlockStruct(), 563351762cdSJohn McCall enclosingCapture.getIndex(), 564351762cdSJohn McCall "block.capture.addr"); 565351762cdSJohn McCall } else { 566351762cdSJohn McCall // This is a [[type]]*. 567351762cdSJohn McCall src = LocalDeclMap[variable]; 568351762cdSJohn McCall } 569351762cdSJohn McCall 570351762cdSJohn McCall // For byrefs, we just write the pointer to the byref struct into 571351762cdSJohn McCall // the block field. There's no need to chase the forwarding 572351762cdSJohn McCall // pointer at this point, since we're building something that will 573351762cdSJohn McCall // live a shorter life than the stack byref anyway. 574351762cdSJohn McCall if (ci->isByRef()) { 575e3dc1707SJohn McCall // Get a void* that points to the byref struct. 576351762cdSJohn McCall if (ci->isNested()) 577351762cdSJohn McCall src = Builder.CreateLoad(src, "byref.capture"); 578351762cdSJohn McCall else 579e3dc1707SJohn McCall src = Builder.CreateBitCast(src, VoidPtrTy); 580351762cdSJohn McCall 581e3dc1707SJohn McCall // Write that void* into the capture field. 582351762cdSJohn McCall Builder.CreateStore(src, blockField); 583351762cdSJohn McCall 584351762cdSJohn McCall // If we have a copy constructor, evaluate that into the block field. 585351762cdSJohn McCall } else if (const Expr *copyExpr = ci->getCopyExpr()) { 586351762cdSJohn McCall EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr); 587351762cdSJohn McCall 588351762cdSJohn McCall // If it's a reference variable, copy the reference into the block field. 589351762cdSJohn McCall } else if (type->isReferenceType()) { 590351762cdSJohn McCall Builder.CreateStore(Builder.CreateLoad(src, "ref.val"), blockField); 591351762cdSJohn McCall 592351762cdSJohn McCall // Otherwise, fake up a POD copy into the block field. 593351762cdSJohn McCall } else { 59493be3f75SJohn McCall // We use one of these or the other depending on whether the 59593be3f75SJohn McCall // reference is nested. 59693be3f75SJohn McCall DeclRefExpr notNested(const_cast<VarDecl*>(variable), type, VK_LValue, 597351762cdSJohn McCall SourceLocation()); 59893be3f75SJohn McCall BlockDeclRefExpr nested(const_cast<VarDecl*>(variable), type, 59993be3f75SJohn McCall VK_LValue, SourceLocation(), /*byref*/ false); 60093be3f75SJohn McCall 60193be3f75SJohn McCall Expr *declRef = 60293be3f75SJohn McCall (ci->isNested() ? static_cast<Expr*>(&nested) : ¬Nested); 60393be3f75SJohn McCall 604351762cdSJohn McCall ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue, 60593be3f75SJohn McCall declRef, VK_RValue); 6065c8f6c47SJohn McCall EmitExprAsInit(&l2r, variable, blockField, 6075c8f6c47SJohn McCall getContext().getDeclAlign(variable), 6085c8f6c47SJohn McCall /*captured by init*/ false); 609351762cdSJohn McCall } 610351762cdSJohn McCall 611351762cdSJohn McCall // Push a destructor if necessary. The semantics for when this 612351762cdSJohn McCall // actually gets run are really obscure. 613351762cdSJohn McCall if (!ci->isByRef() && CGM.getLangOptions().CPlusPlus) 614351762cdSJohn McCall PushDestructorCleanup(type, blockField); 615351762cdSJohn McCall } 616351762cdSJohn McCall 617351762cdSJohn McCall // Cast to the converted block-pointer type, which happens (somewhat 618351762cdSJohn McCall // unfortunately) to be a pointer to function type. 619351762cdSJohn McCall llvm::Value *result = 620351762cdSJohn McCall Builder.CreateBitCast(blockAddr, 621351762cdSJohn McCall ConvertType(blockInfo.getBlockExpr()->getType())); 6223882ace2SJohn McCall 623351762cdSJohn McCall return result; 624b750d928SMike Stump } 62585284bacSMike Stump 62685284bacSMike Stump 627ad7c5c16SJohn McCall const llvm::Type *CodeGenModule::getBlockDescriptorType() { 628650c932dSMike Stump if (BlockDescriptorType) 629650c932dSMike Stump return BlockDescriptorType; 6302437cbfaSAnders Carlsson 6312437cbfaSAnders Carlsson const llvm::Type *UnsignedLongTy = 632650c932dSMike Stump getTypes().ConvertType(getContext().UnsignedLongTy); 6332437cbfaSAnders Carlsson 6342437cbfaSAnders Carlsson // struct __block_descriptor { 6352437cbfaSAnders Carlsson // unsigned long reserved; 6362437cbfaSAnders Carlsson // unsigned long block_size; 637fc83aa04SBlaine Garst // 638fc83aa04SBlaine Garst // // later, the following will be added 639fc83aa04SBlaine Garst // 640fc83aa04SBlaine Garst // struct { 641fc83aa04SBlaine Garst // void (*copyHelper)(); 642fc83aa04SBlaine Garst // void (*copyHelper)(); 643fc83aa04SBlaine Garst // } helpers; // !!! optional 644fc83aa04SBlaine Garst // 645fc83aa04SBlaine Garst // const char *signature; // the block signature 646fc83aa04SBlaine Garst // const char *layout; // reserved 6472437cbfaSAnders Carlsson // }; 648758428f4SOwen Anderson BlockDescriptorType = llvm::StructType::get(UnsignedLongTy->getContext(), 649758428f4SOwen Anderson UnsignedLongTy, 6502437cbfaSAnders Carlsson UnsignedLongTy, 6512437cbfaSAnders Carlsson NULL); 6522437cbfaSAnders Carlsson 653650c932dSMike Stump getModule().addTypeName("struct.__block_descriptor", 654650c932dSMike Stump BlockDescriptorType); 6552437cbfaSAnders Carlsson 656351762cdSJohn McCall // Now form a pointer to that. 657351762cdSJohn McCall BlockDescriptorType = llvm::PointerType::getUnqual(BlockDescriptorType); 658650c932dSMike Stump return BlockDescriptorType; 6592437cbfaSAnders Carlsson } 6602437cbfaSAnders Carlsson 661ad7c5c16SJohn McCall const llvm::Type *CodeGenModule::getGenericBlockLiteralType() { 662005c9a62SMike Stump if (GenericBlockLiteralType) 663005c9a62SMike Stump return GenericBlockLiteralType; 6642437cbfaSAnders Carlsson 665351762cdSJohn McCall const llvm::Type *BlockDescPtrTy = getBlockDescriptorType(); 6662437cbfaSAnders Carlsson 6672437cbfaSAnders Carlsson // struct __block_literal_generic { 6685d2534adSMike Stump // void *__isa; 6695d2534adSMike Stump // int __flags; 6705d2534adSMike Stump // int __reserved; 6715d2534adSMike Stump // void (*__invoke)(void *); 6725d2534adSMike Stump // struct __block_descriptor *__descriptor; 6732437cbfaSAnders Carlsson // }; 674e3dc1707SJohn McCall GenericBlockLiteralType = llvm::StructType::get(getLLVMContext(), 675e3dc1707SJohn McCall VoidPtrTy, 67692bbd6d4SMike Stump IntTy, 67792bbd6d4SMike Stump IntTy, 678e3dc1707SJohn McCall VoidPtrTy, 6792437cbfaSAnders Carlsson BlockDescPtrTy, 6802437cbfaSAnders Carlsson NULL); 6812437cbfaSAnders Carlsson 682005c9a62SMike Stump getModule().addTypeName("struct.__block_literal_generic", 683005c9a62SMike Stump GenericBlockLiteralType); 6842437cbfaSAnders Carlsson 685005c9a62SMike Stump return GenericBlockLiteralType; 6862437cbfaSAnders Carlsson } 6872437cbfaSAnders Carlsson 6885d2534adSMike Stump 689bfb3671bSAnders Carlsson RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E, 690bfb3671bSAnders Carlsson ReturnValueSlot ReturnValue) { 6912437cbfaSAnders Carlsson const BlockPointerType *BPT = 692c23c7e6aSTed Kremenek E->getCallee()->getType()->getAs<BlockPointerType>(); 6932437cbfaSAnders Carlsson 6942437cbfaSAnders Carlsson llvm::Value *Callee = EmitScalarExpr(E->getCallee()); 6952437cbfaSAnders Carlsson 6962437cbfaSAnders Carlsson // Get a pointer to the generic block literal. 6972437cbfaSAnders Carlsson const llvm::Type *BlockLiteralTy = 6989793f0e4SOwen Anderson llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType()); 6992437cbfaSAnders Carlsson 7002437cbfaSAnders Carlsson // Bitcast the callee to a block literal. 7012437cbfaSAnders Carlsson llvm::Value *BlockLiteral = 7022437cbfaSAnders Carlsson Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal"); 7032437cbfaSAnders Carlsson 7042437cbfaSAnders Carlsson // Get the function pointer from the literal. 7052437cbfaSAnders Carlsson llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp"); 7062437cbfaSAnders Carlsson 707e3dc1707SJohn McCall BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy, "tmp"); 7082437cbfaSAnders Carlsson 7092437cbfaSAnders Carlsson // Add the block literal. 7102437cbfaSAnders Carlsson CallArgList Args; 7119dc0db21SJohn McCall Args.add(RValue::get(BlockLiteral), getContext().VoidPtrTy); 7122437cbfaSAnders Carlsson 713479e6fc7SAnders Carlsson QualType FnType = BPT->getPointeeType(); 714479e6fc7SAnders Carlsson 7152437cbfaSAnders Carlsson // And the rest of the arguments. 7169dd450bbSJohn McCall EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), 717479e6fc7SAnders Carlsson E->arg_begin(), E->arg_end()); 7182437cbfaSAnders Carlsson 7195f50c651SAnders Carlsson // Load the function. 720c76493a6SDaniel Dunbar llvm::Value *Func = Builder.CreateLoad(FuncPtr, "tmp"); 7215f50c651SAnders Carlsson 72285915250SJohn McCall const FunctionType *FuncTy = FnType->castAs<FunctionType>(); 723ab26cfa5SJohn McCall QualType ResultType = FuncTy->getResultType(); 724a60cbcdfSAnders Carlsson 725a60cbcdfSAnders Carlsson const CGFunctionInfo &FnInfo = 726c50c27ccSRafael Espindola CGM.getTypes().getFunctionInfo(ResultType, Args, 727c50c27ccSRafael Espindola FuncTy->getExtInfo()); 7285f50c651SAnders Carlsson 7295f50c651SAnders Carlsson // Cast the function pointer to the right type. 7305f50c651SAnders Carlsson const llvm::Type *BlockFTy = 731a60cbcdfSAnders Carlsson CGM.getTypes().GetFunctionType(FnInfo, false); 7325f50c651SAnders Carlsson 7339793f0e4SOwen Anderson const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); 7345f50c651SAnders Carlsson Func = Builder.CreateBitCast(Func, BlockFTyPtr); 7355f50c651SAnders Carlsson 7362437cbfaSAnders Carlsson // And call the block. 737bfb3671bSAnders Carlsson return EmitCall(FnInfo, Func, ReturnValue, Args); 7382437cbfaSAnders Carlsson } 7396a60fa24SAnders Carlsson 740351762cdSJohn McCall llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable, 741351762cdSJohn McCall bool isByRef) { 742351762cdSJohn McCall assert(BlockInfo && "evaluating block ref without block information?"); 743351762cdSJohn McCall const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable); 74487fe5d56SJohn McCall 745351762cdSJohn McCall // Handle constant captures. 746351762cdSJohn McCall if (capture.isConstant()) return LocalDeclMap[variable]; 74787fe5d56SJohn McCall 748351762cdSJohn McCall llvm::Value *addr = 749351762cdSJohn McCall Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(), 750351762cdSJohn McCall "block.capture.addr"); 751351762cdSJohn McCall 752351762cdSJohn McCall if (isByRef) { 753351762cdSJohn McCall // addr should be a void** right now. Load, then cast the result 754351762cdSJohn McCall // to byref*. 755351762cdSJohn McCall 756351762cdSJohn McCall addr = Builder.CreateLoad(addr); 757351762cdSJohn McCall const llvm::PointerType *byrefPointerType 758351762cdSJohn McCall = llvm::PointerType::get(BuildByRefType(variable), 0); 759351762cdSJohn McCall addr = Builder.CreateBitCast(addr, byrefPointerType, 760351762cdSJohn McCall "byref.addr"); 761351762cdSJohn McCall 762351762cdSJohn McCall // Follow the forwarding pointer. 763351762cdSJohn McCall addr = Builder.CreateStructGEP(addr, 1, "byref.forwarding"); 764351762cdSJohn McCall addr = Builder.CreateLoad(addr, "byref.addr.forwarded"); 765351762cdSJohn McCall 766351762cdSJohn McCall // Cast back to byref* and GEP over to the actual object. 767351762cdSJohn McCall addr = Builder.CreateBitCast(addr, byrefPointerType); 768351762cdSJohn McCall addr = Builder.CreateStructGEP(addr, getByRefValueLLVMField(variable), 769351762cdSJohn McCall variable->getNameAsString()); 77087fe5d56SJohn McCall } 77187fe5d56SJohn McCall 772351762cdSJohn McCall if (variable->getType()->isReferenceType()) 773351762cdSJohn McCall addr = Builder.CreateLoad(addr, "ref.tmp"); 7740168f4b2SAnders Carlsson 775351762cdSJohn McCall return addr; 77697d01d50SMike Stump } 77797d01d50SMike Stump 7782d5a2878SMike Stump llvm::Constant * 779ad7c5c16SJohn McCall CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr, 780351762cdSJohn McCall const char *name) { 781351762cdSJohn McCall CGBlockInfo blockInfo(blockExpr, name); 7826a60fa24SAnders Carlsson 783351762cdSJohn McCall // Compute information about the layout, etc., of this block. 784ad7c5c16SJohn McCall computeBlockInfo(*this, blockInfo); 7856a60fa24SAnders Carlsson 786351762cdSJohn McCall // Using that metadata, generate the actual block function. 787351762cdSJohn McCall llvm::Constant *blockFn; 788351762cdSJohn McCall { 7895469f29aSMike Stump llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap; 790ad7c5c16SJohn McCall blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(), 791351762cdSJohn McCall blockInfo, 792351762cdSJohn McCall 0, LocalDeclMap); 793351762cdSJohn McCall } 794e3dc1707SJohn McCall blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); 7956a60fa24SAnders Carlsson 796ad7c5c16SJohn McCall return buildGlobalBlock(*this, blockInfo, blockFn); 7976a60fa24SAnders Carlsson } 7986a60fa24SAnders Carlsson 799351762cdSJohn McCall static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, 800351762cdSJohn McCall const CGBlockInfo &blockInfo, 801351762cdSJohn McCall llvm::Constant *blockFn) { 802351762cdSJohn McCall assert(blockInfo.CanBeGlobal); 803351762cdSJohn McCall 804351762cdSJohn McCall // Generate the constants for the block literal initializer. 805351762cdSJohn McCall llvm::Constant *fields[BlockHeaderSize]; 806351762cdSJohn McCall 807351762cdSJohn McCall // isa 808351762cdSJohn McCall fields[0] = CGM.getNSConcreteGlobalBlock(); 809351762cdSJohn McCall 810351762cdSJohn McCall // __flags 81185915250SJohn McCall BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE; 81285915250SJohn McCall if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; 81385915250SJohn McCall 814e3dc1707SJohn McCall fields[1] = llvm::ConstantInt::get(CGM.IntTy, flags.getBitMask()); 815351762cdSJohn McCall 816351762cdSJohn McCall // Reserved 817e3dc1707SJohn McCall fields[2] = llvm::Constant::getNullValue(CGM.IntTy); 818351762cdSJohn McCall 819351762cdSJohn McCall // Function 820351762cdSJohn McCall fields[3] = blockFn; 821351762cdSJohn McCall 822351762cdSJohn McCall // Descriptor 823351762cdSJohn McCall fields[4] = buildBlockDescriptor(CGM, blockInfo); 824351762cdSJohn McCall 825351762cdSJohn McCall llvm::Constant *init = 826351762cdSJohn McCall llvm::ConstantStruct::get(CGM.getLLVMContext(), fields, BlockHeaderSize, 827351762cdSJohn McCall /*packed*/ false); 828351762cdSJohn McCall 829351762cdSJohn McCall llvm::GlobalVariable *literal = 830351762cdSJohn McCall new llvm::GlobalVariable(CGM.getModule(), 831351762cdSJohn McCall init->getType(), 832351762cdSJohn McCall /*constant*/ true, 833351762cdSJohn McCall llvm::GlobalVariable::InternalLinkage, 834351762cdSJohn McCall init, 835351762cdSJohn McCall "__block_literal_global"); 836351762cdSJohn McCall literal->setAlignment(blockInfo.BlockAlign.getQuantity()); 837351762cdSJohn McCall 838351762cdSJohn McCall // Return a constant of the appropriately-casted type. 839351762cdSJohn McCall const llvm::Type *requiredType = 840351762cdSJohn McCall CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType()); 841351762cdSJohn McCall return llvm::ConstantExpr::getBitCast(literal, requiredType); 842cb2fbcb0SMike Stump } 843cb2fbcb0SMike Stump 8444446dcf0SMike Stump llvm::Function * 845351762cdSJohn McCall CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, 846351762cdSJohn McCall const CGBlockInfo &blockInfo, 847351762cdSJohn McCall const Decl *outerFnDecl, 848351762cdSJohn McCall const DeclMapTy &ldm) { 849351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 8509074ed8cSDevang Patel 8516e40c615SDevang Patel // Check if we should generate debug info for this block function. 8526e40c615SDevang Patel if (CGM.getModuleDebugInfo()) 8536e40c615SDevang Patel DebugInfo = CGM.getModuleDebugInfo(); 8546e40c615SDevang Patel 855351762cdSJohn McCall BlockInfo = &blockInfo; 8569074ed8cSDevang Patel 8575469f29aSMike Stump // Arrange for local static and local extern declarations to appear 858351762cdSJohn McCall // to be local to this function as well, in case they're directly 859351762cdSJohn McCall // referenced in a block. 860351762cdSJohn McCall for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) { 861351762cdSJohn McCall const VarDecl *var = dyn_cast<VarDecl>(i->first); 862351762cdSJohn McCall if (var && !var->hasLocalStorage()) 863351762cdSJohn McCall LocalDeclMap[var] = i->second; 8645469f29aSMike Stump } 8655469f29aSMike Stump 866351762cdSJohn McCall // Begin building the function declaration. 86709a9b6e3SEli Friedman 868351762cdSJohn McCall // Build the argument list. 869351762cdSJohn McCall FunctionArgList args; 8706a60fa24SAnders Carlsson 871351762cdSJohn McCall // The first argument is the block pointer. Just take it as a void* 872351762cdSJohn McCall // and cast it later. 873351762cdSJohn McCall QualType selfTy = getContext().VoidPtrTy; 8747fe9cc1dSMike Stump IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); 875d015328fSMike Stump 876147d021bSJohn McCall ImplicitParamDecl selfDecl(const_cast<BlockDecl*>(blockDecl), 877351762cdSJohn McCall SourceLocation(), II, selfTy); 878a738c25fSJohn McCall args.push_back(&selfDecl); 8797fe9cc1dSMike Stump 880351762cdSJohn McCall // Now add the rest of the parameters. 881351762cdSJohn McCall for (BlockDecl::param_const_iterator i = blockDecl->param_begin(), 882351762cdSJohn McCall e = blockDecl->param_end(); i != e; ++i) 883a738c25fSJohn McCall args.push_back(*i); 884afa3c0a8SFariborz Jahanian 885351762cdSJohn McCall // Create the function declaration. 886351762cdSJohn McCall const FunctionProtoType *fnType = 887351762cdSJohn McCall cast<FunctionProtoType>(blockInfo.getBlockExpr()->getFunctionType()); 888351762cdSJohn McCall const CGFunctionInfo &fnInfo = 889351762cdSJohn McCall CGM.getTypes().getFunctionInfo(fnType->getResultType(), args, 890351762cdSJohn McCall fnType->getExtInfo()); 89185915250SJohn McCall if (CGM.ReturnTypeUsesSRet(fnInfo)) 89285915250SJohn McCall blockInfo.UsesStret = true; 89385915250SJohn McCall 894351762cdSJohn McCall const llvm::FunctionType *fnLLVMType = 895351762cdSJohn McCall CGM.getTypes().GetFunctionType(fnInfo, fnType->isVariadic()); 89687fe5d56SJohn McCall 897351762cdSJohn McCall MangleBuffer name; 898351762cdSJohn McCall CGM.getBlockMangledName(GD, name, blockDecl); 899351762cdSJohn McCall llvm::Function *fn = 900351762cdSJohn McCall llvm::Function::Create(fnLLVMType, llvm::GlobalValue::InternalLinkage, 901351762cdSJohn McCall name.getString(), &CGM.getModule()); 902351762cdSJohn McCall CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo); 9036a60fa24SAnders Carlsson 904351762cdSJohn McCall // Begin generating the function. 905a738c25fSJohn McCall StartFunction(blockDecl, fnType->getResultType(), fn, fnInfo, args, 9065f070a51SDevang Patel blockInfo.getBlockExpr()->getBody()->getLocStart()); 907351762cdSJohn McCall CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl 9086a60fa24SAnders Carlsson 909147d021bSJohn McCall // Okay. Undo some of what StartFunction did. 910147d021bSJohn McCall 911147d021bSJohn McCall // Pull the 'self' reference out of the local decl map. 912147d021bSJohn McCall llvm::Value *blockAddr = LocalDeclMap[&selfDecl]; 913147d021bSJohn McCall LocalDeclMap.erase(&selfDecl); 914351762cdSJohn McCall BlockPointer = Builder.CreateBitCast(blockAddr, 915351762cdSJohn McCall blockInfo.StructureType->getPointerTo(), 916351762cdSJohn McCall "block"); 917017460abSMike Stump 91887fe5d56SJohn McCall // If we have a C++ 'this' reference, go ahead and force it into 91987fe5d56SJohn McCall // existence now. 920351762cdSJohn McCall if (blockDecl->capturesCXXThis()) { 921351762cdSJohn McCall llvm::Value *addr = Builder.CreateStructGEP(BlockPointer, 922351762cdSJohn McCall blockInfo.CXXThisIndex, 923351762cdSJohn McCall "block.captured-this"); 924351762cdSJohn McCall CXXThisValue = Builder.CreateLoad(addr, "this"); 92587fe5d56SJohn McCall } 92687fe5d56SJohn McCall 927351762cdSJohn McCall // LoadObjCSelf() expects there to be an entry for 'self' in LocalDeclMap; 928351762cdSJohn McCall // appease it. 929351762cdSJohn McCall if (const ObjCMethodDecl *method 930351762cdSJohn McCall = dyn_cast_or_null<ObjCMethodDecl>(CurFuncDecl)) { 931351762cdSJohn McCall const VarDecl *self = method->getSelfDecl(); 932351762cdSJohn McCall 933351762cdSJohn McCall // There might not be a capture for 'self', but if there is... 934351762cdSJohn McCall if (blockInfo.Captures.count(self)) { 935351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(self); 936351762cdSJohn McCall llvm::Value *selfAddr = Builder.CreateStructGEP(BlockPointer, 937351762cdSJohn McCall capture.getIndex(), 938351762cdSJohn McCall "block.captured-self"); 939351762cdSJohn McCall LocalDeclMap[self] = selfAddr; 940351762cdSJohn McCall } 941351762cdSJohn McCall } 942351762cdSJohn McCall 943351762cdSJohn McCall // Also force all the constant captures. 944351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 945351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 946351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 947351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 948351762cdSJohn McCall if (!capture.isConstant()) continue; 949351762cdSJohn McCall 950351762cdSJohn McCall unsigned align = getContext().getDeclAlign(variable).getQuantity(); 951351762cdSJohn McCall 952351762cdSJohn McCall llvm::AllocaInst *alloca = 953351762cdSJohn McCall CreateMemTemp(variable->getType(), "block.captured-const"); 954351762cdSJohn McCall alloca->setAlignment(align); 955351762cdSJohn McCall 956351762cdSJohn McCall Builder.CreateStore(capture.getConstant(), alloca, align); 957351762cdSJohn McCall 958351762cdSJohn McCall LocalDeclMap[variable] = alloca; 9599d42f0f1SJohn McCall } 9609d42f0f1SJohn McCall 961017460abSMike Stump // Save a spot to insert the debug information for all the BlockDeclRefDecls. 962017460abSMike Stump llvm::BasicBlock *entry = Builder.GetInsertBlock(); 963017460abSMike Stump llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint(); 964017460abSMike Stump --entry_ptr; 965017460abSMike Stump 966351762cdSJohn McCall EmitStmt(blockDecl->getBody()); 967017460abSMike Stump 9687d69911aSMike Stump // Remember where we were... 9697d69911aSMike Stump llvm::BasicBlock *resume = Builder.GetInsertBlock(); 970017460abSMike Stump 9717d69911aSMike Stump // Go back to the entry. 972017460abSMike Stump ++entry_ptr; 973017460abSMike Stump Builder.SetInsertPoint(entry, entry_ptr); 974017460abSMike Stump 9752e722b91SMike Stump // Emit debug information for all the BlockDeclRefDecls. 97687fe5d56SJohn McCall // FIXME: also for 'this' 977351762cdSJohn McCall if (CGDebugInfo *DI = getDebugInfo()) { 978351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 979351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 980351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 981351762cdSJohn McCall DI->setLocation(variable->getLocation()); 982351762cdSJohn McCall 983351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 984351762cdSJohn McCall if (capture.isConstant()) { 985351762cdSJohn McCall DI->EmitDeclareOfAutoVariable(variable, LocalDeclMap[variable], 986351762cdSJohn McCall Builder); 987351762cdSJohn McCall continue; 988351762cdSJohn McCall } 989351762cdSJohn McCall 990147d021bSJohn McCall DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer, 991351762cdSJohn McCall Builder, blockInfo); 9922e722b91SMike Stump } 9932e722b91SMike Stump } 994351762cdSJohn McCall 9957d69911aSMike Stump // And resume where we left off. 9967d69911aSMike Stump if (resume == 0) 9977d69911aSMike Stump Builder.ClearInsertionPoint(); 9987d69911aSMike Stump else 9997d69911aSMike Stump Builder.SetInsertPoint(resume); 10002e722b91SMike Stump 1001351762cdSJohn McCall FinishFunction(cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc()); 10026a60fa24SAnders Carlsson 1003351762cdSJohn McCall return fn; 10046a60fa24SAnders Carlsson } 10051db7d04bSMike Stump 1006351762cdSJohn McCall /* 1007351762cdSJohn McCall notes.push_back(HelperInfo()); 1008351762cdSJohn McCall HelperInfo ¬e = notes.back(); 1009351762cdSJohn McCall note.index = capture.getIndex(); 1010351762cdSJohn McCall note.RequiresCopying = (ci->hasCopyExpr() || BlockRequiresCopying(type)); 1011351762cdSJohn McCall note.cxxbar_import = ci->getCopyExpr(); 10121db7d04bSMike Stump 1013351762cdSJohn McCall if (ci->isByRef()) { 1014351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_BYREF; 1015351762cdSJohn McCall if (type.isObjCGCWeak()) 1016351762cdSJohn McCall note.flag |= BLOCK_FIELD_IS_WEAK; 1017351762cdSJohn McCall } else if (type->isBlockPointerType()) { 1018351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_BLOCK; 1019351762cdSJohn McCall } else { 1020351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_OBJECT; 10211db7d04bSMike Stump } 1022351762cdSJohn McCall */ 10231db7d04bSMike Stump 102497d01d50SMike Stump 10250c743277SMike Stump 1026351762cdSJohn McCall 1027351762cdSJohn McCall 1028351762cdSJohn McCall llvm::Constant * 1029ad7c5c16SJohn McCall CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { 1030351762cdSJohn McCall ASTContext &C = getContext(); 1031351762cdSJohn McCall 1032351762cdSJohn McCall FunctionArgList args; 1033a738c25fSJohn McCall ImplicitParamDecl dstDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1034a738c25fSJohn McCall args.push_back(&dstDecl); 1035a738c25fSJohn McCall ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1036a738c25fSJohn McCall args.push_back(&srcDecl); 10370c743277SMike Stump 10380c743277SMike Stump const CGFunctionInfo &FI = 1039351762cdSJohn McCall CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo()); 10400c743277SMike Stump 1041351762cdSJohn McCall // FIXME: it would be nice if these were mergeable with things with 1042351762cdSJohn McCall // identical semantics. 1043351762cdSJohn McCall const llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false); 10440c743277SMike Stump 10450c743277SMike Stump llvm::Function *Fn = 10460c743277SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1047d6b28fc6SBenjamin Kramer "__copy_helper_block_", &CGM.getModule()); 10480c743277SMike Stump 10490c743277SMike Stump IdentifierInfo *II 10500c743277SMike Stump = &CGM.getContext().Idents.get("__copy_helper_block_"); 10510c743277SMike Stump 10522a7c2194SDevang Patel // Check if we should generate debug info for this block helper function. 10532a7c2194SDevang Patel if (CGM.getModuleDebugInfo()) 10542a7c2194SDevang Patel DebugInfo = CGM.getModuleDebugInfo(); 10552a7c2194SDevang Patel 1056351762cdSJohn McCall FunctionDecl *FD = FunctionDecl::Create(C, 1057351762cdSJohn McCall C.getTranslationUnitDecl(), 1058dff1930bSAbramo Bagnara SourceLocation(), 1059351762cdSJohn McCall SourceLocation(), II, C.VoidTy, 0, 10608e7d656aSJohn McCall SC_Static, 10618e7d656aSJohn McCall SC_None, 1062c4df4076SDouglas Gregor false, 10630c743277SMike Stump true); 1064a738c25fSJohn McCall StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); 1065aeb0ffd5SMike Stump 1066351762cdSJohn McCall const llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); 106767645930SMike Stump 1068a738c25fSJohn McCall llvm::Value *src = GetAddrOfLocalVar(&srcDecl); 1069ad7c5c16SJohn McCall src = Builder.CreateLoad(src); 1070ad7c5c16SJohn McCall src = Builder.CreateBitCast(src, structPtrTy, "block.source"); 107167645930SMike Stump 1072a738c25fSJohn McCall llvm::Value *dst = GetAddrOfLocalVar(&dstDecl); 1073ad7c5c16SJohn McCall dst = Builder.CreateLoad(dst); 1074ad7c5c16SJohn McCall dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest"); 1075aeb0ffd5SMike Stump 1076351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1077aeb0ffd5SMike Stump 1078351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1079351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1080351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1081351762cdSJohn McCall QualType type = variable->getType(); 1082aeb0ffd5SMike Stump 1083351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1084351762cdSJohn McCall if (capture.isConstant()) continue; 1085351762cdSJohn McCall 1086351762cdSJohn McCall const Expr *copyExpr = ci->getCopyExpr(); 1087351762cdSJohn McCall unsigned flags = 0; 1088351762cdSJohn McCall 1089351762cdSJohn McCall if (copyExpr) { 1090351762cdSJohn McCall assert(!ci->isByRef()); 1091351762cdSJohn McCall // don't bother computing flags 1092351762cdSJohn McCall } else if (ci->isByRef()) { 1093351762cdSJohn McCall flags = BLOCK_FIELD_IS_BYREF; 1094351762cdSJohn McCall if (type.isObjCGCWeak()) flags |= BLOCK_FIELD_IS_WEAK; 1095351762cdSJohn McCall } else if (type->isBlockPointerType()) { 1096351762cdSJohn McCall flags = BLOCK_FIELD_IS_BLOCK; 1097351762cdSJohn McCall } else if (type->isObjCObjectPointerType() || C.isObjCNSObjectType(type)) { 1098351762cdSJohn McCall flags = BLOCK_FIELD_IS_OBJECT; 1099a3e54bd3SFariborz Jahanian } 1100351762cdSJohn McCall 1101351762cdSJohn McCall if (!copyExpr && !flags) continue; 1102351762cdSJohn McCall 1103351762cdSJohn McCall unsigned index = capture.getIndex(); 1104ad7c5c16SJohn McCall llvm::Value *srcField = Builder.CreateStructGEP(src, index); 1105ad7c5c16SJohn McCall llvm::Value *dstField = Builder.CreateStructGEP(dst, index); 1106351762cdSJohn McCall 1107351762cdSJohn McCall // If there's an explicit copy expression, we do that. 1108351762cdSJohn McCall if (copyExpr) { 1109ad7c5c16SJohn McCall EmitSynthesizedCXXCopyCtor(dstField, srcField, copyExpr); 1110351762cdSJohn McCall } else { 1111351762cdSJohn McCall llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); 1112e3dc1707SJohn McCall srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy); 1113e3dc1707SJohn McCall llvm::Value *dstAddr = Builder.CreateBitCast(dstField, VoidPtrTy); 1114351762cdSJohn McCall Builder.CreateCall3(CGM.getBlockObjectAssign(), dstAddr, srcValue, 1115ad7c5c16SJohn McCall llvm::ConstantInt::get(Int32Ty, flags)); 111667645930SMike Stump } 1117e988bdacSFariborz Jahanian } 1118aeb0ffd5SMike Stump 1119ad7c5c16SJohn McCall FinishFunction(); 11200c743277SMike Stump 1121e3dc1707SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); 112297d01d50SMike Stump } 112397d01d50SMike Stump 1124351762cdSJohn McCall llvm::Constant * 1125ad7c5c16SJohn McCall CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { 1126351762cdSJohn McCall ASTContext &C = getContext(); 11270c743277SMike Stump 1128351762cdSJohn McCall FunctionArgList args; 1129a738c25fSJohn McCall ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1130a738c25fSJohn McCall args.push_back(&srcDecl); 11310c743277SMike Stump 11320c743277SMike Stump const CGFunctionInfo &FI = 1133351762cdSJohn McCall CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo()); 11340c743277SMike Stump 1135cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1136cbc2bcafSMike Stump // internal linkage. 1137351762cdSJohn McCall const llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false); 11380c743277SMike Stump 11390c743277SMike Stump llvm::Function *Fn = 11400c743277SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1141d6b28fc6SBenjamin Kramer "__destroy_helper_block_", &CGM.getModule()); 11420c743277SMike Stump 11432a7c2194SDevang Patel // Check if we should generate debug info for this block destroy function. 11442a7c2194SDevang Patel if (CGM.getModuleDebugInfo()) 11452a7c2194SDevang Patel DebugInfo = CGM.getModuleDebugInfo(); 11462a7c2194SDevang Patel 11470c743277SMike Stump IdentifierInfo *II 11480c743277SMike Stump = &CGM.getContext().Idents.get("__destroy_helper_block_"); 11490c743277SMike Stump 1150351762cdSJohn McCall FunctionDecl *FD = FunctionDecl::Create(C, C.getTranslationUnitDecl(), 1151dff1930bSAbramo Bagnara SourceLocation(), 1152351762cdSJohn McCall SourceLocation(), II, C.VoidTy, 0, 11538e7d656aSJohn McCall SC_Static, 11548e7d656aSJohn McCall SC_None, 1155c4df4076SDouglas Gregor false, true); 1156a738c25fSJohn McCall StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); 11576f7d9f87SMike Stump 1158351762cdSJohn McCall const llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); 115967645930SMike Stump 1160a738c25fSJohn McCall llvm::Value *src = GetAddrOfLocalVar(&srcDecl); 1161ad7c5c16SJohn McCall src = Builder.CreateLoad(src); 1162ad7c5c16SJohn McCall src = Builder.CreateBitCast(src, structPtrTy, "block"); 11636f7d9f87SMike Stump 1164351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1165351762cdSJohn McCall 1166ad7c5c16SJohn McCall CodeGenFunction::RunCleanupsScope cleanups(*this); 1167351762cdSJohn McCall 1168351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1169351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1170351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1171351762cdSJohn McCall QualType type = variable->getType(); 1172351762cdSJohn McCall 1173351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1174351762cdSJohn McCall if (capture.isConstant()) continue; 1175351762cdSJohn McCall 1176ad7c5c16SJohn McCall BlockFieldFlags flags; 1177351762cdSJohn McCall const CXXDestructorDecl *dtor = 0; 1178351762cdSJohn McCall 1179351762cdSJohn McCall if (ci->isByRef()) { 1180351762cdSJohn McCall flags = BLOCK_FIELD_IS_BYREF; 1181351762cdSJohn McCall if (type.isObjCGCWeak()) flags |= BLOCK_FIELD_IS_WEAK; 1182351762cdSJohn McCall } else if (type->isBlockPointerType()) { 1183351762cdSJohn McCall flags = BLOCK_FIELD_IS_BLOCK; 1184351762cdSJohn McCall } else if (type->isObjCObjectPointerType() || C.isObjCNSObjectType(type)) { 1185351762cdSJohn McCall flags = BLOCK_FIELD_IS_OBJECT; 1186351762cdSJohn McCall } else if (C.getLangOptions().CPlusPlus) { 1187351762cdSJohn McCall if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) 1188351762cdSJohn McCall if (!record->hasTrivialDestructor()) 1189351762cdSJohn McCall dtor = record->getDestructor(); 1190e988bdacSFariborz Jahanian } 1191351762cdSJohn McCall 1192ad7c5c16SJohn McCall if (!dtor && flags.empty()) continue; 1193351762cdSJohn McCall 1194351762cdSJohn McCall unsigned index = capture.getIndex(); 1195ad7c5c16SJohn McCall llvm::Value *srcField = Builder.CreateStructGEP(src, index); 1196351762cdSJohn McCall 1197351762cdSJohn McCall // If there's an explicit copy expression, we do that. 1198351762cdSJohn McCall if (dtor) { 1199ad7c5c16SJohn McCall PushDestructorCleanup(dtor, srcField); 1200351762cdSJohn McCall 1201351762cdSJohn McCall // Otherwise we call _Block_object_dispose. It wouldn't be too 1202351762cdSJohn McCall // hard to just emit this as a cleanup if we wanted to make sure 1203351762cdSJohn McCall // that things were done in reverse. 1204351762cdSJohn McCall } else { 1205351762cdSJohn McCall llvm::Value *value = Builder.CreateLoad(srcField); 1206e3dc1707SJohn McCall value = Builder.CreateBitCast(value, VoidPtrTy); 1207351762cdSJohn McCall BuildBlockRelease(value, flags); 12086f7d9f87SMike Stump } 12096f7d9f87SMike Stump } 1210351762cdSJohn McCall 1211351762cdSJohn McCall cleanups.ForceCleanup(); 12126f7d9f87SMike Stump 1213ad7c5c16SJohn McCall FinishFunction(); 12140c743277SMike Stump 1215e3dc1707SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); 12160c743277SMike Stump } 12170c743277SMike Stump 1218f9b056b0SJohn McCall namespace { 1219f9b056b0SJohn McCall 1220f9b056b0SJohn McCall /// Emits the copy/dispose helper functions for a __block object of id type. 1221f9b056b0SJohn McCall class ObjectByrefHelpers : public CodeGenModule::ByrefHelpers { 1222f9b056b0SJohn McCall BlockFieldFlags Flags; 1223f9b056b0SJohn McCall 1224f9b056b0SJohn McCall public: 1225f9b056b0SJohn McCall ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags) 1226f9b056b0SJohn McCall : ByrefHelpers(alignment), Flags(flags) {} 1227f9b056b0SJohn McCall 12287c623641SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 12297c623641SJohn McCall llvm::Value *srcField) { 1230f9b056b0SJohn McCall destField = CGF.Builder.CreateBitCast(destField, CGF.VoidPtrTy); 1231f9b056b0SJohn McCall 1232f9b056b0SJohn McCall srcField = CGF.Builder.CreateBitCast(srcField, CGF.VoidPtrPtrTy); 1233f9b056b0SJohn McCall llvm::Value *srcValue = CGF.Builder.CreateLoad(srcField); 1234f9b056b0SJohn McCall 1235f9b056b0SJohn McCall unsigned flags = (Flags | BLOCK_BYREF_CALLER).getBitMask(); 1236f9b056b0SJohn McCall 1237f9b056b0SJohn McCall llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); 1238f9b056b0SJohn McCall llvm::Value *fn = CGF.CGM.getBlockObjectAssign(); 1239f9b056b0SJohn McCall CGF.Builder.CreateCall3(fn, destField, srcValue, flagsVal); 1240f9b056b0SJohn McCall } 1241f9b056b0SJohn McCall 1242f9b056b0SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1243f9b056b0SJohn McCall field = CGF.Builder.CreateBitCast(field, CGF.Int8PtrTy->getPointerTo(0)); 1244f9b056b0SJohn McCall llvm::Value *value = CGF.Builder.CreateLoad(field); 1245f9b056b0SJohn McCall 1246f9b056b0SJohn McCall CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER); 1247f9b056b0SJohn McCall } 1248f9b056b0SJohn McCall 1249f9b056b0SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 1250f9b056b0SJohn McCall id.AddInteger(Flags.getBitMask()); 1251f9b056b0SJohn McCall } 1252f9b056b0SJohn McCall }; 1253f9b056b0SJohn McCall 1254f9b056b0SJohn McCall /// Emits the copy/dispose helpers for a __block variable with a 1255f9b056b0SJohn McCall /// nontrivial copy constructor or destructor. 1256f9b056b0SJohn McCall class CXXByrefHelpers : public CodeGenModule::ByrefHelpers { 1257f9b056b0SJohn McCall QualType VarType; 1258f9b056b0SJohn McCall const Expr *CopyExpr; 1259f9b056b0SJohn McCall 1260f9b056b0SJohn McCall public: 1261f9b056b0SJohn McCall CXXByrefHelpers(CharUnits alignment, QualType type, 1262f9b056b0SJohn McCall const Expr *copyExpr) 1263f9b056b0SJohn McCall : ByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {} 1264f9b056b0SJohn McCall 1265f9b056b0SJohn McCall bool needsCopy() const { return CopyExpr != 0; } 1266f9b056b0SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 1267f9b056b0SJohn McCall llvm::Value *srcField) { 1268f9b056b0SJohn McCall if (!CopyExpr) return; 1269f9b056b0SJohn McCall CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr); 1270f9b056b0SJohn McCall } 1271f9b056b0SJohn McCall 1272f9b056b0SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1273f9b056b0SJohn McCall EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin(); 1274f9b056b0SJohn McCall CGF.PushDestructorCleanup(VarType, field); 1275f9b056b0SJohn McCall CGF.PopCleanupBlocks(cleanupDepth); 1276f9b056b0SJohn McCall } 1277f9b056b0SJohn McCall 1278f9b056b0SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 1279f9b056b0SJohn McCall id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr()); 1280f9b056b0SJohn McCall } 1281f9b056b0SJohn McCall }; 1282f9b056b0SJohn McCall } // end anonymous namespace 1283f9b056b0SJohn McCall 1284f9b056b0SJohn McCall static llvm::Constant * 1285f9b056b0SJohn McCall generateByrefCopyHelper(CodeGenFunction &CGF, 1286f9b056b0SJohn McCall const llvm::StructType &byrefType, 1287f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &byrefInfo) { 1288f9b056b0SJohn McCall ASTContext &Context = CGF.getContext(); 1289f9b056b0SJohn McCall 1290f9b056b0SJohn McCall QualType R = Context.VoidTy; 1291ee2a5ee5SMike Stump 1292a738c25fSJohn McCall FunctionArgList args; 1293f9b056b0SJohn McCall ImplicitParamDecl dst(0, SourceLocation(), 0, Context.VoidPtrTy); 1294a738c25fSJohn McCall args.push_back(&dst); 1295f89230d9SMike Stump 1296f9b056b0SJohn McCall ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); 1297a738c25fSJohn McCall args.push_back(&src); 1298ee2a5ee5SMike Stump 1299ee2a5ee5SMike Stump const CGFunctionInfo &FI = 1300f9b056b0SJohn McCall CGF.CGM.getTypes().getFunctionInfo(R, args, FunctionType::ExtInfo()); 1301ee2a5ee5SMike Stump 1302f9b056b0SJohn McCall CodeGenTypes &Types = CGF.CGM.getTypes(); 1303ee2a5ee5SMike Stump const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); 1304ee2a5ee5SMike Stump 1305cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1306cbc2bcafSMike Stump // internal linkage. 1307ee2a5ee5SMike Stump llvm::Function *Fn = 1308ee2a5ee5SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1309f9b056b0SJohn McCall "__Block_byref_object_copy_", &CGF.CGM.getModule()); 1310ee2a5ee5SMike Stump 1311ee2a5ee5SMike Stump IdentifierInfo *II 1312f9b056b0SJohn McCall = &Context.Idents.get("__Block_byref_object_copy_"); 1313ee2a5ee5SMike Stump 1314f9b056b0SJohn McCall FunctionDecl *FD = FunctionDecl::Create(Context, 1315f9b056b0SJohn McCall Context.getTranslationUnitDecl(), 1316dff1930bSAbramo Bagnara SourceLocation(), 131760ed5604SArgyrios Kyrtzidis SourceLocation(), II, R, 0, 13188e7d656aSJohn McCall SC_Static, 13198e7d656aSJohn McCall SC_None, 1320c4df4076SDouglas Gregor false, true); 1321f9b056b0SJohn McCall CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); 1322f9b056b0SJohn McCall 1323f9b056b0SJohn McCall if (byrefInfo.needsCopy()) { 1324f9b056b0SJohn McCall const llvm::Type *byrefPtrType = byrefType.getPointerTo(0); 1325f89230d9SMike Stump 1326f89230d9SMike Stump // dst->x 1327f9b056b0SJohn McCall llvm::Value *destField = CGF.GetAddrOfLocalVar(&dst); 1328f9b056b0SJohn McCall destField = CGF.Builder.CreateLoad(destField); 1329f9b056b0SJohn McCall destField = CGF.Builder.CreateBitCast(destField, byrefPtrType); 1330f9b056b0SJohn McCall destField = CGF.Builder.CreateStructGEP(destField, 6, "x"); 1331f89230d9SMike Stump 1332f89230d9SMike Stump // src->x 1333f9b056b0SJohn McCall llvm::Value *srcField = CGF.GetAddrOfLocalVar(&src); 1334f9b056b0SJohn McCall srcField = CGF.Builder.CreateLoad(srcField); 1335f9b056b0SJohn McCall srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType); 1336f9b056b0SJohn McCall srcField = CGF.Builder.CreateStructGEP(srcField, 6, "x"); 133750198098SFariborz Jahanian 1338f9b056b0SJohn McCall byrefInfo.emitCopy(CGF, destField, srcField); 133950198098SFariborz Jahanian } 1340f89230d9SMike Stump 1341f9b056b0SJohn McCall CGF.FinishFunction(); 1342ee2a5ee5SMike Stump 1343f9b056b0SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); 1344ee2a5ee5SMike Stump } 1345ee2a5ee5SMike Stump 1346f9b056b0SJohn McCall /// Build the copy helper for a __block variable. 1347f9b056b0SJohn McCall static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM, 1348f9b056b0SJohn McCall const llvm::StructType &byrefType, 1349f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &info) { 1350f9b056b0SJohn McCall CodeGenFunction CGF(CGM); 1351f9b056b0SJohn McCall return generateByrefCopyHelper(CGF, byrefType, info); 1352f9b056b0SJohn McCall } 1353f9b056b0SJohn McCall 1354f9b056b0SJohn McCall /// Generate code for a __block variable's dispose helper. 1355f9b056b0SJohn McCall static llvm::Constant * 1356f9b056b0SJohn McCall generateByrefDisposeHelper(CodeGenFunction &CGF, 1357f9b056b0SJohn McCall const llvm::StructType &byrefType, 1358f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &byrefInfo) { 1359f9b056b0SJohn McCall ASTContext &Context = CGF.getContext(); 1360f9b056b0SJohn McCall QualType R = Context.VoidTy; 1361ee2a5ee5SMike Stump 1362a738c25fSJohn McCall FunctionArgList args; 1363f9b056b0SJohn McCall ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); 1364a738c25fSJohn McCall args.push_back(&src); 1365ee2a5ee5SMike Stump 1366ee2a5ee5SMike Stump const CGFunctionInfo &FI = 1367f9b056b0SJohn McCall CGF.CGM.getTypes().getFunctionInfo(R, args, FunctionType::ExtInfo()); 1368ee2a5ee5SMike Stump 1369f9b056b0SJohn McCall CodeGenTypes &Types = CGF.CGM.getTypes(); 1370ee2a5ee5SMike Stump const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); 1371ee2a5ee5SMike Stump 1372cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1373cbc2bcafSMike Stump // internal linkage. 1374ee2a5ee5SMike Stump llvm::Function *Fn = 1375ee2a5ee5SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 137650198098SFariborz Jahanian "__Block_byref_object_dispose_", 1377f9b056b0SJohn McCall &CGF.CGM.getModule()); 1378ee2a5ee5SMike Stump 1379ee2a5ee5SMike Stump IdentifierInfo *II 1380f9b056b0SJohn McCall = &Context.Idents.get("__Block_byref_object_dispose_"); 1381ee2a5ee5SMike Stump 1382f9b056b0SJohn McCall FunctionDecl *FD = FunctionDecl::Create(Context, 1383f9b056b0SJohn McCall Context.getTranslationUnitDecl(), 1384dff1930bSAbramo Bagnara SourceLocation(), 138560ed5604SArgyrios Kyrtzidis SourceLocation(), II, R, 0, 13868e7d656aSJohn McCall SC_Static, 13878e7d656aSJohn McCall SC_None, 1388c4df4076SDouglas Gregor false, true); 1389f9b056b0SJohn McCall CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); 1390fbe25dd1SMike Stump 1391f9b056b0SJohn McCall if (byrefInfo.needsDispose()) { 1392f9b056b0SJohn McCall llvm::Value *V = CGF.GetAddrOfLocalVar(&src); 1393f9b056b0SJohn McCall V = CGF.Builder.CreateLoad(V); 1394f9b056b0SJohn McCall V = CGF.Builder.CreateBitCast(V, byrefType.getPointerTo(0)); 1395f9b056b0SJohn McCall V = CGF.Builder.CreateStructGEP(V, 6, "x"); 1396ad7c5c16SJohn McCall 1397f9b056b0SJohn McCall byrefInfo.emitDispose(CGF, V); 1398f9b056b0SJohn McCall } 1399ad7c5c16SJohn McCall 1400f9b056b0SJohn McCall CGF.FinishFunction(); 1401f9b056b0SJohn McCall 1402f9b056b0SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); 1403f9b056b0SJohn McCall } 1404f9b056b0SJohn McCall 1405f9b056b0SJohn McCall /// Build the dispose helper for a __block variable. 1406f9b056b0SJohn McCall static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM, 1407f9b056b0SJohn McCall const llvm::StructType &byrefType, 1408f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &info) { 1409f9b056b0SJohn McCall CodeGenFunction CGF(CGM); 1410f9b056b0SJohn McCall return generateByrefDisposeHelper(CGF, byrefType, info); 1411f9b056b0SJohn McCall } 1412f9b056b0SJohn McCall 1413f9b056b0SJohn McCall /// 1414f9b056b0SJohn McCall template <class T> static T *buildByrefHelpers(CodeGenModule &CGM, 1415f9b056b0SJohn McCall const llvm::StructType &byrefTy, 1416f9b056b0SJohn McCall T &byrefInfo) { 1417f9b056b0SJohn McCall // Increase the field's alignment to be at least pointer alignment, 1418f9b056b0SJohn McCall // since the layout of the byref struct will guarantee at least that. 1419f9b056b0SJohn McCall byrefInfo.Alignment = std::max(byrefInfo.Alignment, 1420f9b056b0SJohn McCall CharUnits::fromQuantity(CGM.PointerAlignInBytes)); 1421f9b056b0SJohn McCall 1422f9b056b0SJohn McCall llvm::FoldingSetNodeID id; 1423f9b056b0SJohn McCall byrefInfo.Profile(id); 1424f9b056b0SJohn McCall 1425f9b056b0SJohn McCall void *insertPos; 1426f9b056b0SJohn McCall CodeGenModule::ByrefHelpers *node 1427f9b056b0SJohn McCall = CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos); 1428f9b056b0SJohn McCall if (node) return static_cast<T*>(node); 1429f9b056b0SJohn McCall 1430f9b056b0SJohn McCall byrefInfo.CopyHelper = buildByrefCopyHelper(CGM, byrefTy, byrefInfo); 1431f9b056b0SJohn McCall byrefInfo.DisposeHelper = buildByrefDisposeHelper(CGM, byrefTy, byrefInfo); 1432f9b056b0SJohn McCall 1433f9b056b0SJohn McCall T *copy = new (CGM.getContext()) T(byrefInfo); 1434f9b056b0SJohn McCall CGM.ByrefHelpersCache.InsertNode(copy, insertPos); 1435f9b056b0SJohn McCall return copy; 1436f9b056b0SJohn McCall } 1437f9b056b0SJohn McCall 1438f9b056b0SJohn McCall CodeGenModule::ByrefHelpers * 1439f9b056b0SJohn McCall CodeGenFunction::buildByrefHelpers(const llvm::StructType &byrefType, 1440f9b056b0SJohn McCall const AutoVarEmission &emission) { 1441f9b056b0SJohn McCall const VarDecl &var = *emission.Variable; 1442f9b056b0SJohn McCall QualType type = var.getType(); 1443f9b056b0SJohn McCall 1444f9b056b0SJohn McCall if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) { 1445f9b056b0SJohn McCall const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var); 1446f9b056b0SJohn McCall if (!copyExpr && record->hasTrivialDestructor()) return 0; 1447f9b056b0SJohn McCall 1448f9b056b0SJohn McCall CXXByrefHelpers byrefInfo(emission.Alignment, type, copyExpr); 1449f9b056b0SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 1450f9b056b0SJohn McCall } 1451f9b056b0SJohn McCall 1452f9b056b0SJohn McCall BlockFieldFlags flags; 1453f9b056b0SJohn McCall if (type->isBlockPointerType()) { 1454f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_BLOCK; 1455f9b056b0SJohn McCall } else if (CGM.getContext().isObjCNSObjectType(type) || 1456f9b056b0SJohn McCall type->isObjCObjectPointerType()) { 1457f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_OBJECT; 1458ad7c5c16SJohn McCall } else { 1459f9b056b0SJohn McCall return 0; 1460ee2a5ee5SMike Stump } 1461ee2a5ee5SMike Stump 1462f9b056b0SJohn McCall if (type.isObjCGCWeak()) 1463f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_WEAK; 1464ad7c5c16SJohn McCall 1465f9b056b0SJohn McCall ObjectByrefHelpers byrefInfo(emission.Alignment, flags); 1466f9b056b0SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 1467ee2a5ee5SMike Stump } 1468ee2a5ee5SMike Stump 146973064870SJohn McCall unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const { 147073064870SJohn McCall assert(ByRefValueInfo.count(VD) && "Did not find value!"); 147173064870SJohn McCall 147273064870SJohn McCall return ByRefValueInfo.find(VD)->second.second; 147373064870SJohn McCall } 147473064870SJohn McCall 147573064870SJohn McCall llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr, 147673064870SJohn McCall const VarDecl *V) { 147773064870SJohn McCall llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding"); 147873064870SJohn McCall Loc = Builder.CreateLoad(Loc); 147973064870SJohn McCall Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V), 148073064870SJohn McCall V->getNameAsString()); 148173064870SJohn McCall return Loc; 148273064870SJohn McCall } 148373064870SJohn McCall 148473064870SJohn McCall /// BuildByRefType - This routine changes a __block variable declared as T x 148573064870SJohn McCall /// into: 148673064870SJohn McCall /// 148773064870SJohn McCall /// struct { 148873064870SJohn McCall /// void *__isa; 148973064870SJohn McCall /// void *__forwarding; 149073064870SJohn McCall /// int32_t __flags; 149173064870SJohn McCall /// int32_t __size; 149273064870SJohn McCall /// void *__copy_helper; // only if needed 149373064870SJohn McCall /// void *__destroy_helper; // only if needed 149473064870SJohn McCall /// char padding[X]; // only if needed 149573064870SJohn McCall /// T x; 149673064870SJohn McCall /// } x 149773064870SJohn McCall /// 149873064870SJohn McCall const llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) { 149973064870SJohn McCall std::pair<const llvm::Type *, unsigned> &Info = ByRefValueInfo[D]; 150073064870SJohn McCall if (Info.first) 150173064870SJohn McCall return Info.first; 150273064870SJohn McCall 150373064870SJohn McCall QualType Ty = D->getType(); 150473064870SJohn McCall 15059dc0db21SJohn McCall llvm::SmallVector<const llvm::Type *, 8> types; 150673064870SJohn McCall 150773064870SJohn McCall llvm::PATypeHolder ByRefTypeHolder = llvm::OpaqueType::get(getLLVMContext()); 150873064870SJohn McCall 150973064870SJohn McCall // void *__isa; 15109dc0db21SJohn McCall types.push_back(Int8PtrTy); 151173064870SJohn McCall 151273064870SJohn McCall // void *__forwarding; 15139dc0db21SJohn McCall types.push_back(llvm::PointerType::getUnqual(ByRefTypeHolder)); 151473064870SJohn McCall 151573064870SJohn McCall // int32_t __flags; 15169dc0db21SJohn McCall types.push_back(Int32Ty); 151773064870SJohn McCall 151873064870SJohn McCall // int32_t __size; 15199dc0db21SJohn McCall types.push_back(Int32Ty); 152073064870SJohn McCall 152173064870SJohn McCall bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty); 152273064870SJohn McCall if (HasCopyAndDispose) { 152373064870SJohn McCall /// void *__copy_helper; 15249dc0db21SJohn McCall types.push_back(Int8PtrTy); 152573064870SJohn McCall 152673064870SJohn McCall /// void *__destroy_helper; 15279dc0db21SJohn McCall types.push_back(Int8PtrTy); 152873064870SJohn McCall } 152973064870SJohn McCall 153073064870SJohn McCall bool Packed = false; 153173064870SJohn McCall CharUnits Align = getContext().getDeclAlign(D); 153273064870SJohn McCall if (Align > getContext().toCharUnitsFromBits(Target.getPointerAlign(0))) { 153373064870SJohn McCall // We have to insert padding. 153473064870SJohn McCall 153573064870SJohn McCall // The struct above has 2 32-bit integers. 153673064870SJohn McCall unsigned CurrentOffsetInBytes = 4 * 2; 153773064870SJohn McCall 153873064870SJohn McCall // And either 2 or 4 pointers. 153973064870SJohn McCall CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) * 154073064870SJohn McCall CGM.getTargetData().getTypeAllocSize(Int8PtrTy); 154173064870SJohn McCall 154273064870SJohn McCall // Align the offset. 154373064870SJohn McCall unsigned AlignedOffsetInBytes = 154473064870SJohn McCall llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity()); 154573064870SJohn McCall 154673064870SJohn McCall unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes; 154773064870SJohn McCall if (NumPaddingBytes > 0) { 154873064870SJohn McCall const llvm::Type *Ty = llvm::Type::getInt8Ty(getLLVMContext()); 154973064870SJohn McCall // FIXME: We need a sema error for alignment larger than the minimum of 15509dc0db21SJohn McCall // the maximal stack alignment and the alignment of malloc on the system. 155173064870SJohn McCall if (NumPaddingBytes > 1) 155273064870SJohn McCall Ty = llvm::ArrayType::get(Ty, NumPaddingBytes); 155373064870SJohn McCall 15549dc0db21SJohn McCall types.push_back(Ty); 155573064870SJohn McCall 155673064870SJohn McCall // We want a packed struct. 155773064870SJohn McCall Packed = true; 155873064870SJohn McCall } 155973064870SJohn McCall } 156073064870SJohn McCall 156173064870SJohn McCall // T x; 15629dc0db21SJohn McCall types.push_back(ConvertTypeForMem(Ty)); 156373064870SJohn McCall 15649dc0db21SJohn McCall const llvm::Type *T = llvm::StructType::get(getLLVMContext(), types, Packed); 156573064870SJohn McCall 156673064870SJohn McCall cast<llvm::OpaqueType>(ByRefTypeHolder.get())->refineAbstractTypeTo(T); 156773064870SJohn McCall CGM.getModule().addTypeName("struct.__block_byref_" + D->getNameAsString(), 156873064870SJohn McCall ByRefTypeHolder.get()); 156973064870SJohn McCall 157073064870SJohn McCall Info.first = ByRefTypeHolder.get(); 157173064870SJohn McCall 15729dc0db21SJohn McCall Info.second = types.size() - 1; 157373064870SJohn McCall 157473064870SJohn McCall return Info.first; 157573064870SJohn McCall } 157673064870SJohn McCall 157773064870SJohn McCall /// Initialize the structural components of a __block variable, i.e. 157873064870SJohn McCall /// everything but the actual object. 157973064870SJohn McCall void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { 1580f9b056b0SJohn McCall // Find the address of the local. 1581f9b056b0SJohn McCall llvm::Value *addr = emission.Address; 158273064870SJohn McCall 1583f9b056b0SJohn McCall // That's an alloca of the byref structure type. 1584f9b056b0SJohn McCall const llvm::StructType *byrefType = cast<llvm::StructType>( 1585f9b056b0SJohn McCall cast<llvm::PointerType>(addr->getType())->getElementType()); 1586f9b056b0SJohn McCall 1587f9b056b0SJohn McCall // Build the byref helpers if necessary. This is null if we don't need any. 1588f9b056b0SJohn McCall CodeGenModule::ByrefHelpers *helpers = 1589f9b056b0SJohn McCall buildByrefHelpers(*byrefType, emission); 159073064870SJohn McCall 159173064870SJohn McCall const VarDecl &D = *emission.Variable; 159273064870SJohn McCall QualType type = D.getType(); 159373064870SJohn McCall 1594f9b056b0SJohn McCall llvm::Value *V; 159573064870SJohn McCall 159673064870SJohn McCall // Initialize the 'isa', which is just 0 or 1. 159773064870SJohn McCall int isa = 0; 1598f9b056b0SJohn McCall if (type.isObjCGCWeak()) 159973064870SJohn McCall isa = 1; 160073064870SJohn McCall V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa"); 160173064870SJohn McCall Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa")); 160273064870SJohn McCall 160373064870SJohn McCall // Store the address of the variable into its own forwarding pointer. 160473064870SJohn McCall Builder.CreateStore(addr, 160573064870SJohn McCall Builder.CreateStructGEP(addr, 1, "byref.forwarding")); 160673064870SJohn McCall 160773064870SJohn McCall // Blocks ABI: 160873064870SJohn McCall // c) the flags field is set to either 0 if no helper functions are 160973064870SJohn McCall // needed or BLOCK_HAS_COPY_DISPOSE if they are, 161073064870SJohn McCall BlockFlags flags; 1611f9b056b0SJohn McCall if (helpers) flags |= BLOCK_HAS_COPY_DISPOSE; 161273064870SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()), 161373064870SJohn McCall Builder.CreateStructGEP(addr, 2, "byref.flags")); 161473064870SJohn McCall 1615f9b056b0SJohn McCall CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType); 1616f9b056b0SJohn McCall V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity()); 161773064870SJohn McCall Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size")); 161873064870SJohn McCall 1619f9b056b0SJohn McCall if (helpers) { 162073064870SJohn McCall llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4); 1621f9b056b0SJohn McCall Builder.CreateStore(helpers->CopyHelper, copy_helper); 162273064870SJohn McCall 162373064870SJohn McCall llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5); 1624f9b056b0SJohn McCall Builder.CreateStore(helpers->DisposeHelper, destroy_helper); 162573064870SJohn McCall } 162673064870SJohn McCall } 162773064870SJohn McCall 1628ad7c5c16SJohn McCall void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) { 1629900546d2SDaniel Dunbar llvm::Value *F = CGM.getBlockObjectDispose(); 1630fbe25dd1SMike Stump llvm::Value *N; 1631ad7c5c16SJohn McCall V = Builder.CreateBitCast(V, Int8PtrTy); 1632ad7c5c16SJohn McCall N = llvm::ConstantInt::get(Int32Ty, flags.getBitMask()); 1633626aecc4SMike Stump Builder.CreateCall2(F, V, N); 1634626aecc4SMike Stump } 163573064870SJohn McCall 163673064870SJohn McCall namespace { 163773064870SJohn McCall struct CallBlockRelease : EHScopeStack::Cleanup { 163873064870SJohn McCall llvm::Value *Addr; 163973064870SJohn McCall CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {} 164073064870SJohn McCall 164173064870SJohn McCall void Emit(CodeGenFunction &CGF, bool IsForEH) { 164273064870SJohn McCall CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF); 164373064870SJohn McCall } 164473064870SJohn McCall }; 164573064870SJohn McCall } 164673064870SJohn McCall 164773064870SJohn McCall /// Enter a cleanup to destroy a __block variable. Note that this 164873064870SJohn McCall /// cleanup should be a no-op if the variable hasn't left the stack 164973064870SJohn McCall /// yet; if a cleanup is required for the variable itself, that needs 165073064870SJohn McCall /// to be done externally. 165173064870SJohn McCall void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) { 165273064870SJohn McCall // We don't enter this cleanup if we're in pure-GC mode. 165373064870SJohn McCall if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly) 165473064870SJohn McCall return; 165573064870SJohn McCall 165673064870SJohn McCall EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address); 165773064870SJohn McCall } 1658